// MIDI 1: Note on / off events global Event midiMessage; global int midiCommand; global int midiNote; global int midiVelocity; TriOsc t => ADSR adsr => dac; adsr.set( 0.1::second, 0.3::second, 0.5, 0.7::second ); false => int alreadyOn; 0 => int mostRecentOn; fun void RespondToMidi() { while( true ) { midiMessage => now; if( midiCommand >= 144 && midiCommand < 160 ) { if( midiVelocity > 0 ) { NoteOn( midiNote, midiVelocity ); } else { NoteOff( midiNote ); } } else if( midiCommand >= 128 && midiCommand < 144 ) { NoteOff( midiNote ); } else { <<< "unknown midi command:", midiCommand, midiNote, midiVelocity >>>; } } } spork ~ RespondToMidi(); fun void NoteOn( int note, int velocity ) { <<< "on:", note, velocity >>>; note => Std.mtof => float newFreq; velocity * 1.0 / 127.0 => float newGain; if( !alreadyOn ) { adsr.keyOn(1); newFreq => t.freq; newGain => adsr.gain; note => mostRecentOn; true => alreadyOn; } else { spork ~ SlideFreq( newFreq, 0.05::second ); spork ~ SlideGain( newGain, 0.05::second ); } } fun void NoteOff( int note ) { <<< "off:", note >>>; if( note == mostRecentOn ) { adsr.keyOff(1); false => alreadyOn; 0 => mostRecentOn; } } fun void SlideFreq( float newFreq, dur slideTime ) { t.freq() => float oldFreq; 1000 => int numSteps; slideTime / numSteps => dur delta; ( newFreq - oldFreq ) / numSteps => float freqDelta; for( int i; i < numSteps; i++ ) { oldFreq + freqDelta * i => t.freq; delta => now; } newFreq => t.freq; } fun void SlideGain( float newGain, dur slideTime ) { t.gain() => float oldGain; 1000 => int numSteps; slideTime / numSteps => dur delta; ( newGain - oldGain ) / numSteps => float gainDelta; for( int i; i < numSteps; i++ ) { oldGain + gainDelta * i => t.gain; delta => now; } newGain => t.gain; } while( true ) { 1::second => now; }

Click the desired MIDI device:

(Please note, the Web MIDI API is not implemented yet in Firefox or Safari.)

shredcodetimeremove