aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Burk <[email protected]>2015-01-02 13:23:30 -0800
committerPhil Burk <[email protected]>2015-04-29 08:11:10 -0700
commit7aec269a333d43cc226a0c9c30986e4b50bafa28 (patch)
tree8029f57340ef5211586ea21d8a63614cfb1a9ae9
parentd3c74876db36598813068ce0bb8ea887e41a1c71 (diff)
Use AudioMath for pitch to frequency conversion.
Fix ListDevices default. Cleanup interpolator in AutoCorrelator. Remove empty string from SubtractiveSynth library.
-rw-r--r--src/com/jsyn/instruments/SubtractiveSynthVoice.java3
-rw-r--r--src/com/jsyn/unitgen/PitchDetector.java2
-rw-r--r--src/com/jsyn/util/AutoCorrelator.java42
-rw-r--r--tests/com/jsyn/benchmarks/BenchJSyn.java52
-rw-r--r--tests/com/jsyn/examples/ListAudioDevices.java2
-rw-r--r--tests/com/jsyn/examples/PlayChords.java12
6 files changed, 56 insertions, 57 deletions
diff --git a/src/com/jsyn/instruments/SubtractiveSynthVoice.java b/src/com/jsyn/instruments/SubtractiveSynthVoice.java
index 9ea593e..af3329e 100644
--- a/src/com/jsyn/instruments/SubtractiveSynthVoice.java
+++ b/src/com/jsyn/instruments/SubtractiveSynthVoice.java
@@ -135,6 +135,7 @@ public class SubtractiveSynthVoice extends Circuit implements UnitVoice {
cutoffRange.set(500.0);
filter.Q.set(3.0);
break;
+ case 2:
default:
ampEnv.attack.set(0.1);
ampEnv.decay.set(0.3);
@@ -147,7 +148,7 @@ public class SubtractiveSynthVoice extends Circuit implements UnitVoice {
}
static String[] presetNames = {
- "FastSaw", "SlowSaw", "BrightSaw", ""
+ "FastSaw", "SlowSaw", "BrightSaw"
};
static class MyVoiceDescription extends VoiceDescription {
diff --git a/src/com/jsyn/unitgen/PitchDetector.java b/src/com/jsyn/unitgen/PitchDetector.java
index 59bba69..da6a0e3 100644
--- a/src/com/jsyn/unitgen/PitchDetector.java
+++ b/src/com/jsyn/unitgen/PitchDetector.java
@@ -42,7 +42,7 @@ public class PitchDetector extends UnitGenerator {
protected SignalCorrelator signalCorrelator;
private double lastFrequency = 440.0;
- private double lastPeriod = 44100.0 / lastFrequency; // result of analysis
+ private double lastPeriod = 44100.0 / lastFrequency; // result of analysis TODO update for 48000
private double lastConfidence = 0.0; // Measure of confidence in the result.
private static final int LOWEST_FREQUENCY = 40;
diff --git a/src/com/jsyn/util/AutoCorrelator.java b/src/com/jsyn/util/AutoCorrelator.java
index 5512abb..2996036 100644
--- a/src/com/jsyn/util/AutoCorrelator.java
+++ b/src/com/jsyn/util/AutoCorrelator.java
@@ -193,42 +193,9 @@ public class AutoCorrelator implements SignalCorrelator {
return interpolatePeak(d1, d2, d3) + indexMax;
}
- // return offset between -1.0 and +1.0 from center
+ // Use quadratic fit to return offset between -0.5 and +0.5 from center.
protected static double interpolatePeak(double d1, double d2, double d3) {
- // System.out.println( " d1 = " + d1 + ", d2 = " + d2 + ", d3 = "
- // + d3 );
- // Make sure d2 is a maximum or result will blow up.
- if (d1 > d2)
- return -1.0;
- else if (d3 > d2)
- return 1.0;
-
- // The interpolated maximum should be the same
- // point where the line between slopes crosses zero.
- double y2 = d3 - d2;
- double y1 = d2 - d1;
- // System.out.println(" y1 = " + y1 + ", y2 = " + y2 );
- // Derive equations for interpolated maximum.
- // y = ax + b
- // when y is zero, x = -b/a
- // y2 = a*x2 + b
- // y1 = a*x1 + b
- // b = y2-a*x2
- // y1 = a*x1 + (y2 - a*x2)
- // y1 - y2 = a*(x1 - x2) ; x1 and x2 are one from each other
- // y1 - y2 = a*(-1)
- // a = y2 - y1
- // for zero crossing:
- // 0 = ax+b
- // -ax = b
- // x = -b / a
- // = -(y2-a*x2)/a
- // = (a*x2 -y2)/a
- // = x2 - y2/a
- // = x2 - (y2/(y2-y1))
- double x2 = 0.5;
- double precise = x2 - (y2 / (y2 - y1));
- return precise;
+ return 0.5 * (d1 - d3) / (d1 - (2.0 * d2) + d3);
}
// Calculate a little more for each sample.
@@ -293,7 +260,6 @@ public class AutoCorrelator implements SignalCorrelator {
@Override
public boolean addSample(double value) {
- boolean updated = false;
double average = (value + previousSample) * 0.5;
previousSample = value;
@@ -304,9 +270,7 @@ public class AutoCorrelator implements SignalCorrelator {
}
buffer[cursor] = (float) average;
- updated = incrementalAnalysis();
-
- return updated;
+ return incrementalAnalysis();
}
@Override
diff --git a/tests/com/jsyn/benchmarks/BenchJSyn.java b/tests/com/jsyn/benchmarks/BenchJSyn.java
index 51e09a4..5b8d128 100644
--- a/tests/com/jsyn/benchmarks/BenchJSyn.java
+++ b/tests/com/jsyn/benchmarks/BenchJSyn.java
@@ -22,9 +22,13 @@ package com.jsyn.benchmarks;
import com.jsyn.JSyn;
import com.jsyn.Synthesizer;
import com.jsyn.unitgen.PassThrough;
+import com.jsyn.unitgen.PitchDetector;
import com.jsyn.unitgen.SawtoothOscillator;
import com.jsyn.unitgen.SawtoothOscillatorBL;
import com.jsyn.unitgen.SawtoothOscillatorDPW;
+import com.jsyn.unitgen.SineOscillator;
+import com.jsyn.unitgen.SquareOscillator;
+import com.jsyn.unitgen.SquareOscillatorBL;
import com.jsyn.unitgen.UnitOscillator;
import com.softsynth.math.FourierMath;
@@ -57,11 +61,18 @@ public class BenchJSyn {
double realTime = 10.0;
int count = 40;
- benchFFTDouble();
- benchFFTFloat();
- benchmarkOscillator(SawtoothOscillator.class, count, realTime);
- benchmarkOscillator(SawtoothOscillatorDPW.class, count, realTime);
- benchmarkOscillator(SawtoothOscillatorBL.class, count, realTime);
+ // benchFFTDouble();
+ // benchFFTFloat();
+ /*
+ * realTime = 20.0; benchmarkOscillator(SawtoothOscillator.class, count, realTime);
+ * benchmarkOscillator(SawtoothOscillatorDPW.class, count, realTime);
+ * benchmarkOscillator(SawtoothOscillatorBL.class, count, realTime);
+ */
+ benchmarkOscillator(SquareOscillator.class, count, realTime);
+ benchmarkOscillator(SquareOscillatorBL.class, count, realTime);
+
+ benchmarkOscillator(SineOscillator.class, count, realTime);
+ benchmarkPitchDetector(count, realTime);
}
@@ -164,6 +175,37 @@ public class BenchJSyn {
stopSynth();
}
+ private void benchmarkPitchDetector(int count, double realTime) throws InstantiationException,
+ IllegalAccessException, InterruptedException {
+ startSynth();
+
+ PitchDetector detector = new PitchDetector();
+ synth.add(detector);
+ double frequency = 198.0;
+ double period = synth.getFrameRate() / frequency;
+ // simple harmonic synthesis
+ for (int i = 0; i < count; i++) {
+ SineOscillator osc = new SineOscillator();
+ synth.add(osc);
+ osc.frequency.set(frequency * (i + 1));
+ osc.amplitude.set(0.5 * (1.0 - (i * 0.2)));
+ osc.output.connect(detector.input);
+ }
+ detector.start();
+ startTiming();
+ synth.sleepFor(realTime);
+ endTiming(PitchDetector.class, count, realTime);
+
+ double measuredPeriod = detector.period.getValue();
+ double confidence = detector.confidence.getValue();
+ System.out.println("period = " + period + ", measured = " + measuredPeriod
+ + ", confidence = " + confidence);
+ if (confidence > 0.1) {
+ assert (Math.abs(measuredPeriod - period) < 0.1);
+ }
+ stopSynth();
+ }
+
private void endTiming(Class<?> clazz, int count, double realTime) {
endTime = System.nanoTime();
double elapsedTime = (endTime - startTime) * 1E-9;
diff --git a/tests/com/jsyn/examples/ListAudioDevices.java b/tests/com/jsyn/examples/ListAudioDevices.java
index 6c5372d..dceaa0d 100644
--- a/tests/com/jsyn/examples/ListAudioDevices.java
+++ b/tests/com/jsyn/examples/ListAudioDevices.java
@@ -33,7 +33,7 @@ public class ListAudioDevices {
int maxInputs = audioManager.getMaxInputChannels(i);
int maxOutputs = audioManager.getMaxInputChannels(i);
boolean isDefaultInput = (i == audioManager.getDefaultInputDeviceID());
- boolean isDefaultOutput = (i == audioManager.getDefaultInputDeviceID());
+ boolean isDefaultOutput = (i == audioManager.getDefaultOutputDeviceID());
System.out.println("#" + i + " : " + deviceName);
System.out.println(" max inputs : " + maxInputs
+ (isDefaultInput ? " (default)" : ""));
diff --git a/tests/com/jsyn/examples/PlayChords.java b/tests/com/jsyn/examples/PlayChords.java
index 0b1ae2e..28cab5f 100644
--- a/tests/com/jsyn/examples/PlayChords.java
+++ b/tests/com/jsyn/examples/PlayChords.java
@@ -22,6 +22,7 @@ import com.jsyn.instruments.SubtractiveSynthVoice;
import com.jsyn.unitgen.LineOut;
import com.jsyn.unitgen.UnitVoice;
import com.jsyn.util.VoiceAllocator;
+import com.softsynth.math.AudioMath;
import com.softsynth.shared.time.TimeStamp;
/**
@@ -167,21 +168,12 @@ public class PlayChords {
}
private void noteOn(double time, int noteNumber) {
- double frequency = convertPitchToFrequency(noteNumber);
+ double frequency = AudioMath.pitchToFrequency(noteNumber);
double amplitude = 0.2;
TimeStamp timeStamp = new TimeStamp(time);
allocator.noteOn(noteNumber, frequency, amplitude, timeStamp);
}
- /**
- * Calculate frequency in Hertz based on MIDI pitch. Middle C is 60.0. You can use fractional
- * pitches so 60.5 would give you a pitch half way between C and C#.
- */
- double convertPitchToFrequency(double pitch) {
- final double concertA = 440.0;
- return concertA * Math.pow(2.0, ((pitch - 69) * (1.0 / 12.0)));
- }
-
public static void main(String[] args) {
new PlayChords().test();
}