Compare commits

...

5 Commits

7 changed files with 123 additions and 17 deletions

View File

@@ -34,4 +34,4 @@ Third party software
* CMU Sphinx: https://github.com/mpatric/mp3agic * CMU Sphinx: https://github.com/mpatric/mp3agic
* JAVE ffmpeg wrapper: http://www.sauronsoftware.it/projects/jave/ * JAVE ffmpeg wrapper: http://www.sauronsoftware.it/projects/jave/
* JTattoo: 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 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 * 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. 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 "D" to delete the last phrase you recorded.
* Press "E" to re-record the currently selected phrase. * Press "E" to re-record the currently selected phrase.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 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("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("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("released D"), "deleteLast");
centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("SPACE"), "startPlayback"); centralPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("SPACE"), "startPlayback");
@@ -477,6 +480,12 @@ public class AudiobookRecorder extends JFrame {
startRecording(); startRecording();
} }
}); });
centralPanel.getActionMap().put("startRecordNewPara", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return;
startRecordingNewParagraph();
}
});
centralPanel.getActionMap().put("startRerecord", new AbstractAction() { centralPanel.getActionMap().put("startRerecord", new AbstractAction() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (bookTree.isEditing()) return; if (bookTree.isEditing()) return;
@@ -512,6 +521,18 @@ public class AudiobookRecorder extends JFrame {
pack(); pack();
setVisible(true); 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[]) { public static void main(String args[]) {
@@ -538,6 +559,9 @@ public class AudiobookRecorder extends JFrame {
prefs.setProperty("book.author", info.getAuthor()); prefs.setProperty("book.author", info.getAuthor());
prefs.setProperty("book.genre", info.getGenre()); prefs.setProperty("book.genre", info.getGenre());
prefs.setProperty("book.comment", info.getComment()); 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.name", "Opening Credits");
prefs.setProperty("chapter.open.pre-gap", Options.get("catenation.pre-chapter")); prefs.setProperty("chapter.open.pre-gap", Options.get("catenation.pre-chapter"));
prefs.setProperty("chapter.open.post-gap", Options.get("catenation.post-chapter")); prefs.setProperty("chapter.open.post-gap", Options.get("catenation.post-chapter"));
@@ -641,18 +665,22 @@ public class AudiobookRecorder extends JFrame {
bookTree.setSelectionPath(new TreePath(c.getPath())); bookTree.setSelectionPath(new TreePath(c.getPath()));
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();
JMenuObject ren = new JMenuObject("Rename chapter", c); JMenuObject peak = new JMenuObject("Auto-trim all (Peak)", c);
ren.addActionListener(new ActionListener() { peak.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JMenuObject o = (JMenuObject)e.getSource(); JMenuObject o = (JMenuObject)e.getSource();
Chapter c = (Chapter)o.getObject(); Chapter c = (Chapter)o.getObject();
c.renameChapter(); for (Enumeration<Sentence> s = c.children(); s.hasMoreElements();) {
bookTreeModel.reload(c); Sentence snt = s.nextElement();
if (!snt.isLocked()) {
snt.autoTrimSamplePeak();
}
}
} }
}); });
menu.add(ren); menu.add(peak);
menu.show(bookTree, e.getX(), e.getY()); menu.show(bookTree, e.getX(), e.getY());
} }
@@ -687,6 +715,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() { public void startRecording() {
if (recording != null) return; if (recording != null) return;
@@ -950,7 +1025,25 @@ public class AudiobookRecorder extends JFrame {
mainScroll.setViewportView(bookTree); 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.setPostGap(s2i(prefs.getProperty("chapter.open.post-gap")));
c.setPreGap(s2i(prefs.getProperty("chapter.open.pre-gap"))); c.setPreGap(s2i(prefs.getProperty("chapter.open.pre-gap")));
bookTreeModel.insertNodeInto(c, book, 0); bookTreeModel.insertNodeInto(c, book, 0);
@@ -968,6 +1061,8 @@ public class AudiobookRecorder extends JFrame {
bookTreeModel.insertNodeInto(s, c, c.getChildCount()); bookTreeModel.insertNodeInto(s, c, c.getChildCount());
} }
for (int cno = 1; cno < 10000; cno++) { for (int cno = 1; cno < 10000; cno++) {
String cname = prefs.getProperty(String.format("chapter.%04d.name", cno)); String cname = prefs.getProperty(String.format("chapter.%04d.name", cno));
if (cname == null) break; if (cname == null) break;
@@ -1037,6 +1132,9 @@ public class AudiobookRecorder extends JFrame {
} }
loadBookStructure(f); loadBookStructure(f);
Options.set("path.last-book", book.getName());
Options.savePreferences();
} }
@@ -1233,6 +1331,7 @@ public class AudiobookRecorder extends JFrame {
tags.setTrack(Integer.toString(s2i(c.getId()) - 0)); tags.setTrack(Integer.toString(s2i(c.getId()) - 0));
tags.setTitle(c.getName()); tags.setTitle(c.getName());
tags.setAlbum(book.getName());
tags.setArtist(book.getAuthor()); tags.setArtist(book.getAuthor());
// ID3v2TextFrameData g = new ID3v2TextFrameData(false, new EncodedText(book.getGenre())); // ID3v2TextFrameData g = new ID3v2TextFrameData(false, new EncodedText(book.getGenre()));
@@ -1310,7 +1409,6 @@ public class AudiobookRecorder extends JFrame {
bookTree.setSelectionPath(new TreePath(s.getPath())); bookTree.setSelectionPath(new TreePath(s.getPath()));
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
playing = null; playing = null;
} }
toolBar.enableSentence(); toolBar.enableSentence();

View File

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

View File

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

View File

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