diff --git a/resources/uk/co/majenko/audiobookrecorder/icons/disable-effects.png b/resources/uk/co/majenko/audiobookrecorder/icons/disable-effects.png new file mode 100644 index 0000000..08f5d03 Binary files /dev/null and b/resources/uk/co/majenko/audiobookrecorder/icons/disable-effects.png differ diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index 70de31a..f93ea64 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -115,6 +115,8 @@ public class AudiobookRecorder extends JFrame { SourceDataLine play = null; + boolean effectsEnabled = true; + public TargetDataLine microphone = null; public AudioInputStream microphoneStream = null; @@ -395,7 +397,7 @@ public class AudiobookRecorder extends JFrame { public void actionPerformed(ActionEvent e) { if (selectedSentence != null) { selectedSentence.autoTrimSampleFFT(); - sampleWaveform.setData(selectedSentence.getDoubleAudioData()); + sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); postSentenceGap.setValue(selectedSentence.getPostGap()); @@ -408,7 +410,7 @@ public class AudiobookRecorder extends JFrame { public void actionPerformed(ActionEvent e) { if (selectedSentence != null) { selectedSentence.autoTrimSamplePeak(); - sampleWaveform.setData(selectedSentence.getDoubleAudioData()); + sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); postSentenceGap.setValue(selectedSentence.getPostGap()); @@ -421,7 +423,7 @@ public class AudiobookRecorder extends JFrame { public void actionPerformed(ActionEvent e) { if (selectedSentence != null) { selectedSentence.normalize(); - sampleWaveform.setData(selectedSentence.getDoubleAudioData()); + sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); } } }); @@ -464,7 +466,7 @@ public class AudiobookRecorder extends JFrame { JSpinner ob = (JSpinner)e.getSource(); if (selectedSentence != null) { selectedSentence.setGain((Integer)ob.getValue() / 100d); - sampleWaveform.setData(selectedSentence.getDoubleAudioData()); + sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); } } }); @@ -579,7 +581,6 @@ public class AudiobookRecorder extends JFrame { int i = effectChain.getSelectedIndex(); KVPair p = effectChain.getItemAt(i); if (p == null) return; - CacheManager.removeFromCache(selectedSentence); selectedSentence.setEffectChain(p.getKey()); updateWaveform(); } @@ -1920,7 +1921,7 @@ public class AudiobookRecorder extends JFrame { if (n instanceof Sentence) { Sentence s = (Sentence)n; selectedSentence = s; - sampleWaveform.setData(s.getDoubleAudioData()); + sampleWaveform.setData(s.getDoubleAudioData(effectsEnabled)); sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset()); s.updateCrossings(); sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing()); @@ -2184,7 +2185,7 @@ public class AudiobookRecorder extends JFrame { play.drain(); bookTree.scrollPathToVisible(new TreePath(s.getPath())); - data = s.getPCMData(); + data = s.getPCMData(effectsEnabled); for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) { sampleWaveform.setPlayMarker(pos / format.getFrameSize()); int l = data.length - pos; @@ -2280,7 +2281,7 @@ public class AudiobookRecorder extends JFrame { play.drain(); bookTree.scrollPathToVisible(new TreePath(s.getPath())); - data = s.getPCMData(); + data = s.getPCMData(effectsEnabled); int startPos = 0; int endPos = data.length / format.getFrameSize(); @@ -2367,17 +2368,17 @@ public class AudiobookRecorder extends JFrame { data = getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter"))); play.write(data, 0, data.length); } - data = s.getPCMData(); + data = s.getPCMData(effectsEnabled); DefaultMutableTreeNode next = s.getNextSibling(); -// if (next != null) { -// Thread t = new Thread(new Runnable() { -// public void run() { -// Sentence ns = (Sentence)next; -// ns.getProcessedAudioData(); // Cache it -// } -// }); -// t.start(); -// } + if (next != null) { + Thread t = new Thread(new Runnable() { + public void run() { + Sentence ns = (Sentence)next; + ns.getProcessedAudioData(effectsEnabled); // Cache it + } + }); + t.start(); + } for (int pos = 0; pos < data.length; pos += PLAYBACK_CHUNK_SIZE) { sampleWaveform.setPlayMarker(pos / format.getFrameSize()); int l = data.length - pos; @@ -2904,7 +2905,7 @@ public class AudiobookRecorder extends JFrame { if (rawAudio.isSelected()) { sampleWaveform.setData(selectedSentence.getRawAudioData()); } else { - sampleWaveform.setData(selectedSentence.getDoubleAudioData()); + sampleWaveform.setData(selectedSentence.getDoubleAudioData(effectsEnabled)); } } } @@ -3313,4 +3314,9 @@ public class AudiobookRecorder extends JFrame { doCutSplit.setEnabled(false); } + public void setEffectsEnabled(boolean b) { + effectsEnabled = b; + System.err.println("Effects Enabled: " + b); + } + } diff --git a/src/uk/co/majenko/audiobookrecorder/CacheManager.java b/src/uk/co/majenko/audiobookrecorder/CacheManager.java index 5350d06..537a5a8 100644 --- a/src/uk/co/majenko/audiobookrecorder/CacheManager.java +++ b/src/uk/co/majenko/audiobookrecorder/CacheManager.java @@ -13,6 +13,10 @@ public class CacheManager { if (ob.lockedInCache()) { cache.add(ob); } else { + if (ob instanceof Sentence) { + Sentence s = (Sentence)ob; + s.debug("Normal removal from cache"); + } ob.clearCache(); } } @@ -27,6 +31,10 @@ public class CacheManager { } public static void removeFromCache(Cacheable c) { + if (c instanceof Sentence) { + Sentence s = (Sentence)c; + s.debug("Manual removal from cache"); + } cache.remove(c); c.clearCache(); } diff --git a/src/uk/co/majenko/audiobookrecorder/Icons.java b/src/uk/co/majenko/audiobookrecorder/Icons.java index 47ce025..2ea0018 100644 --- a/src/uk/co/majenko/audiobookrecorder/Icons.java +++ b/src/uk/co/majenko/audiobookrecorder/Icons.java @@ -37,4 +37,5 @@ public class Icons { static public final ImageIcon cut = new ImageIcon(Icons.class.getResource("icons/cut.png")); static public final ImageIcon docut = new ImageIcon(Icons.class.getResource("icons/do-cut.png")); static public final ImageIcon playto = new ImageIcon(Icons.class.getResource("icons/play-to.png")); + static public final ImageIcon disable = new ImageIcon(Icons.class.getResource("icons/disable-effects.png")); } diff --git a/src/uk/co/majenko/audiobookrecorder/MainToolBar.java b/src/uk/co/majenko/audiobookrecorder/MainToolBar.java index a229cb1..c78740e 100644 --- a/src/uk/co/majenko/audiobookrecorder/MainToolBar.java +++ b/src/uk/co/majenko/audiobookrecorder/MainToolBar.java @@ -17,7 +17,9 @@ public class MainToolBar extends JToolBar { JButtonSpacePlay playtoSentence; JButtonSpacePlay stopPlaying; JButtonSpacePlay eq; - JToggleButton mic; + JToggleButtonSpacePlay mic; + + JToggleButtonSpacePlay disableEffects; AudiobookRecorder root; @@ -129,6 +131,28 @@ public class MainToolBar extends JToolBar { add(mic); + addSeparator(); + + disableEffects = new JToggleButtonSpacePlay(Icons.disable, "Disable effects", new ActionListener() { + Color bgCol = null; + public void actionPerformed(ActionEvent e) { + JToggleButton b = (JToggleButton)e.getSource(); + if (b.isSelected()) { + root.setEffectsEnabled(false); + bgCol = b.getBackground(); + b.setBackground(Color.RED); + } else { + root.setEffectsEnabled(true); + if (bgCol != null) { + b.setBackground(bgCol); + } + } + } + }); + + add(disableEffects); + + setFloatable(false); } diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 930b100..88fd280 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -161,6 +161,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { return false; } + debug("Start recording based purge"); CacheManager.removeFromCache(this); recordingThread = new RecordingThread(getTempFile(), getFile(), Options.getAudioFormat()); @@ -182,11 +183,9 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } } + debug("Stop recording based purge"); CacheManager.removeFromCache(this); - audioData = null; - processedAudio = null; - if (!id.equals("room-noise")) { autoTrimSample(true); if (Options.getBoolean("process.sphinx")) { @@ -225,7 +224,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { samples = getProcessedAudioData(); } if (samples == null) { - System.err.println("Error: loading data failed!"); + debug("Error: loading data failed!"); return; } @@ -588,6 +587,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public void clearCache() { + debug("Clearing cached data"); audioData = null; processedAudio = null; storedFormat = null; @@ -721,6 +721,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { if (g == gain) return; if (gain != g) { + debug("Gain based purge"); CacheManager.removeFromCache(this); } gain = g; @@ -767,6 +768,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { proc.waitFor(); } catch (Exception e) { } + debug("External editor based purge"); CacheManager.removeFromCache(Sentence.this); AudiobookRecorder.window.updateWaveform(); } @@ -793,7 +795,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } } if (backupNumber == -1) { - System.err.println("Out of backup space!"); + debug("Out of backup space!"); return; } @@ -857,6 +859,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } } + debug("External processor based purge"); CacheManager.removeFromCache(Sentence.this); AudiobookRecorder.window.updateWaveform(); } @@ -900,6 +903,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { e.printStackTrace(); } + debug("Undo based purge"); CacheManager.removeFromCache(this); AudiobookRecorder.window.updateWaveform(); } @@ -1074,6 +1078,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { break; } + debug("Write based purge"); CacheManager.removeFromCache(this); } @@ -1124,7 +1129,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { File f = getFile(); try { if (!f.exists()) { - System.err.println("TODO: Race condition: wav file doesn't exist yet"); + debug("TODO: Race condition: wav file doesn't exist yet"); return; } AudioInputStream s = AudioSystem.getAudioInputStream(f); @@ -1156,8 +1161,15 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } synchronized public double[][] getProcessedAudioData() { + return getProcessedAudioData(true); + } + + synchronized public double[][] getProcessedAudioData(boolean effectsEnabled) { loadFile(); - if (processedAudio != null) return processedAudio; + if (processedAudio != null) { + debug("Returning cached data"); + return processedAudio; + } if (audioData == null) return null; processedAudio = new double[audioData.length][2]; @@ -1171,21 +1183,26 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { String def = AudiobookRecorder.window.getDefaultEffectsChain(); Effect eff = AudiobookRecorder.window.effects.get(def); - if (eff != null) { - eff.init(getAudioFormat().getFrameRate()); - eff.process(processedAudio); - } + if (effectsEnabled) { + debug("Processing audio effects"); + if (eff != null) { + eff.init(getAudioFormat().getFrameRate()); + eff.process(processedAudio); + } - if (effectChain != null) { - // Don't double up the default chain - if (!effectChain.equals(def)) { - eff = AudiobookRecorder.window.effects.get(effectChain); - if (eff != null) { - eff.init(getAudioFormat().getFrameRate()); - eff.process(processedAudio); + if (effectChain != null) { + // Don't double up the default chain + if (!effectChain.equals(def)) { + eff = AudiobookRecorder.window.effects.get(effectChain); + if (eff != null) { + eff.init(getAudioFormat().getFrameRate()); + eff.process(processedAudio); + } } } } + + debug("Processing done"); // Add final master gain stage for (int i = 0; i < processedAudio.length; i++) { @@ -1193,15 +1210,25 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { processedAudio[i][RIGHT] *= gain; } + debug("Gain applied"); + return processedAudio; } public double[][] getDoubleAudioData() { - return getProcessedAudioData(); + return getDoubleAudioData(true); + } + + public double[][] getDoubleAudioData(boolean effectsEnabled) { + return getProcessedAudioData(effectsEnabled); } public double[][] getCroppedAudioData() { - double[][] inSamples = getDoubleAudioData(); + return getCroppedAudioData(true); + } + + public double[][] getCroppedAudioData(boolean effectsEnabled) { + double[][] inSamples = getDoubleAudioData(effectsEnabled); if (inSamples == null) return null; updateCrossings(); @@ -1216,7 +1243,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } public byte[] getPCMData() { - double[][] croppedData = getCroppedAudioData(); + return getPCMData(true); + } + + public byte[] getPCMData(boolean effectsEnabled) { + double[][] croppedData = getCroppedAudioData(effectsEnabled); if (croppedData == null) return null; int length = croppedData.length; byte[] pcmData = new byte[length * 4]; @@ -1239,6 +1270,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { public void setEffectChain(String key) { if ((effectChain != null) && (!effectChain.equals(key))) { + debug("Effects chain based purge"); CacheManager.removeFromCache(this); } effectChain = key; @@ -1285,4 +1317,8 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { } } + + public void debug(String txt) { + System.err.println(id + ": " + txt); + } }