Hid hi1; HidMsg msg1; Hid hi2; HidMsg msg2; // synchronize periods 200::ms => dur T; T - (now % T) => now; SinOsc s => NRev n => LPF ls => dac; TriOsc bass => n => ADSR e => LPF lb => dac; 0.02 => n.mix; 0.1 => s.gain; 0 => s.freq; 0 => bass.freq; 0 => bass.gain; e.set( 0.05::T, 0.05::T, .5, 1::T ); 500 => ls.freq; 500 => lb.freq; 0 => int device; if( me.args() ) me.arg(0) => Std.atoi => device; // set up keyboard input if( !hi1.openKeyboard( device ) ) me.exit(); <<< "keyboard '" + hi1.name() + "' ready", "" >>>; // set up mouse input if( !hi2.openMouse( device ) ) me.exit(); <<< "mouse '" + hi2.name() + "' ready", "" >>>; 0 => int currentMidiRoot; [0, 3, 5, 7, 10, 11, 12] @=> int pitchClasses[]; dur rhythms[4][pitchClasses.size()]; int whichRhythm; // there will be 12 pitches total, i.e. 12 or 6 T for (int i; i < pitchClasses.size(); i++) { 1::T @=> rhythms[0][i]; 0.5::T @=> rhythms[1][i]; } [0.5::T, 1::T, 0.5::T, 1::T, 0.5::T, 1::T, 1.5::T] @=> rhythms[2]; [3::T, 1::T, 1::T, 1::T, 3::T, 1::T, 1::T] @=> rhythms[3]; spork ~ arp(); spork ~ bassline(); spork ~ mouseInput(); // infinite event loop while( true ) { // wait on event hi1 => now; // get one or more messages while (hi1.recv(msg1)) { // check for action type if (msg1.isButtonDown()) { //<<< "down:", msg.which, "(code)", msg.key, "(usb key)", msg.ascii, "(ascii)" >>>; if (msg1.ascii >= 65 && msg1.ascii <= 71) { asciiToMidi(msg1.ascii) => currentMidiRoot; } else if (msg1.ascii >= 49 && msg1.ascii <= 52) { msg1.ascii - 49 => whichRhythm; } else { if (msg1.key == 82) { // raise by half step currentMidiRoot++; } else if (msg1.key == 81) { // lower by half step currentMidiRoot--; } } } } } fun void mouseInput() { // infinite event loop while( true ) { // wait on event hi2 => now; // get one or more messages while (hi2.recv(msg2)) { // check for action type if (msg2.isMouseMotion()) { msg2.cursorY => lb.freq; msg2.cursorX => ls.freq; } } } } fun void arp() { while (true) { whichRhythm => int rhythmNow; for (int i; i < pitchClasses.size(); i++) { Std.mtof(currentMidiRoot + pitchClasses[i]) => s.freq; rhythms[rhythmNow][i] => now; } pitchClasses.size() - 2 => int i; for (i; i > 0; i--) { Std.mtof(currentMidiRoot + pitchClasses[i]) => s.freq; rhythms[rhythmNow][i] => now; } } } fun void bassline() { while (true) { if (currentMidiRoot != 0) { 0.1 => bass.gain; Std.mtof(currentMidiRoot - 24) => bass.freq; } e.keyOn(); 2::T => now; e.keyOff(); e.releaseTime() => now; 1::T => now; } } fun int asciiToMidi(int ascii) { 0 => int midi; if (ascii == 67) // C5 { 72 => midi; } else if (ascii == 68) // D5 { 74 => midi; } else if (ascii == 69) // E5 { 76 => midi; } else if (ascii == 70) // F5 { 77 => midi; } else if (ascii == 71) // G5 { 79 => midi; } else if (ascii == 65) // A5 { 81 => midi; } else if (ascii == 66) // B5 { 83 => midi; } return midi; }