diff --git a/README.md b/README.md index e54d494..8268e60 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,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. diff --git a/resources/uk/co/majenko/audiobookrecorder/icons/appIcon.png b/resources/uk/co/majenko/audiobookrecorder/icons/appIcon.png new file mode 100644 index 0000000..a6a93d0 Binary files /dev/null and b/resources/uk/co/majenko/audiobookrecorder/icons/appIcon.png differ diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index 6d33e7e..16da0bc 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -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; @@ -699,6 +708,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; @@ -1248,6 +1304,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())); @@ -1325,7 +1382,6 @@ public class AudiobookRecorder extends JFrame { bookTree.setSelectionPath(new TreePath(s.getPath())); } } catch (Exception e) { - e.printStackTrace(); playing = null; } toolBar.enableSentence(); diff --git a/src/uk/co/majenko/audiobookrecorder/Options.java b/src/uk/co/majenko/audiobookrecorder/Options.java index 15d35aa..1c07204 100644 --- a/src/uk/co/majenko/audiobookrecorder/Options.java +++ b/src/uk/co/majenko/audiobookrecorder/Options.java @@ -21,6 +21,7 @@ public class Options extends JDialog { JSpinner preChapterGap; JSpinner postChapterGap; JSpinner postSentenceGap; + JSpinner postParagraphGap; JTextField ffmpegLocation; JComboBox bitRate; JComboBox 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(); @@ -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"); diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 795f73b..01115b7 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -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() {