aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Burk <[email protected]>2016-12-01 07:16:24 -0800
committerGitHub <[email protected]>2016-12-01 07:16:24 -0800
commitd8b670ca9dd985fd987cae992019ae1b77a83d8f (patch)
tree583b57862b4d24162dd8b095f874b0fdd44f068e
parent10ffa9acf32c7fb40f084d9cef9a0ff5e608fc0c (diff)
parent265381fa6d885f7fa7fdb76c0e6bf0c9511c63b4 (diff)
Merge pull request #44 from philburk/floatshaper
Floatshaper
-rw-r--r--src/com/jsyn/data/FloatSample.java30
-rw-r--r--tests/com/jsyn/examples/PlaySampleWaveShaper.java112
2 files changed, 133 insertions, 9 deletions
diff --git a/src/com/jsyn/data/FloatSample.java b/src/com/jsyn/data/FloatSample.java
index 78c71d7..0855786 100644
--- a/src/com/jsyn/data/FloatSample.java
+++ b/src/com/jsyn/data/FloatSample.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -25,7 +25,7 @@ import com.jsyn.util.SampleLoader;
/**
* Store multi-channel floating point audio data in an interleaved buffer. The values are stored as
* 32-bit floats. You can play samples using one of the readers, for example VariableRateMonoReader.
- *
+ *
* @author Phil Burk (C) 2010 Mobileer Inc
* @see SampleLoader
* @see FixedRateMonoReader
@@ -33,7 +33,7 @@ import com.jsyn.util.SampleLoader;
* @see VariableRateMonoReader
* @see VariableRateStereoReader
*/
-public class FloatSample extends AudioSample {
+public class FloatSample extends AudioSample implements Function {
private float[] buffer;
public FloatSample() {
@@ -59,7 +59,7 @@ public class FloatSample extends AudioSample {
/**
* Create an silent sample with enough memory to hold the audio data. The number of sample
* numbers in the array will be numFrames*channelsPerFrame.
- *
+ *
* @param numFrames number of sample groups. A stereo frame contains 2 samples.
* @param channelsPerFrame 1 for mono, 2 for stereo
*/
@@ -70,7 +70,7 @@ public class FloatSample extends AudioSample {
/**
* Allocate memory to hold the audio data. The number of sample numbers in the array will be
* numFrames*channelsPerFrame.
- *
+ *
* @param numFrames number of sample groups. A stereo frame contains 2 samples.
* @param channelsPerFrame 1 for mono, 2 for stereo
*/
@@ -83,7 +83,7 @@ public class FloatSample extends AudioSample {
/**
* Note that in a stereo sample, a frame has two values.
- *
+ *
* @param startFrame index of frame in the sample
* @param data data to be written
* @param startIndex index of first value in array
@@ -97,7 +97,7 @@ public class FloatSample extends AudioSample {
/**
* Note that in a stereo sample, a frame has two values.
- *
+ *
* @param startFrame index of frame in the sample
* @param data array to receive the data from the sample
* @param startIndex index of first location in array to start filling
@@ -112,7 +112,7 @@ public class FloatSample extends AudioSample {
/**
* Write the entire array to the sample. The sample data must have already been allocated with
* enough room to contain the data.
- *
+ *
* @param data
*/
public void write(float[] data) {
@@ -143,4 +143,16 @@ public class FloatSample extends AudioSample {
float target = buffer[index + 1];
return ((target - source) * phase) + source;
}
+
+ @Override
+ public double evaluate(double input) {
+ // Input ranges from -1 to +1
+ // Map it to range of sample with guard point.
+ double normalizedInput = (input + 1.0) * 0.5;
+ // Clip so it does not go out of range of the sample.
+ if (normalizedInput < 0.0) normalizedInput = 0.0;
+ else if (normalizedInput > 1.0) normalizedInput = 1.0;
+ double fractionalIndex = (getNumFrames() - 1.01) * normalizedInput;
+ return interpolate(fractionalIndex);
+ }
}
diff --git a/tests/com/jsyn/examples/PlaySampleWaveShaper.java b/tests/com/jsyn/examples/PlaySampleWaveShaper.java
new file mode 100644
index 0000000..73758dd
--- /dev/null
+++ b/tests/com/jsyn/examples/PlaySampleWaveShaper.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.examples;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.jsyn.JSyn;
+import com.jsyn.Synthesizer;
+import com.jsyn.data.FloatSample;
+import com.jsyn.data.Function;
+import com.jsyn.unitgen.FunctionEvaluator;
+import com.jsyn.unitgen.LineOut;
+import com.jsyn.unitgen.SineOscillator;
+import com.jsyn.util.SampleLoader;
+
+/**
+ * Play a sample from a WAV file using JSyn.
+ *
+ * @author Phil Burk (C) 2010 Mobileer Inc
+ */
+public class PlaySampleWaveShaper {
+ private Synthesizer synth;
+ private LineOut lineOut;
+
+ private void test() {
+
+ URL sampleFile;
+ try {
+ sampleFile = new URL("http://www.softsynth.com/samples/Clarinet.wav");
+ // sampleFile = new URL("http://www.softsynth.com/samples/NotHereNow22K.wav");
+ } catch (MalformedURLException e2) {
+ e2.printStackTrace();
+ return;
+ }
+
+ synth = JSyn.createSynthesizer();
+
+ FloatSample sample;
+ try {
+ // Add an output mixer.
+ synth.add(lineOut = new LineOut());
+
+ // Load the sample and display its properties.
+ SampleLoader.setJavaSoundPreferred(false);
+ sample = SampleLoader.loadFloatSample(sampleFile);
+ System.out.println("Sample has: channels = " + sample.getChannelsPerFrame());
+ System.out.println(" frames = " + sample.getNumFrames());
+ System.out.println(" rate = " + sample.getFrameRate());
+ System.out.println(" loopStart = " + sample.getSustainBegin());
+ System.out.println(" loopEnd = " + sample.getSustainEnd());
+
+ if (sample.getChannelsPerFrame() != 1) {
+ throw new RuntimeException("Can only use mono samples.");
+ }
+
+ System.out.println("eval -1.1 = " + sample.evaluate(-1.1));
+ System.out.println("eval -1.0 = " + sample.evaluate(-1.0));
+ System.out.println("eval 0.3 = " + sample.evaluate(0.3));
+ System.out.println("eval 1.0 = " + sample.evaluate(1.0));
+ System.out.println("eval 1.1 = " + sample.evaluate(1.1));
+
+ FunctionEvaluator shaper = new FunctionEvaluator();
+ shaper.function.set(sample);
+ synth.add(shaper);
+
+ shaper.output.connect(0, lineOut.input, 0);
+ shaper.output.connect(0, lineOut.input, 1);
+
+ SineOscillator osc = new SineOscillator();
+ osc.frequency.set(0.2);
+ osc.output.connect(shaper.input);
+ synth.add(osc);
+
+ // Start synthesizer using default stereo output at 44100 Hz.
+ synth.start();
+
+ // We only need to start the LineOut. It will pull data from the
+ // sample player.
+ lineOut.start();
+
+ // Wait until the sample has finished playing.
+ synth.sleepFor(5.0);
+
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // Stop everything.
+ synth.stop();
+ }
+
+ public static void main(String[] args) {
+ new PlaySampleWaveShaper().test();
+ }
+}