diff options
author | Phil Burk <[email protected]> | 2015-01-02 13:23:30 -0800 |
---|---|---|
committer | Phil Burk <[email protected]> | 2015-04-29 08:11:10 -0700 |
commit | 7aec269a333d43cc226a0c9c30986e4b50bafa28 (patch) | |
tree | 8029f57340ef5211586ea21d8a63614cfb1a9ae9 | |
parent | d3c74876db36598813068ce0bb8ea887e41a1c71 (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.java | 3 | ||||
-rw-r--r-- | src/com/jsyn/unitgen/PitchDetector.java | 2 | ||||
-rw-r--r-- | src/com/jsyn/util/AutoCorrelator.java | 42 | ||||
-rw-r--r-- | tests/com/jsyn/benchmarks/BenchJSyn.java | 52 | ||||
-rw-r--r-- | tests/com/jsyn/examples/ListAudioDevices.java | 2 | ||||
-rw-r--r-- | tests/com/jsyn/examples/PlayChords.java | 12 |
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(); } |