Fix caching of processed audio. Add effect icon and name to tree
This commit is contained in:
@@ -34,7 +34,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
public static final String SPHINX_MODEL = "resource:/edu/cmu/sphinx/models/en-us/en-us";
|
public static final String SPHINX_MODEL = "resource:/edu/cmu/sphinx/models/en-us/en-us";
|
||||||
|
|
||||||
static Properties config = new Properties();
|
static Properties config = new Properties();
|
||||||
HashMap<String, EffectGroup> effects;
|
TreeMap<String, EffectGroup> effects;
|
||||||
|
|
||||||
String defaultEffectChain = "none";
|
String defaultEffectChain = "none";
|
||||||
|
|
||||||
@@ -748,7 +748,6 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
prefs.setProperty("chapter.close.pre-gap", Options.get("catenation.pre-chapter"));
|
prefs.setProperty("chapter.close.pre-gap", Options.get("catenation.pre-chapter"));
|
||||||
prefs.setProperty("chapter.close.post-gap", Options.get("catenation.post-chapter"));
|
prefs.setProperty("chapter.close.post-gap", Options.get("catenation.post-chapter"));
|
||||||
|
|
||||||
loadEffects();
|
|
||||||
buildBook(prefs);
|
buildBook(prefs);
|
||||||
|
|
||||||
Options.set("path.last-book", book.getName());
|
Options.set("path.last-book", book.getName());
|
||||||
@@ -1684,7 +1683,6 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
prefs.loadFromXML(fis);
|
prefs.loadFromXML(fis);
|
||||||
|
|
||||||
File r = f.getParentFile();
|
File r = f.getParentFile();
|
||||||
loadEffects();
|
|
||||||
|
|
||||||
buildBook(prefs);
|
buildBook(prefs);
|
||||||
|
|
||||||
@@ -1716,6 +1714,8 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
book.setComment(prefs.getProperty("book.comment"));
|
book.setComment(prefs.getProperty("book.comment"));
|
||||||
book.setACX(prefs.getProperty("book.acx"));
|
book.setACX(prefs.getProperty("book.acx"));
|
||||||
|
|
||||||
|
loadEffects();
|
||||||
|
|
||||||
defaultEffectChain = prefs.getProperty("audio.effect.default");
|
defaultEffectChain = prefs.getProperty("audio.effect.default");
|
||||||
if (defaultEffectChain == null) {
|
if (defaultEffectChain == null) {
|
||||||
defaultEffectChain = "none";
|
defaultEffectChain = "none";
|
||||||
@@ -2119,7 +2119,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
Thread t = new Thread(new Runnable() {
|
Thread t = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Sentence ns = (Sentence)next;
|
Sentence ns = (Sentence)next;
|
||||||
ns.loadFile(); // Cache it
|
ns.getProcessedAudioData(); // Cache it
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
t.start();
|
t.start();
|
||||||
@@ -2649,7 +2649,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadEffects() {
|
public void loadEffects() {
|
||||||
effects = new HashMap<String,EffectGroup>();
|
effects = new TreeMap<String,EffectGroup>();
|
||||||
loadEffectsFromFolder(new File(Options.get("path.storage"), "System"));
|
loadEffectsFromFolder(new File(Options.get("path.storage"), "System"));
|
||||||
if (book != null) {
|
if (book != null) {
|
||||||
loadEffectsFromFolder(new File(Options.get("path.storage"), book.getName()));
|
loadEffectsFromFolder(new File(Options.get("path.storage"), book.getName()));
|
||||||
@@ -2705,6 +2705,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
group.addEffect(eff);
|
group.addEffect(eff);
|
||||||
}
|
}
|
||||||
|
} else if (e.getTagName().equals("pan")) {
|
||||||
|
Effect eff = (Effect)loadPan(e);
|
||||||
|
if (eff != null) {
|
||||||
|
group.addEffect(eff);
|
||||||
|
}
|
||||||
} else if (e.getTagName().equals("amplifier")) {
|
} else if (e.getTagName().equals("amplifier")) {
|
||||||
Effect eff = (Effect)loadAmplifier(e);
|
Effect eff = (Effect)loadAmplifier(e);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
@@ -2769,6 +2774,9 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
DelayLine line = new DelayLine();
|
DelayLine line = new DelayLine();
|
||||||
|
|
||||||
NodeList list = root.getChildNodes();
|
NodeList list = root.getChildNodes();
|
||||||
|
if (Utils.s2b(root.getAttribute("wetonly"))) {
|
||||||
|
line.setWetOnly(true);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < list.getLength(); i++) {
|
for (int i = 0; i < list.getLength(); i++) {
|
||||||
Node n = list.item(i);
|
Node n = list.item(i);
|
||||||
@@ -2777,7 +2785,9 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (e.getTagName().equals("delay")) {
|
if (e.getTagName().equals("delay")) {
|
||||||
int samples = Utils.s2i(e.getAttribute("samples"));
|
int samples = Utils.s2i(e.getAttribute("samples"));
|
||||||
double gain = Utils.s2d(e.getAttribute("gain"));
|
double gain = Utils.s2d(e.getAttribute("gain"));
|
||||||
DelayLineStore store = line.addDelayLine(samples, gain);
|
double pan = Utils.s2d(e.getAttribute("pan"));
|
||||||
|
DelayLineStore store = line.addDelayLine(samples, gain, pan);
|
||||||
|
|
||||||
|
|
||||||
NodeList inner = e.getChildNodes();
|
NodeList inner = e.getChildNodes();
|
||||||
for (int j = 0; j < inner.getLength(); j++) {
|
for (int j = 0; j < inner.getLength(); j++) {
|
||||||
@@ -2795,6 +2805,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
store.addEffect(eff);
|
store.addEffect(eff);
|
||||||
}
|
}
|
||||||
|
} else if (ie.getTagName().equals("pan")) {
|
||||||
|
Effect eff = (Effect)loadPan(ie);
|
||||||
|
if (eff != null) {
|
||||||
|
store.addEffect(eff);
|
||||||
|
}
|
||||||
} else if (ie.getTagName().equals("amplifier")) {
|
} else if (ie.getTagName().equals("amplifier")) {
|
||||||
Effect eff = (Effect)loadAmplifier(ie);
|
Effect eff = (Effect)loadAmplifier(ie);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
@@ -2835,6 +2850,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Pan loadPan(Element root) {
|
||||||
|
Pan p = new Pan(Utils.s2d(root.getAttribute("pan")));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
public Clipping loadClipping(Element root) {
|
public Clipping loadClipping(Element root) {
|
||||||
Clipping c = new Clipping(Utils.s2d(root.getAttribute("clip")));
|
Clipping c = new Clipping(Utils.s2d(root.getAttribute("clip")));
|
||||||
return c;
|
return c;
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer {
|
|||||||
icn.add(Overlays.important, OverlayIcon.TOP_RIGHT);
|
icn.add(Overlays.important, OverlayIcon.TOP_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s.getEffectChain() != null) {
|
||||||
|
if (!s.getEffectChain().equals("none")) {
|
||||||
|
icn.add(Overlays.filter, OverlayIcon.BOTTOM_RIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret.setIcon(icn);
|
ret.setIcon(icn);
|
||||||
|
|
||||||
} else if (value instanceof Chapter) {
|
} else if (value instanceof Chapter) {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ public class DelayLine implements Effect {
|
|||||||
|
|
||||||
ArrayList<DelayLineStore> delayLines;
|
ArrayList<DelayLineStore> delayLines;
|
||||||
|
|
||||||
|
boolean wetOnly = false;
|
||||||
|
|
||||||
public DelayLine() {
|
public DelayLine() {
|
||||||
delayLines = new ArrayList<DelayLineStore>();
|
delayLines = new ArrayList<DelayLineStore>();
|
||||||
}
|
}
|
||||||
@@ -19,6 +21,12 @@ public class DelayLine implements Effect {
|
|||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < samples.length; i++) {
|
||||||
savedSamples[i] = new Sample(samples[i].left, samples[i].right);
|
savedSamples[i] = new Sample(samples[i].left, samples[i].right);
|
||||||
}
|
}
|
||||||
|
if (wetOnly) {
|
||||||
|
for (int i = 0; i < samples.length; i++) {
|
||||||
|
samples[i].left = 0d;
|
||||||
|
samples[i].right = 0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (DelayLineStore d : delayLines) {
|
for (DelayLineStore d : delayLines) {
|
||||||
Sample[] subSamples = new Sample[samples.length];
|
Sample[] subSamples = new Sample[samples.length];
|
||||||
@@ -62,6 +70,12 @@ public class DelayLine implements Effect {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DelayLineStore addDelayLine(int samples, double gain, double pan) {
|
||||||
|
DelayLineStore s = new DelayLineStore(samples, gain, pan);
|
||||||
|
delayLines.add(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
public DelayLineStore addDelayLine(int samples, double gain) {
|
public DelayLineStore addDelayLine(int samples, double gain) {
|
||||||
DelayLineStore s = new DelayLineStore(samples, gain);
|
DelayLineStore s = new DelayLineStore(samples, gain);
|
||||||
delayLines.add(s);
|
delayLines.add(s);
|
||||||
@@ -88,4 +102,8 @@ public class DelayLine implements Effect {
|
|||||||
s.init(sf);
|
s.init(sf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setWetOnly(boolean b) {
|
||||||
|
wetOnly = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,21 @@ import java.util.ArrayList;
|
|||||||
public class DelayLineStore {
|
public class DelayLineStore {
|
||||||
double gain;
|
double gain;
|
||||||
int numSamples;
|
int numSamples;
|
||||||
|
double pan;
|
||||||
|
|
||||||
ArrayList<Effect> effects;
|
ArrayList<Effect> effects;
|
||||||
|
|
||||||
|
public DelayLineStore(int s, double g, double p) {
|
||||||
|
numSamples = s;
|
||||||
|
gain = g;
|
||||||
|
pan = p;
|
||||||
|
effects = new ArrayList<Effect>();
|
||||||
|
}
|
||||||
|
|
||||||
public DelayLineStore(int s, double g) {
|
public DelayLineStore(int s, double g) {
|
||||||
numSamples = s;
|
numSamples = s;
|
||||||
gain = g;
|
gain = g;
|
||||||
|
pan = 0d;
|
||||||
effects = new ArrayList<Effect>();
|
effects = new ArrayList<Effect>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +32,14 @@ public class DelayLineStore {
|
|||||||
for (Sample sample : samples) {
|
for (Sample sample : samples) {
|
||||||
sample.left *= gain;
|
sample.left *= gain;
|
||||||
sample.right *= gain;
|
sample.right *= gain;
|
||||||
|
|
||||||
|
if (pan < 0) {
|
||||||
|
double p = 1 + pan;
|
||||||
|
sample.right *= p;
|
||||||
|
} else {
|
||||||
|
double p = 1 - pan;
|
||||||
|
sample.left *= p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
double storedLength = -1d;
|
double storedLength = -1d;
|
||||||
|
|
||||||
Sample[] audioData = null;
|
Sample[] audioData = null;
|
||||||
|
Sample[] processedAudio = null;
|
||||||
|
|
||||||
RecordingThread recordingThread;
|
RecordingThread recordingThread;
|
||||||
|
|
||||||
@@ -391,7 +392,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return text;
|
if (effectChain == null) return text;
|
||||||
|
if (effectChain.equals("none")) return text;
|
||||||
|
Effect e = AudiobookRecorder.window.effects.get(effectChain);
|
||||||
|
if (e == null) return text;
|
||||||
|
return text + " (" + e.toString() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRecording() {
|
public boolean isRecording() {
|
||||||
@@ -560,6 +565,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
audioData = null;
|
audioData = null;
|
||||||
|
processedAudio = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean lockedInCache() {
|
public boolean lockedInCache() {
|
||||||
@@ -669,8 +675,11 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void setGain(double g) {
|
public void setGain(double g) {
|
||||||
if (g <= 0.0001d) g = 1.0d;
|
if (g <= 0.0001d) g = 1.0d;
|
||||||
if (g == gain) return;
|
if (g == gain) return;
|
||||||
|
|
||||||
|
if (gain != g) {
|
||||||
|
clearCache();
|
||||||
|
}
|
||||||
gain = g;
|
gain = g;
|
||||||
clearCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getGain() {
|
public double getGain() {
|
||||||
@@ -952,10 +961,12 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
public Sample[] getProcessedAudioData() {
|
public Sample[] getProcessedAudioData() {
|
||||||
loadFile();
|
loadFile();
|
||||||
|
if (processedAudio != null) return processedAudio;
|
||||||
|
|
||||||
if (audioData == null) return null;
|
if (audioData == null) return null;
|
||||||
Sample[] samples = new Sample[audioData.length];
|
processedAudio = new Sample[audioData.length];
|
||||||
for (int i = 0; i < audioData.length; i++) {
|
for (int i = 0; i < audioData.length; i++) {
|
||||||
samples[i] = new Sample(audioData[i].left, audioData[i].right);
|
processedAudio[i] = new Sample(audioData[i].left, audioData[i].right);
|
||||||
}
|
}
|
||||||
// Add processing in here.
|
// Add processing in here.
|
||||||
|
|
||||||
@@ -965,7 +976,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
|
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
eff.init(getAudioFormat().getFrameRate());
|
eff.init(getAudioFormat().getFrameRate());
|
||||||
eff.process(samples);
|
eff.process(processedAudio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effectChain != null) {
|
if (effectChain != null) {
|
||||||
@@ -974,17 +985,17 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
eff = AudiobookRecorder.window.effects.get(effectChain);
|
eff = AudiobookRecorder.window.effects.get(effectChain);
|
||||||
if (eff != null) {
|
if (eff != null) {
|
||||||
eff.init(getAudioFormat().getFrameRate());
|
eff.init(getAudioFormat().getFrameRate());
|
||||||
eff.process(samples);
|
eff.process(processedAudio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add final master gain stage
|
// Add final master gain stage
|
||||||
for (int i = 0; i < samples.length; i++) {
|
for (int i = 0; i < processedAudio.length; i++) {
|
||||||
samples[i].left = samples[i].left * gain;
|
processedAudio[i].left = processedAudio[i].left * gain;
|
||||||
samples[i].right = samples[i].right * gain;
|
processedAudio[i].right = processedAudio[i].right * gain;
|
||||||
}
|
}
|
||||||
return samples;
|
return processedAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sample[] getDoubleAudioData() {
|
public Sample[] getDoubleAudioData() {
|
||||||
@@ -1028,6 +1039,9 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setEffectChain(String key) {
|
public void setEffectChain(String key) {
|
||||||
|
if ((effectChain != null) && (!effectChain.equals(key))) {
|
||||||
|
clearCache();
|
||||||
|
}
|
||||||
effectChain = key;
|
effectChain = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user