package com.jsyn.examples; import com.jsyn.JSyn; import com.jsyn.Synthesizer; import com.jsyn.ports.UnitOutputPort; import com.jsyn.unitgen.Add; import com.jsyn.unitgen.AsymptoticRamp; import com.jsyn.unitgen.Circuit; import com.jsyn.unitgen.LineOut; import com.jsyn.unitgen.Pan; import com.jsyn.unitgen.SawtoothOscillatorDPW; import com.jsyn.unitgen.SineOscillator; import com.jsyn.unitgen.UnitOscillator; import com.jsyn.unitgen.UnitSource; /** * Make a bunch of oscillators that swarm around a moving frequency. * * @author Phil Burk (C) 2009 Mobileer Inc * */ public class SwarmOfOscillators { private Synthesizer synth; Follower[] followers; SineOscillator lfo; LineOut lineOut; private Add tiePoint; private static final int NUM_FOLLOWERS = 30; class Follower extends Circuit implements UnitSource { UnitOscillator osc; AsymptoticRamp lag; Pan panner; Follower() { // Add a tone generator. add( osc = new SawtoothOscillatorDPW() ); osc.amplitude.set( 0.03 ); // Use a lag to smoothly change frequency. add( lag = new AsymptoticRamp() ); double hlife = 0.01 + (Math.random() * 0.9); lag.halfLife.set( hlife ); // Set left/right pan randomly between -1.0 and +1.0. add( panner = new Pan() ); panner.pan.set((Math.random() * 2.0) - 1.0); // Track the frequency coming through the tiePoint. tiePoint.output.connect( lag.input ); // Add the LFO offset. lfo.output.connect( lag.input ); lag.output.connect( osc.frequency ); // Connect the oscillator to the left and right audio output. osc.output.connect( panner.input ); } public UnitOutputPort getOutput() { return panner.output; } } private void test() { synth = JSyn.createSynthesizer(); // Add an output mixer. synth.add( lineOut = new LineOut() ); // Add a unit just to distribute the control frequency. synth.add( tiePoint = new Add() ); synth.add( lfo = new SineOscillator() ); lfo.amplitude.set( 40.0 ); lfo.frequency.set( 2.3 ); followers = new Follower[NUM_FOLLOWERS]; for( int i = 0; i < followers.length; i++ ) { Follower follower = new Follower(); synth.add( follower ); // Every follower can connect directly to the lineOut because all input ports are mixers. follower.getOutput().connect( 0, lineOut.input, 0 ); follower.getOutput().connect( 1, lineOut.input, 1 ); followers[i] = follower; } // Start synthesizer using default stereo output at 44100 Hz. synth.start(); // We only need to start the LineOut. It will pull data from the // oscillator. lineOut.start(); // Get synthesizer time in seconds. double timeNow = synth.getCurrentTime(); // Advance to a near future time so we have a clean start. double duration = 0.9; double time = timeNow + duration; double freq = 400.0; // hertz tiePoint.inputA.set( freq, time ); // Randomly change the target frequency for the followers. try { for( int i = 0; i < 20; i++ ) { // Schedule this to happen a bit later. time += duration; freq = 200.0 + (Math.random() * 500.0); tiePoint.inputA.set( freq, time ); // Sleep while the sound is being generated in the background // thread. synth.sleepUntil( time - 0.2 ); } } catch( InterruptedException e ) { e.printStackTrace(); } System.out.format( "CPU usage = %4.2f%c\n", synth.getUsage()*100,'%' ); // Stop everything. synth.stop(); } public static void main( String[] args ) { new SwarmOfOscillators().test(); } }