package com.jsyn.examples; import java.io.File; import java.io.IOException; import com.jsyn.JSyn; import com.jsyn.Synthesizer; import com.jsyn.data.SegmentedEnvelope; import com.jsyn.unitgen.LineOut; import com.jsyn.unitgen.SawtoothOscillatorBL; import com.jsyn.unitgen.UnitOscillator; import com.jsyn.unitgen.VariableRateDataReader; import com.jsyn.unitgen.VariableRateMonoReader; import com.jsyn.util.WaveRecorder; /** * Modulate the amplitude of an oscillator using a segmented envelope. * * @author Phil Burk (C) 2010 Mobileer Inc * */ public class PlaySegmentedEnvelope { private Synthesizer synth; private UnitOscillator osc; private LineOut lineOut; private SegmentedEnvelope envelope; private VariableRateDataReader envelopePlayer; private WaveRecorder recorder; private final static boolean useRecorder = true; private void test() throws IOException { // Create a context for the synthesizer. synth = JSyn.createSynthesizer(); // Add a tone generator. synth.add( osc = new SawtoothOscillatorBL() ); // Add an envelope player. synth.add( envelopePlayer = new VariableRateMonoReader() ); if( useRecorder ) { File waveFile = new File( "temp_recording.wav" ); // Default is stereo, 16 bits. recorder = new WaveRecorder( synth, waveFile ); System.out.println( "Writing to WAV file " + waveFile.getAbsolutePath() ); } // Create an envelope consisting of (duration,value) pairs. double[] pairs = { 0.1, 1.0, 0.2, 0.3, 0.6, 0.0 }; envelope = new SegmentedEnvelope( pairs ); // Add an output mixer. synth.add( lineOut = new LineOut() ); envelopePlayer.output.connect( osc.amplitude ); // Connect the oscillator to the output. osc.output.connect( 0, lineOut.input, 0 ); osc.output.connect( 0, lineOut.input, 1 ); // Start synthesizer using default stereo output at 44100 Hz. synth.start(); if( useRecorder ) { osc.output.connect( 0, recorder.getInput(), 0 ); envelopePlayer.output.connect( 0, recorder.getInput(), 1 ); // When we start the recorder it will pull data from the oscillator // and sweeper. recorder.start(); } // We only need to start the LineOut. It will pull data from the other // units. lineOut.start(); try { // --------------------------------------------- // Queue the entire envelope to play once. envelopePlayer.dataQueue.queue( envelope ); synth.sleepFor( 2.0 ); // --------------------------------------------- // Queue the attack, then sustain for a while, then queue the // release. osc.frequency.set( 750.0 ); envelopePlayer.dataQueue.queue( envelope, 0, 2 ); // attack synth.sleepFor( 2.0 ); envelopePlayer.dataQueue.queue( envelope, 2, 1 ); // release synth.sleepFor( 2.0 ); // --------------------------------------------- // Queue the attack, then sustain for a while, then queue the // release. But this time use the sustain loop points. osc.frequency.set( 950.0 ); // For noteOn, we want to play frames 0 and 1 then stop before 2. envelope.setSustainBegin( 2 ); envelope.setSustainEnd( 2 ); envelopePlayer.dataQueue.queueOn( envelope ); // attack synth.sleepFor( 2.0 ); envelopePlayer.dataQueue.queueOff( envelope ); // release synth.sleepFor( 2.0 ); // --------------------------------------------- // Queue the entire envelope to play 4 times (3 loops back). osc.frequency.set( 350.0 ); envelopePlayer.dataQueue.queueLoop( envelope, 0, envelope.getNumFrames(), 3 ); synth.sleepFor( 5.0 ); // --------------------------------------------- // Queue the entire envelope as a repeating loop. // It will loop until something else is queued. osc.frequency.set( 450.0 ); envelopePlayer.dataQueue.queueLoop( envelope, 0, envelope.getNumFrames() ); envelopePlayer.rate.set( 3.0 ); synth.sleepFor( 5.0 ); // Queue last frame to stop the looping. envelopePlayer.dataQueue.queue( envelope, envelope.getNumFrames() - 1, 1 ); synth.sleepFor( 1.0 ); if( recorder != null ) { recorder.stop(); recorder.close(); } } catch( InterruptedException e ) { e.printStackTrace(); } // Stop everything. synth.stop(); } public static void main( String[] args ) { try { new PlaySegmentedEnvelope().test(); } catch( IOException e ) { e.printStackTrace(); } } }