diff --git a/build.xml b/build.xml index 896827d..4f2979a 100644 --- a/build.xml +++ b/build.xml @@ -25,7 +25,7 @@ debug="true" debuglevel="lines,vars,source" encoding="UTF-8" - bootclasspath="${bootclass.path}" + bootclasspath="/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar" includeAntRuntime="false" deprecation="true" srcdir="src" diff --git a/src/uk/co/majenko/audiobookrecorder/Amplifier.java b/src/uk/co/majenko/audiobookrecorder/Amplifier.java index 0c3e425..80e2fe3 100644 --- a/src/uk/co/majenko/audiobookrecorder/Amplifier.java +++ b/src/uk/co/majenko/audiobookrecorder/Amplifier.java @@ -1,9 +1,8 @@ package uk.co.majenko.audiobookrecorder; import java.util.ArrayList; -import javax.swing.tree.*; -public class Amplifier extends DefaultMutableTreeNode implements Effect { +public class Amplifier implements Effect { double gain; public Amplifier() { gain = 1.0d; diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index c6150b0..8c6c298 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -525,6 +525,7 @@ public class AudiobookRecorder extends JFrame { if (selectedSentence != null) { int i = effectChain.getSelectedIndex(); KVPair p = effectChain.getItemAt(i); + if (p == null) return; selectedSentence.setEffectChain(p.getKey()); updateWaveform(); } @@ -707,6 +708,7 @@ public class AudiobookRecorder extends JFrame { prefs.setProperty("chapter.close.pre-gap", Options.get("catenation.pre-chapter")); prefs.setProperty("chapter.close.post-gap", Options.get("catenation.post-chapter")); + loadEffects(); buildBook(prefs); Options.set("path.last-book", book.getName()); @@ -1192,13 +1194,15 @@ public class AudiobookRecorder extends JFrame { JComboBox> defEff = new JComboBox>(); int selEff = -1; int i = 0; - for (String k : effects.keySet()) { - if (k.equals(defaultEffectChain)) { - selEff = i; + if (effects != null) { + for (String k : effects.keySet()) { + if (k.equals(defaultEffectChain)) { + selEff = i; + } + KVPair p = new KVPair(k, effects.get(k).toString()); + defEff.addItem(p); + i++; } - KVPair p = new KVPair(k, effects.get(k).toString()); - defEff.addItem(p); - i++; } defEff.setSelectedIndex(selEff); @@ -2578,6 +2582,11 @@ System.err.println(format); if (eff != null) { group.addEffect(eff); } + } else if (e.getTagName().equals("lfo")) { + Effect eff = (Effect)loadLFO(e); + if (eff != null) { + group.addEffect(eff); + } } } } @@ -2653,6 +2662,11 @@ System.err.println(format); if (eff != null) { store.addEffect(eff); } + } else if (ie.getTagName().equals("lfo")) { + Effect eff = (Effect)loadLFO(ie); + if (eff != null) { + store.addEffect(eff); + } } } } @@ -2668,7 +2682,16 @@ System.err.println(format); return a; } + public LFO loadLFO(Element root) { + double f = Utils.s2d(root.getAttribute("frequency")); + double d = Utils.s2d(root.getAttribute("depth")); + double p = Utils.s2d(root.getAttribute("phase")); + return new LFO(f, d, p); + } + public void updateEffectChains() { + int sel = effectChain.getSelectedIndex(); + KVPair ent = effectChain.getItemAt(sel); while (effectChain.getItemCount() > 0) { effectChain.removeItemAt(0); } @@ -2677,6 +2700,11 @@ System.err.println(format); KVPair p = new KVPair(k, e.toString()); effectChain.addItem(p); } + if (ent != null) { + setEffectChain(ent.getKey()); + } else { + setEffectChain(defaultEffectChain); + } } public void setEffectChain(String key) { diff --git a/src/uk/co/majenko/audiobookrecorder/Biquad.java b/src/uk/co/majenko/audiobookrecorder/Biquad.java index 0dc3798..1b3ef92 100644 --- a/src/uk/co/majenko/audiobookrecorder/Biquad.java +++ b/src/uk/co/majenko/audiobookrecorder/Biquad.java @@ -19,9 +19,8 @@ package uk.co.majenko.audiobookrecorder; // import java.util.ArrayList; -import javax.swing.tree.*; -public class Biquad extends DefaultMutableTreeNode implements Effect { +public class Biquad implements Effect { public static final int Lowpass = 0; public static final int Highpass = 1; public static final int Bandpass = 2; diff --git a/src/uk/co/majenko/audiobookrecorder/DelayLine.java b/src/uk/co/majenko/audiobookrecorder/DelayLine.java index 9483b75..8debc52 100644 --- a/src/uk/co/majenko/audiobookrecorder/DelayLine.java +++ b/src/uk/co/majenko/audiobookrecorder/DelayLine.java @@ -1,9 +1,8 @@ package uk.co.majenko.audiobookrecorder; import java.util.ArrayList; -import javax.swing.tree.*; -public class DelayLine extends DefaultMutableTreeNode implements Effect { +public class DelayLine implements Effect { ArrayList delayLines; diff --git a/src/uk/co/majenko/audiobookrecorder/Effect.java b/src/uk/co/majenko/audiobookrecorder/Effect.java index e889cd8..6e5021d 100644 --- a/src/uk/co/majenko/audiobookrecorder/Effect.java +++ b/src/uk/co/majenko/audiobookrecorder/Effect.java @@ -8,4 +8,5 @@ public interface Effect { public ArrayList getChildEffects(); public void dump(); public void init(double sr); + public String toString(); } diff --git a/src/uk/co/majenko/audiobookrecorder/EffectGroup.java b/src/uk/co/majenko/audiobookrecorder/EffectGroup.java index df327e4..3591984 100644 --- a/src/uk/co/majenko/audiobookrecorder/EffectGroup.java +++ b/src/uk/co/majenko/audiobookrecorder/EffectGroup.java @@ -1,9 +1,8 @@ package uk.co.majenko.audiobookrecorder; import java.util.ArrayList; -import javax.swing.tree.*; -public class EffectGroup extends DefaultMutableTreeNode implements Effect { +public class EffectGroup implements Effect { String name; ArrayList effects; diff --git a/src/uk/co/majenko/audiobookrecorder/LFO.java b/src/uk/co/majenko/audiobookrecorder/LFO.java new file mode 100644 index 0000000..2195955 --- /dev/null +++ b/src/uk/co/majenko/audiobookrecorder/LFO.java @@ -0,0 +1,66 @@ +package uk.co.majenko.audiobookrecorder; + +import java.util.ArrayList; + +public class LFO implements Effect { + + double phase; + double frequency; + double depth; + double sampleRate; + double sampleStep; + + public LFO(double f, double d) { + frequency = f; + depth = d; + phase = 0; + } + + public LFO(double f, double d, double p) { + frequency = f; + depth = d; + phase = p; + } + + public double process(double sample) { + double v = Math.sin(phase); + phase += sampleStep; + if (phase > (Math.PI * 2d)) { + phase -= (Math.PI * 2d); + } + +// // Make it between 0 and 1. +// v = 1d + v; +// v /= 2d; + + // Multiply it by the gain factor + v *= depth; + + // Apply it to the sample + sample += (sample * v); + + return sample; + } + + public String getName() { return "Low Frequency Oscillator (" + frequency + " Hz, " + (depth * 100d) + "%)"; } + + public ArrayList getChildEffects() { return null; } + + public void dump() { + System.out.println(getName()); + } + + public void init(double sr) { + sampleRate = sr; + + // Number of samples that make up one cycle of the LFO + double oneCycle = sampleRate / frequency; + + // Amount to increase each step + sampleStep = (Math.PI * 2d) / oneCycle; + + } + + public String toString() { return getName(); } + +} diff --git a/src/uk/co/majenko/audiobookrecorder/Options.java b/src/uk/co/majenko/audiobookrecorder/Options.java index b3aea68..c14a420 100644 --- a/src/uk/co/majenko/audiobookrecorder/Options.java +++ b/src/uk/co/majenko/audiobookrecorder/Options.java @@ -37,6 +37,8 @@ public class Options extends JDialog { JCheckBox enableParsing; JSpinner cacheSize; + JSpinner fftThreshold; + JSpinner etherealIterations; JSpinner etherealAttenuation; JSpinner etherealOffset; @@ -295,6 +297,7 @@ public class Options extends JDialog { rateList = addDropdown(optionsPanel, "Sample rate:", getSampleRateList(), get("audio.recording.samplerate")); bitDepth = addDropdown(optionsPanel, "Sample resolution:", getResolutionList(), get("audio.recording.resolution")); trimMethod = addDropdown(optionsPanel, "Auto-trim method:", getTrimMethods(), get("audio.recording.trim")); + fftThreshold = addSpinner(optionsPanel, "FFT threshold:", 0, 100, 1, getInteger("audio.recording.trim.fft"), ""); addSeparator(optionsPanel); @@ -569,6 +572,8 @@ public class Options extends JDialog { defaultPrefs.put("catenation.post-sentence", "1000"); defaultPrefs.put("catenation.short-sentence", "100"); defaultPrefs.put("catenation.post-paragraph", "2000"); + + defaultPrefs.put("audio.recording.trim.fft", "10"); defaultPrefs.put("path.storage", (new File(System.getProperty("user.home"), "Recordings")).toString()); defaultPrefs.put("path.archive", (new File(new File(System.getProperty("user.home"), "Recordings"),"archive")).toString()); @@ -704,6 +709,7 @@ public class Options extends JDialog { set("process.haven.apikey", havenApiKey.getText()); set("editor.external", externalEditor.getText()); set("cache.size", cacheSize.getValue()); + set("audio.recording.trim.fft", fftThreshold.getValue()); set("effects.ethereal.offset", etherealOffset.getValue()); set("effects.ethereal.iterations", etherealIterations.getValue()); diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 27c4313..345e941 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -87,7 +87,6 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable { tempFile = tf; wavFile = wf; format = af; -System.err.println(format); } public void run() { @@ -271,14 +270,15 @@ System.err.println(format); } } block++; - } - // Find first block with > 0 intensity and subtract one. + int limit = Options.getInteger("audio.recording.trim.fft"); + + // Find first block with > 1 intensity and subtract one. int start = 0; for (int i = 0; i < blocks; i++) { - if (intens[i] > 0) break; + if (intens[i] > limit) break; start = i; } @@ -291,9 +291,9 @@ System.err.println(format); if (startOffset >= samples.length) startOffset = samples.length; int end = blocks - 1; - // And last block with > 0 intensity and add one. + // And last block with > 1 intensity and add one. for (int i = blocks-1; i >= 0; i--) { - if (intens[i] > 0) break; + if (intens[i] > limit) break; end = i; } @@ -318,6 +318,7 @@ System.err.println(format); double[] samples = getProcessedAudioData(); if (samples == null) return; double noiseFloor = AudiobookRecorder.window.getNoiseFloor(); + noiseFloor *= 1.1; // Find start for (int i = 0; i < samples.length; i++) {