class MidiHandler { // Open MIDI Device. 0 is the first device, 1 is the second and so on. MidiIn input; 0 => int device; if(!input.open(device)) { <<< "Could not open MIDI input device." >>>; me.exit(); } // MIDI Event IDs int codes[0]; 144 => codes["NoteOn"]; 128 => codes["NoteOff"]; fun void run() { // Now handle incoming events. MidiMsg message; while(true) { input => now; while(input.recv(message)) { message.data1 => int code; if(code == codes["NoteOn"]) { spork ~ noteOn(message.data2, message.data3); } else if(code == codes["NoteOff"]) { spork ~ noteOff(message.data2, message.data3); } else { <<< "Unhandled MIDI Message: ", message.data1, message.data2, message.data3 >>>; } } } } fun void noteOn(int pitch, int velocity) { <<< "Note On: ", pitch, velocity >>>; } fun void noteOff(int pitch, int velocity) { <<< "Note Off:", pitch, velocity >>>; } } class Bank { // Initialize oscilators and set the partials relative to the fundamental SinOsc @ oscilators[6]; [ 1.0, 0.1, 0.2, 0.4, 0.1, 0.2 ] @=> float partials[]; for(0 => int i; i < oscilators.cap(); i++) { SinOsc oscilator => dac; 0 => oscilator.gain; oscilator @=> oscilators[i]; } 0 => int m_pitch; // Handle note on events fun void noteOn(int pitch, int velocity) { Std.mtof(pitch) => float frequency; velocity / 127.0 => float gain; for(0 => int i; i < oscilators.cap(); i++) { frequency * (i + 1) => oscilators[i].freq; gain * partials[i] => oscilators[i].gain; } pitch => m_pitch; } fun void noteOff() { for(0 => int i; i < oscilators.cap(); i++) { 0 => oscilators[i].gain; } 0 => m_pitch; } fun int getPitch() { return m_pitch; } } class Synth extends MidiHandler { Bank @ banks[6]; for(0 => int i; i < banks.cap(); i++) { new Bank @=> banks[i]; } fun void noteOn(int pitch, int velocity) { for(0 => int i; i < banks.cap(); i++) { if(banks[i].getPitch() == 0) { banks[i].noteOn(pitch, velocity); return; } } } fun void noteOff(int pitch, int velocity) { for(0 => int i; i < banks.cap(); i++) { if(banks[i].getPitch() == pitch) { banks[i].noteOff(); return; } } } } Synth poly; poly.run();