Added LFO ring modulator

This commit is contained in:
2019-01-19 16:23:33 +00:00
parent 887b2a9205
commit 73d4feb679
10 changed files with 119 additions and 21 deletions

View File

@@ -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"

View File

@@ -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;

View File

@@ -525,6 +525,7 @@ public class AudiobookRecorder extends JFrame {
if (selectedSentence != null) {
int i = effectChain.getSelectedIndex();
KVPair<String, String> 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<KVPair<String, String>> defEff = new JComboBox<KVPair<String, String>>();
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<String, String> p = new KVPair<String, String>(k, effects.get(k).toString());
defEff.addItem(p);
i++;
}
KVPair<String, String> p = new KVPair<String, String>(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<String, String> ent = effectChain.getItemAt(sel);
while (effectChain.getItemCount() > 0) {
effectChain.removeItemAt(0);
}
@@ -2677,6 +2700,11 @@ System.err.println(format);
KVPair<String, String> p = new KVPair<String, String>(k, e.toString());
effectChain.addItem(p);
}
if (ent != null) {
setEffectChain(ent.getKey());
} else {
setEffectChain(defaultEffectChain);
}
}
public void setEffectChain(String key) {

View File

@@ -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;

View File

@@ -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<DelayLineStore> delayLines;

View File

@@ -8,4 +8,5 @@ public interface Effect {
public ArrayList<Effect> getChildEffects();
public void dump();
public void init(double sr);
public String toString();
}

View File

@@ -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<Effect> effects;

View File

@@ -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<Effect> 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(); }
}

View File

@@ -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());

View File

@@ -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++) {