Compare commits

...

17 Commits

22 changed files with 545 additions and 55 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.DS_Store
._*
bin
AudiobookRecorder.jar
AudiobookRecorder.dmg
AudiobookRecorder.exe

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "universalJavaApplicationStub"]
path = universalJavaApplicationStub
url = ./universalJavaApplicationStub

View File

@@ -34,4 +34,4 @@ Third party software
* CMU Sphinx: https://github.com/mpatric/mp3agic
* JAVE ffmpeg wrapper: http://www.sauronsoftware.it/projects/jave/
* JTattoo: http://www.sauronsoftware.it/projects/jave/
* Icons from, or based on, Oxygen: https://github.com/KDE/oxygen-icons

View File

@@ -1,3 +1,5 @@
![Application Icon](https://github.com/MajenkoProjects/AudiobookRecorder/raw/master/resources/uk/co/majenko/audiobookrecorder/icons/appIcon.png)
Audiobook Recorder
==================
@@ -24,6 +26,7 @@ From here on much is controlled by key presses.
* Press and hold "R" to record a new phrase - the screen flashes red while it's recording. The phrase is
appended to the currently selected chapter, or to the last chapter if none is selected.
* Press and hold "T" to record a new phrase that is the start of a new paragraph. This adds the "post paragraph" gap to the previous sentence. Otherwise it does the same as "R".
* Press "D" to delete the last phrase you recorded.
* Press "E" to re-record the currently selected phrase.

8
TODO.md Normal file
View File

@@ -0,0 +1,8 @@
ToDo
====
* Merge chapters
* Identify and export 5 minute retail sample
* Identify and export 15 minute checkpoint
* Archive (Zip and delete) audiobooks
* File path browser buttons in options

Binary file not shown.

View File

@@ -1,6 +1,8 @@
<?xml version="1.0"?>
<project name="Audiobook Recorder" default="build">
<taskdef name="jarbundler" classname="com.ultramixer.jarbundler.JarBundler" classpath="ant-libs/jarbundler-2.3.2.jar" />
<target name="clean" description="Clean out the build directories">
<delete dir="bin" />
<delete file="AudiobookRecorder.jar" />
@@ -43,4 +45,46 @@
<chmod perm="0755" file="uecide.jar" />
</target>
<target name="release" depends="macapp">
</target>
<target name="macapp" depends="build">
<mkdir dir="tmp"/>
<jarbundler
name="AudiobookRecorder"
shortname="AudiobookRecorder"
icon="dist/macosx/audiobookrecorder.icns"
stubfile="universalJavaApplicationStub/src/universalJavaApplicationStub"
dir="tmp"
jar="AudiobookRecorder.jar"
mainclass="uk.co.majenko.audiobookrecorder.AudiobookRecorder"
jvmversion="1.7+"
>
</jarbundler>
<symlink link="tmp/Applications" resource="/Applications" overwrite="true" />
<!--copy file="dist/macosx/dmg.icns" tofile="tmp/.VolumeIcon.icns" /-->
<exec executable="genisoimage">
<arg value="-D" />
<arg value="-V" />
<arg value="AudiobookRecorder" />
<arg value="-no-pad" />
<arg value="-r" />
<arg value="-apple" />
<arg value="-o" />
<arg value="AudiobookRecorder.dmg" />
<arg value="-dir-mode" />
<arg value="0755" />
<arg value="-file-mode" />
<arg value="0755" />
<arg value="tmp" />
</exec>
<delete dir="tmp" />
</target>
</project>

BIN
dist/macosx/audiobookrecorder.icns vendored Normal file

Binary file not shown.

BIN
dist/macosx/dmg.icns vendored Normal file

Binary file not shown.

26
installers/linux.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
NAME=AudiobookRecorder
BIN=/usr/bin
DESKTOP=/usr/share/applications
SHARE=/usr/share
ICON=/usr/share/icons
mkdir -p "$BIN"
mkdir -p "$SHARE/$NAME"
cp AudiobookRecorder.jar "$SHARE/$NAME/$NAME.jar"
echo "#!/bin/bash" > "$BIN/$NAME"
echo "java -jar \"$SHARE/$NAME/$NAME.jar\"" >> "$BIN/$NAME"
chmod 755 "$BIN/$NAME"
echo "[Desktop Entry]" > "$DESKTOP/$NAME.desktop"
echo "Version=1.0" >> "$DESKTOP/$NAME.desktop"
echo "Name=$NAME" >> "$DESKTOP/$NAME.desktop"
echo "Exec=$NAME" >> "$DESKTOP/$NAME.desktop"
echo "Icon=$NAME" >> "$DESKTOP/$NAME.desktop"
echo "Categories=Multimedia" >> "$DESKTOP/$NAME.desktop"
cp resources/uk/co/majenko/audiobookrecorder/icons/appIcon.png "$ICON/$NAME.png"

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -464,6 +464,9 @@ public class AudiobookRecorder extends JFrame {
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("R"), "startRecord");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released R"), "stopRecord");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("T"), "startRecordNewPara");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released T"), "stopRecord");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released D"), "deleteLast");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("SPACE"), "startPlayback");
@@ -477,6 +480,12 @@ public class AudiobookRecorder extends JFrame {
startRecording();
}
});
centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return;
startRecordingNewParagraph();
}
});
centralPanel.getActionMap().put("startRerecord", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return;
@@ -512,6 +521,18 @@ public class AudiobookRecorder extends JFrame {
pack();
setVisible(true);
String lastBook = Options.get("path.last-book");
if (lastBook != null && !lastBook.equals("")) {
File f = new File(Options.get("path.storage"), lastBook);
if (f.exists() && f.isDirectory()) {
File x = new File(f, "audiobook.abk");
if (x.exists()) {
loadBookStructure(x);
}
}
}
}
public static void main(String args[]) {
@@ -538,6 +559,9 @@ public class AudiobookRecorder extends JFrame {
prefs.setProperty("book.author", info.getAuthor());
prefs.setProperty("book.genre", info.getGenre());
prefs.setProperty("book.comment", info.getComment());
prefs.setProperty("chapter.audition.name", "Audition");
prefs.setProperty("chapter.audition.pre-gap", Options.get("catenation.pre-chapter"));
prefs.setProperty("chapter.audition.post-gap", Options.get("catenation.post-chapter"));
prefs.setProperty("chapter.open.name", "Opening Credits");
prefs.setProperty("chapter.open.pre-gap", Options.get("catenation.pre-chapter"));
prefs.setProperty("chapter.open.post-gap", Options.get("catenation.post-chapter"));
@@ -573,6 +597,40 @@ public class AudiobookRecorder extends JFrame {
}
}
class JMenuObject2 extends JMenuItem {
Object ob1;
Object ob2;
public JMenuObject2(String p) {
super(p);
ob1 = null;
ob2 = null;
}
public JMenuObject2(String p, Object o1, Object o2) {
super(p);
ob1 = o1;
ob2 = o2;
}
public void setObject1(Object o) {
ob1 = o;
}
public void setObject2(Object o) {
ob2 = o;
}
public Object getObject1() {
return ob1;
}
public Object getObject2() {
return ob2;
}
}
@SuppressWarnings("unchecked")
void treePopup(MouseEvent e) {
int selRow = bookTree.getRowForLocation(e.getX(), e.getY());
@@ -588,6 +646,52 @@ public class AudiobookRecorder extends JFrame {
JPopupMenu menu = new JPopupMenu();
JMenuObject rec = new JMenuObject("Recognise text from audio", s);
JMenu moveMenu = new JMenu("Move sentence to...");
for (Enumeration<Chapter> c = book.children(); c.hasMoreElements();) {
Chapter chp = c.nextElement();
JMenuObject2 m = new JMenuObject2(chp.getName(), s, chp);
m.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject2 ob = (JMenuObject2)e.getSource();
Sentence sentence = (Sentence)ob.getObject1();
Chapter target = (Chapter)ob.getObject2();
bookTreeModel.removeNodeFromParent(sentence);
bookTreeModel.insertNodeInto(sentence, target, target.getChildCount());
}
});
moveMenu.add(m);
}
JMenuObject moveUp = new JMenuObject("Move Up", s);
JMenuObject moveDown = new JMenuObject("Move Down", s);
moveUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource();
Sentence sent = (Sentence)o.getObject();
Chapter chap = (Chapter)sent.getParent();
int pos = bookTreeModel.getIndexOfChild(chap, sent);
if (pos > 0) pos--;
bookTreeModel.removeNodeFromParent(sent);
bookTreeModel.insertNodeInto(sent, chap, pos);
}
});
moveDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource();
Sentence sent = (Sentence)o.getObject();
Chapter chap = (Chapter)sent.getParent();
int pos = bookTreeModel.getIndexOfChild(chap, sent);
if (pos < chap.getChildCount() - 1) pos++;
bookTreeModel.removeNodeFromParent(sent);
bookTreeModel.insertNodeInto(sent, chap, pos);
}
});
JMenuObject ins = new JMenuObject("Insert sentence above", s);
JMenuObject del = new JMenuObject("Delete sentence", s);
@@ -632,6 +736,10 @@ public class AudiobookRecorder extends JFrame {
menu.add(rec);
menu.addSeparator();
menu.add(moveUp);
menu.add(moveDown);
menu.add(moveMenu);
menu.addSeparator();
menu.add(ins);
menu.add(del);
menu.show(bookTree, e.getX(), e.getY());
@@ -641,18 +749,72 @@ public class AudiobookRecorder extends JFrame {
bookTree.setSelectionPath(new TreePath(c.getPath()));
JPopupMenu menu = new JPopupMenu();
JMenuObject ren = new JMenuObject("Rename chapter", c);
JMenuObject peak = new JMenuObject("Auto-trim all (Peak)", c);
JMenuObject moveUp = new JMenuObject("Move Up", c);
JMenuObject moveDown = new JMenuObject("Move Down", c);
ren.addActionListener(new ActionListener() {
int idNumber = s2i(c.getId());
moveUp.setEnabled(idNumber > 0);
moveDown.setEnabled(idNumber > 0);
moveUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource();
Chapter c = (Chapter)o.getObject();
c.renameChapter();
bookTreeModel.reload(c);
Chapter chap = (Chapter)o.getObject();
int pos = bookTreeModel.getIndexOfChild(book, chap);
if (pos > 0) pos--;
int id = s2i(chap.getId());
if (id > 0) {
Chapter prevChap = (Chapter)bookTreeModel.getChild(book, pos);
id = s2i(prevChap.getId());
if (id > 0) {
bookTreeModel.removeNodeFromParent(chap);
bookTreeModel.insertNodeInto(chap, book, pos);
}
}
}
});
moveDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource();
Chapter chap = (Chapter)o.getObject();
int pos = bookTreeModel.getIndexOfChild(book, chap);
pos++;
int id = s2i(chap.getId());
if (id > 0) {
Chapter nextChap = (Chapter)bookTreeModel.getChild(book, pos);
if (nextChap != null) {
id = s2i(nextChap.getId());
if (id > 0) {
bookTreeModel.removeNodeFromParent(chap);
bookTreeModel.insertNodeInto(chap, book, pos);
}
}
}
}
});
menu.add(ren);
peak.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource();
Chapter c = (Chapter)o.getObject();
for (Enumeration<Sentence> s = c.children(); s.hasMoreElements();) {
Sentence snt = s.nextElement();
if (!snt.isLocked()) {
snt.autoTrimSamplePeak();
}
}
}
});
menu.add(moveUp);
menu.add(moveDown);
menu.addSeparator();
menu.add(peak);
menu.show(bookTree, e.getX(), e.getY());
}
@@ -687,6 +849,53 @@ public class AudiobookRecorder extends JFrame {
}
}
public void startRecordingNewParagraph() {
if (recording != null) return;
if (book == null) return;
toolBar.disableBook();
toolBar.disableSentence();
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)bookTree.getLastSelectedPathComponent();
if (selectedNode == null) {
selectedNode = book.getLastChapter();
bookTree.setSelectionPath(new TreePath(selectedNode.getPath()));
}
if (selectedNode instanceof Book) {
selectedNode = book.getLastChapter();
bookTree.setSelectionPath(new TreePath(selectedNode.getPath()));
}
if (selectedNode instanceof Sentence) {
selectedNode = (DefaultMutableTreeNode)selectedNode.getParent();
bookTree.setSelectionPath(new TreePath(selectedNode.getPath()));
}
Chapter c = (Chapter)selectedNode;
DefaultMutableTreeNode lastLeaf = c.getLastLeaf();
if (lastLeaf instanceof Sentence) {
Sentence lastSentence = (Sentence)lastLeaf;
lastSentence.setPostGap(Options.getInteger("catenation.post-paragraph"));
}
Sentence s = new Sentence();
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
bookTree.expandPath(new TreePath(c.getPath()));
bookTree.setSelectionPath(new TreePath(s.getPath()));
bookTree.scrollPathToVisible(new TreePath(s.getPath()));
if (s.startRecording()) {
recording = s;
centralPanel.setFlash(true);
}
}
public void startRecording() {
if (recording != null) return;
@@ -851,6 +1060,15 @@ public class AudiobookRecorder extends JFrame {
prefs.loadFromXML(fis);
buildBook(prefs);
File r = f.getParentFile();
File cf = new File(r, "coverart.png");
if (cf.exists()) {
ImageIcon i = new ImageIcon(cf.getAbsolutePath());
Image ri = Utils.getScaledImage(i.getImage(), 22, 22);
book.setIcon(new ImageIcon(ri));
bookTreeModel.reload(book);
}
} catch (Exception e) {
e.printStackTrace();
}
@@ -950,7 +1168,25 @@ public class AudiobookRecorder extends JFrame {
mainScroll.setViewportView(bookTree);
Chapter c = new Chapter("open", prefs.getProperty("chapter.open.name"));
Chapter c = new Chapter("audition", prefs.getProperty("chapter.audition.name"));
c.setPostGap(s2i(prefs.getProperty("chapter.audition.post-gap")));
c.setPreGap(s2i(prefs.getProperty("chapter.audition.pre-gap")));
bookTreeModel.insertNodeInto(c, book, 0);
for (int i = 0; i < 100000000; i++) {
String id = prefs.getProperty(String.format("chapter.audition.sentence.%08d.id", i));
String text = prefs.getProperty(String.format("chapter.audition.sentence.%08d.text", i));
int gap = s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.post-gap", i)));
if (id == null) break;
Sentence s = new Sentence(id, text);
s.setPostGap(gap);
s.setStartOffset(s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.start-offset", i))));
s.setEndOffset(s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.end-offset", i))));
s.setLocked(s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.locked", i))));
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
}
c = new Chapter("open", prefs.getProperty("chapter.open.name"));
c.setPostGap(s2i(prefs.getProperty("chapter.open.post-gap")));
c.setPreGap(s2i(prefs.getProperty("chapter.open.pre-gap")));
bookTreeModel.insertNodeInto(c, book, 0);
@@ -968,6 +1204,8 @@ public class AudiobookRecorder extends JFrame {
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
}
for (int cno = 1; cno < 10000; cno++) {
String cname = prefs.getProperty(String.format("chapter.%04d.name", cno));
if (cname == null) break;
@@ -1013,6 +1251,7 @@ public class AudiobookRecorder extends JFrame {
toolBar.enableBook();
statusLabel.setText("Noise floor: " + getNoiseFloor());
book.setIcon(Icons.book);
}
public void openBook() {
@@ -1037,6 +1276,9 @@ public class AudiobookRecorder extends JFrame {
}
loadBookStructure(f);
Options.set("path.last-book", book.getName());
Options.savePreferences();
}
@@ -1233,6 +1475,7 @@ public class AudiobookRecorder extends JFrame {
tags.setTrack(Integer.toString(s2i(c.getId()) - 0));
tags.setTitle(c.getName());
tags.setAlbum(book.getName());
tags.setArtist(book.getAuthor());
// ID3v2TextFrameData g = new ID3v2TextFrameData(false, new EncodedText(book.getGenre()));
@@ -1310,7 +1553,6 @@ public class AudiobookRecorder extends JFrame {
bookTree.setSelectionPath(new TreePath(s.getPath()));
}
} catch (Exception e) {
e.printStackTrace();
playing = null;
}
toolBar.enableSentence();

View File

@@ -16,6 +16,8 @@ public class Book extends DefaultMutableTreeNode {
String genre;
String comment;
ImageIcon icon;
public Book(String bookname) {
super(bookname);
name = bookname;
@@ -99,4 +101,39 @@ public class Book extends DefaultMutableTreeNode {
public String getName() {
return name;
}
public ImageIcon getIcon() {
return icon;
}
public void setIcon(ImageIcon i) {
icon = i;
}
public void setUserObject(Object o) {
if (o instanceof String) {
String newName = (String)o;
File oldDir = new File(Options.get("path.storage"), name);
File newDir = new File(Options.get("path.storage"), newName);
if (newDir.exists()) {
JOptionPane.showMessageDialog(AudiobookRecorder.window, "Book already exists", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
if (oldDir.exists() && oldDir.isDirectory()) {
oldDir.renameTo(newDir);
name = newName;
AudiobookRecorder.window.saveBookStructure();
AudiobookRecorder.window.bookTreeModel.reload(this);
Options.set("path.last-book", name);
Options.savePreferences();
}
}
}
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,96 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.border.*;
import java.util.*;
import java.io.*;
public class BookPanel extends JPanel {
String name;
String author;
String genre;
String comment;
ImageIcon cover;
Image resizedCover;
JLabel iconLabel;
JLabel titleLabel;
JLabel authorLabel;
JLabel otherLabel;
JPanel panel;
File root;
boolean highlight = false;
public BookPanel(File r) {
try {
root = r;
Properties props = new Properties();
props.loadFromXML(new FileInputStream(new File(root, "audiobook.abk")));
name = props.getProperty("book.name");
author = props.getProperty("book.author");
genre = props.getProperty("book.genre");
comment = props.getProperty("book.comment");
File icon = new File(root, "coverart.png");
if (icon.exists()) {
cover = new ImageIcon(icon.getAbsolutePath());
resizedCover = Utils.getScaledImage(cover.getImage(), 75, 75);
iconLabel = new JLabel(new ImageIcon(resizedCover));
} else {
cover = null;
resizedCover = null;
iconLabel = new JLabel("");
}
iconLabel.setSize(new Dimension(75, 75));
iconLabel.setPreferredSize(new Dimension(75, 75));
titleLabel = new JLabel(name);
authorLabel = new JLabel(author);
otherLabel = new JLabel(genre + " :: " + comment);
authorLabel.setForeground(new Color(0x80, 0x80, 0x80));
otherLabel.setForeground(new Color(0x80, 0x80, 0x80));
setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.add(titleLabel);
panel.add(authorLabel);
panel.add(otherLabel);
add(iconLabel, BorderLayout.WEST);
add(panel, BorderLayout.CENTER);
panel.setBackground(new Color(0x20, 0x20, 0x20));
panel.setOpaque(true);
setBackground(new Color(0x20, 0x20, 0x20));
setOpaque(true);
} catch (Exception e) {
}
}
public File getConfigFile() {
return new File(root, "audiobook.abk");
}
public void highlight() {
setBackground(new Color(0x00, 0x20, 0x40));
panel.setBackground(new Color(0x00, 0x20, 0x40));
}
public void lowlight() {
setBackground(new Color(0x20, 0x20, 0x20));
panel.setBackground(new Color(0x20, 0x20, 0x20));
}
}

View File

@@ -19,7 +19,7 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
} else if (value instanceof Chapter) {
ret.setIcon(Icons.chapter);
} else if (value instanceof Book) {
ret.setIcon(Icons.book);
ret.setIcon(((Book)value).getIcon());
}
return ret;
}

View File

@@ -37,13 +37,6 @@ public class Chapter extends DefaultMutableTreeNode {
return null;
}
public void renameChapter() {
String n = JOptionPane.showInputDialog(null, "Rename Chapter", name);
if (n != null) {
name = n;
}
}
public String toString() {
return name;
}

View File

@@ -28,13 +28,28 @@ public class OpenBookPanel extends JPanel {
}
}
public class BookCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) return null;
BookPanel p = (BookPanel)value;
if (isSelected) {
p.highlight();
} else {
p.lowlight();
}
return p;
}
};
class BookTableModel extends AbstractTableModel {
ArrayList<BookInfo> books;
ArrayList<BookPanel> books;
public BookTableModel() {
super();
books = new ArrayList<BookInfo>();
books = new ArrayList<BookPanel>();
}
public int getRowCount() {
@@ -42,38 +57,27 @@ public class OpenBookPanel extends JPanel {
}
public int getColumnCount() {
return 4;
return 1;
}
public boolean isCellEditable(int row, int column) {
return false;
}
public void addBook(BookInfo b) {
public void addBook(BookPanel b) {
books.add(b);
}
public Object getValueAt(int r, int c) {
if (c > 3) return null;
if (r > books.size()) return null;
BookInfo b = books.get(r);
switch (c) {
case 0: return b.name;
case 1: return b.author;
case 2: return b.genre;
case 4: return b.comment;
}
return null;
return books.get(r);
}
public String getColumnName(int i) {
switch(i) {
case 0: return "Name";
case 1: return "Author";
case 2: return "Genre";
case 3: return "Comment";
}
return null;
return "Book";
}
public Class getColumnClass(int i) {
return BookPanel.class;
}
}
@@ -85,7 +89,6 @@ public class OpenBookPanel extends JPanel {
model = new BookTableModel();
setLayout(new BorderLayout());
scroll = new JScrollPane();
add(scroll, BorderLayout.CENTER);
@@ -97,22 +100,17 @@ public class OpenBookPanel extends JPanel {
if (!b.isDirectory()) continue;
File xml = new File(b, "audiobook.abk");
if (xml.exists()) {
Properties props = new Properties();
props.loadFromXML(new FileInputStream(xml));
BookInfo book = new BookInfo(
props.getProperty("book.name"),
props.getProperty("book.author"),
props.getProperty("book.genre"),
props.getProperty("book.comment")
);
BookPanel book = new BookPanel(b);
model.addBook(book);
}
}
table = new JTable(model);
table.setDefaultRenderer(BookPanel.class, new BookCellRenderer());
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowHeight(80);
table.getTableHeader().setUI(null);
scroll.setViewportView(table);
} catch (Exception e) {
e.printStackTrace();
@@ -126,9 +124,7 @@ public class OpenBookPanel extends JPanel {
return null;
}
String name = (String)table.getValueAt(sel, 0);
File d = new File(Options.get("path.storage"), name);
File f = new File(d, "audiobook.abk");
return f;
BookPanel b = (BookPanel)table.getValueAt(sel, 0);
return b.getConfigFile();
}
}

View File

@@ -21,6 +21,7 @@ public class Options extends JDialog {
JSpinner preChapterGap;
JSpinner postChapterGap;
JSpinner postSentenceGap;
JSpinner postParagraphGap;
JTextField ffmpegLocation;
JComboBox<KVPair> bitRate;
JComboBox<KVPair> exportRate;
@@ -190,6 +191,7 @@ public class Options extends JDialog {
preChapterGap = addSpinner("Default pre-chapter gap:", 0, 5000, 100, getInteger("catenation.pre-chapter"), "ms");
postChapterGap = addSpinner("Default post-chapter gap:", 0, 5000, 100, getInteger("catenation.post-chapter"), "ms");
postSentenceGap = addSpinner("Default post-sentence gap:", 0, 5000, 100, getInteger("catenation.post-sentence"), "ms");
postParagraphGap = addSpinner("Default post-paragraph gap:", 0, 5000, 100, getInteger("catenation.post-paragraph"), "ms");
addSeparator();
@@ -277,7 +279,7 @@ public class Options extends JDialog {
}
if (supported) {
KVPair p = new KVPair(i.getName(), i.getDescription());
KVPair p = new KVPair(i.getName(), i.getName()); //i.getDescription());
list.add(p);
}
}
@@ -316,7 +318,7 @@ public class Options extends JDialog {
if (supported) {
KVPair p = new KVPair(i.getName(), i.getDescription());
KVPair p = new KVPair(i.getName(), i.getName()); //i.getDescription());
list.add(p);
}
}
@@ -361,6 +363,7 @@ public class Options extends JDialog {
defaultPrefs.put("catenation.pre-chapter", "2000");
defaultPrefs.put("catenation.post-chapter", "2000");
defaultPrefs.put("catenation.post-sentence", "1000");
defaultPrefs.put("catenation.post-paragraph", "2000");
defaultPrefs.put("path.storage", (new File(System.getProperty("user.home"), "Recordings")).toString());
defaultPrefs.put("path.ffmpeg", "");
@@ -426,6 +429,7 @@ public class Options extends JDialog {
set("catenation.pre-chapter", "" + preChapterGap.getValue());
set("catenation.post-chapter", "" + postChapterGap.getValue());
set("catenation.post-sentence", "" + postSentenceGap.getValue());
set("catenation.post-paragraph", "" + postParagraphGap.getValue());
set("audio.export.bitrate", ((KVPair)bitRate.getSelectedItem()).key);
set("audio.export.samplerate", ((KVPair)exportRate.getSelectedItem()).key);
set("process.sphinx", enableParsing.isSelected() ? "true" : "false");

View File

@@ -222,6 +222,8 @@ public class Sentence extends DefaultMutableTreeNode {
startOffset = 0;
}
startOffset -= 4096;
for (int i = samples.length-1; i >= 0; i--) {
endOffset = i;
if (Math.abs(samples[i]) > noiseFloor) {
@@ -230,10 +232,16 @@ public class Sentence extends DefaultMutableTreeNode {
break;
}
}
endOffset += 4096;
if (endOffset <= startOffset) endOffset = startOffset + 4096;
if (endOffset <= 0) {
endOffset = samples.length-1;
}
if (startOffset < 0) startOffset = 0;
if (endOffset >= samples.length) endOffset = samples.length-1;
}
public String getId() {

View File

@@ -0,0 +1,23 @@
package uk.co.majenko.audiobookrecorder;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.border.*;
import java.util.*;
import java.io.*;
public class Utils {
public static Image getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
}