// 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.)