package jmslexamples.jsyn; import com.softsynth.jmsl.JMSL; import com.softsynth.jmsl.MusicJob; import com.softsynth.jsyn.*; /** * FMNoodler noodles around with the frequency and modulation * parameters of an FM pair. */ public class FMNoodler extends MusicJob { int tickNumber; static double lastFreq = (float) 400.0; /* Shared by all noodlers so they stay together. */ public final static int LEFT = 1 << 0; public final static int RIGHT = 1 << 1; public FMPairBlaster fmPair; // MOD ND, used to be FMPair public LineOut myOut; double duration = 1.0; public FMNoodler(double duration, int flags) throws SynthException { super(); System.out.println("FMNoodler(" + duration + ", " + flags); this.duration = duration; try { /* Make FM pair. */ double seconds = duration / Synth.getTickRate(); fmPair = new FMPairBlaster(0.1 * seconds); myOut = new LineOut(); /* Connect oscillator to left|right channels of Line_Out. */ if ((flags & LEFT) != 0) fmPair.output.connect(0, myOut.input, 0); if ((flags & RIGHT) != 0) fmPair.output.connect(0, myOut.input, 1); } catch (SynthException e) { SynthAlert.showError(null, e); } lastFreq = pickNewFrequency(); } public FMNoodler(int duration) throws SynthException { this(duration, FMNoodler.LEFT + FMNoodler.RIGHT); } /** * Pick new frequency based on random whole ratio of previous frequency. */ synchronized double pickNewFrequency() throws SynthException { double newFreq; int numer, denom; /* Choose whole number ratio. */ numer = ((int) (Math.random() * 8.0)) + 1; denom = ((int) (Math.random() * 8.0)) + 1; newFreq = (lastFreq * numer) / denom; /* Octave folding to bring in range. */ while (newFreq < 100.0) newFreq *= 2.0; while (newFreq > 3000.0) newFreq *= 0.5; lastFreq = newFreq; return newFreq; } public synchronized void trigger(int timestamp, double frequency) throws SynthException { } public double start(double playTime) throws InterruptedException { int itime = (int) JMSL.clock.timeToNative(playTime); try { myOut.start(itime); fmPair.start(itime); } catch (SynthException e) { System.err.println(e); } return playTime; } public double repeat(double playTime) throws InterruptedException { int itime = (int) JMSL.clock.timeToNative(playTime); try { double prevFreq = lastFreq; double frequency = pickNewFrequency(); fmPair.trigger(itime, frequency, prevFreq, Math.random() * 8.0); playTime += duration; } catch (SynthException e) { SynthAlert.showError(null, e); } return playTime; } public double stop(double playTime) throws InterruptedException { try { // myOut.stop(playTime); // fmPair.stop(playTime); myOut.stop(); fmPair.stop(); } catch (SynthException e) { System.err.println(e); } return playTime; } }