// Guitar Motion Sensor Software // Copyright 2008 Les Hall // This software is protected by the GNU General Public License // parameters 2 => int num_stages; // the number of effects chained in series 8 => int num_effects; // the number of effects available per channel 0 => int keyboard_device; // keyboard device number 0 => int mouse_device; // mouse device number 0 => int joystick_device; // joystick device number "GMS.wav" => string filename; // output filename "Betty" => string voice; // name of the subdirectory with voice samples in it ["StageZero.wav", "StageOne.wav", "StageTwo.wav", "StageThree.wav", "StageFour.wav", "StageFive.wav", "StageSix.wav", "StageSeven.wav", "Lock.wav"] @=> string stage_samps[]; // stage samples ["None.wav", "Reverb.wav", "Wah.wav", "Distortion.wav", "Tremolo.wav", "Bass.wav", "PitchShift.wav", "Volume.wav"] @=> string effect_samps[]; // effect samples ["xAcceleration.wav", "yAcceleration.wav", "zAcceleration.wav", "yPosition.wav", "None.wav"] @=> string axis_samps[]; // axis samples // variables Event key[3]; // signals that a key has been pressed Event potentiometer; // signals that the pot has been dialed Event accelerometer; // signals that an accelerometer has changed Shred potentiometer_adj[num_stages]; // shred objects for potentiometer adjust function Shred accelerometer_adj[num_stages]; // shred objects for accelerometer adjust function float extremeness[num_stages]; // the extremeness values, 0 to 1 float mouse_x; // horizontal mouse control value, 0 to 1 float prev_mouse_x; // previous mouse_x value float joystick_msg[axis_samps.cap ()]; // joystick control values int effect[num_stages]; // the effect assignments int axis[num_stages]; // the axis assignments 0 => int stage; // the current channel 1 => int lock; // the effects lock 0 => int exit; // true to exit program // Print Heading <<<"", "">>>; <<<"", "">>>; <<<"", "">>>; <<<" ______ _______ _______", "">>>; <<<"| ____ | | | |______", "">>>; <<<"|_____| | | | ______|", "">>>; <<<" Guitar Motion Sensor", "">>>; <<<"", "">>>; <<<"", "">>>; // class instantiations // // control objects print print_object; // the printer keyboard keyboard_object; // the keyboard interface mouse mouse_object; // the mouse interface joystick joystick_object; // the joystick interface stage_tracker stage_tracker_object; // the stage tracker effect_tracker effect_tracker_object; // the effect tracker axis_tracker axis_tracker_object; // the axis tracker // // effects objects reverb reverb_object[num_stages]; // the reverb objects wah wah_object[num_stages]; // the wah objects distortion distortion_object[num_stages]; // the distortion objects tremolo tremolo_object[num_stages]; // the tremolo objects bass bass_object[num_stages]; // the volume objects pitchshift pitchshift_object[num_stages]; // the volume objects volume volume_object[num_stages]; // the volume objects // // set effect object stages for (int i; i< num_stages; i++) { i => reverb_object[i].my_stage; i => wah_object[i].my_stage; i => distortion_object[i].my_stage; i => tremolo_object[i].my_stage; i => bass_object[i].my_stage; i => pitchshift_object[i].my_stage; i => volume_object[i].my_stage; } // the patch Gain node[num_stages+1]; // the connection nodes Gain none[num_stages]; // the null gain stages adc => node[0]; // the first connection for (int i; i < num_stages; i++) { node[i] => none[i] => node[i+1]; // hook up the null nodes } node[num_stages] => dac; // the last connection SndBuf stage_sndbuf[stage_samps.cap ()]; // the sound buffers for stage samples for (int i; i < stage_sndbuf.cap (); i++) { stage_sndbuf[i] => dac; // make the connection voice + "/" + stage_samps[i] => stage_sndbuf[i].read; // read in the sample stage_sndbuf[i].samples() => stage_sndbuf[i].pos; // position at end of buffer 1 => stage_sndbuf[i].gain; // adjust volume } SndBuf effect_sndbuf[effect_samps.cap ()]; // the sound buffers for effect samples for (int i; i < effect_sndbuf.cap (); i++) { effect_sndbuf[i] => dac; // make the connection voice + "/" + effect_samps[i] => effect_sndbuf[i].read; // read in the sample effect_sndbuf[i].samples() => effect_sndbuf[i].pos; // position at end of buffer 1 => effect_sndbuf[i].gain; // adjust volume } SndBuf axis_sndbuf[axis_samps.cap ()]; // the sound buffers for axis samples for (int i; i < axis_sndbuf.cap (); i++) { axis_sndbuf[i] => dac; // make the connection voice + "/" + axis_samps[i] => axis_sndbuf[i].read; // read in the sample axis_sndbuf[i].samples() => axis_sndbuf[i].pos; // position at end of buffer 1 => axis_sndbuf[i].gain; // adjust volume } dac => WvOut wvout => blackhole; // the patch parameters 1 => adc.gain; 0.5 => wvout.gain; filename => wvout.wavFilename; // time loop print_object.print (); // print the configuration while (exit == 0) { second => now; } filename => wvout.closeFile; <<<"", "">>>; <<<"End of Program: Exit", "">>>; // stage tracker class stage_tracker { // launch the stage function spork ~ stage_right (); // stage incrementor fun void stage_right () { while (true) { key[0] => now; if (lock == 0) { stage + 1 => stage; if (stage == num_stages) { 0 => stage; 2 => lock; } } if (lock > 0) { 1 -=> lock; } // print the configuration print_object.print (); // say computer voice feedback if (lock == 0) { 0 => stage_sndbuf[stage].pos; } else { 0 => stage_sndbuf[8].pos; } } } } // effect tracker class effect_tracker { // launch the effect function spork ~ effect_next (); // function to hook up next effect fun void effect_next () { while (true) { key[1] => now; // remember effect indexed (effect[stage] + 1) % num_effects => effect[stage]; if (effect[stage] == 1) { node[stage] =< none[stage]; // unhook downstream none[stage] =< node[stage+1]; // unhook upstream node[stage] => reverb_object[stage].input; // hook downstream reverb_object[stage].output => node[stage+1]; // hook upstream // spork new shreds spork ~ reverb_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ reverb_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[1].pos; } if (effect[stage] == 2) { node[stage] =< reverb_object[stage].input; // unhook downstream reverb_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => wah_object[stage].input; // hook downstream wah_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ wah_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ wah_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[2].pos; } if (effect[stage] == 3) { node[stage] =< wah_object[stage].input; // unhook downstream wah_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => distortion_object[stage].input; // hook downstream distortion_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ distortion_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ distortion_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[3].pos; } if (effect[stage] == 4) { node[stage] =< distortion_object[stage].input; // unhook downstream distortion_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => tremolo_object[stage].input; // hook downstream volume_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ tremolo_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ tremolo_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[4].pos; } if (effect[stage] == 5) { node[stage] =< tremolo_object[stage].input; // unhook downstream tremolo_object[stage].output =< node[stage+1]; // unhook upstream node[stage] =>bass_object[stage].input; // hook downstream bass_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ bass_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ bass_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[5].pos; } if (effect[stage] == 6) { node[stage] =< bass_object[stage].input; // unhook downstream bass_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => pitchshift_object[stage].input; // hook downstream pitchshift_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ pitchshift_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ pitchshift_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[6].pos; } if (effect[stage] == 7) { node[stage] =< pitchshift_object[stage].input; // unhook downstream pitchshift_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => volume_object[stage].input; // hook downstream volume_object[stage].output => node[stage+1]; // hook upstream potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred // spork new shreds spork ~ volume_object[stage].potentiometer_adjust () @=> potentiometer_adj[stage]; spork ~ volume_object[stage].accelerometer_adjust () @=> accelerometer_adj[stage]; 0 => effect_sndbuf[7].pos; } if (effect[stage] == 0) { node[stage] =< volume_object[stage].input; // unhook downstream volume_object[stage].output =< node[stage+1]; // unhook upstream node[stage] => none[stage] => node[stage+1]; // hook up potentiometer_adj[stage].exit (); // remove old shred accelerometer_adj[stage].exit (); // remove old shred 0 => effect_sndbuf[0].pos; } // print the configuration print_object.print (); } } } // axis tracker class axis_tracker { // initialize axis assignments for (int i; i < num_stages; i++) { 0 => axis[i]; } // launch the axis function spork ~ axis_cycle (); // axis incrementor fun void axis_cycle () { while (true) { key[2] => now; if (lock == 0) { (axis[stage] + 1) % joystick_msg.cap () => axis[stage]; } // print the configuration print_object.print (); // say computer voice feedback if (lock == 0) { 0 => axis_sndbuf[axis[stage]].pos; } } } } // print stuff class print { // variables string axis_name[num_stages]; // name of each axis string effect_name[num_stages]; // name of each effect string outstr; // output string // print the stuff fun void print () { // set strings for (int i; i < num_stages; i++) { if (axis[i] == 0) { "Xacc" => axis_name[i]; } if (axis[i] == 1) { "Yacc" => axis_name[i]; } if (axis[i] == 2) { "Zacc" => axis_name[i]; } if (axis[i] == 3) { "YPos" => axis_name[i]; } if (axis[i] == 4) { "None" => axis_name[i]; } if (effect[i] == 0) { "none" => effect_name[i]; } if (effect[i] == 1) { "reverb" => effect_name[i]; } if (effect[i] == 2) { "wah" => effect_name[i]; } if (effect[i] == 3) { "distortion" => effect_name[i]; } if (effect[i] == 4) { "tremolo" => effect_name[i]; } if (effect[i] == 5) { "bass" => effect_name[i]; } if (effect[i] == 6) { "pitchshift" => effect_name[i]; } if (effect[i] == 7) { "volume" => effect_name[i]; } } // build output string "adc => " => outstr; for (int i; i < num_stages; i++) { if ( (stage == i) & (lock == 0) ) { outstr + "<[ " => outstr; } outstr + axis_name[i] => outstr; outstr + " " => outstr; outstr + effect_name[i] => outstr; outstr + " " => outstr; outstr + (Math.floor(10*extremeness[i]) $ int) => outstr; if ( (stage == i) & (lock == 0) ) { outstr + " ]>" => outstr; } outstr + " => " => outstr; } outstr + "dac" => outstr; <<<"", "">>>; <<>>; } } // interface to the keyboard class keyboard { // hid initialization Hid hid; HidMsg hidmsg; if (!hid.openKeyboard (keyboard_device)) { <<<"Error keyboard not found at device", keyboard_device>>>; me.exit(); } else { <<< "keyboard '" + hid.name () + "' ready.", "" >>>; } // launch the time loop spork ~ time_loop (); // time loop fun void time_loop () { while (true) { hid => now; while (hid.recv (hidmsg)) { if (hidmsg.isButtonDown ()) { if (hidmsg.which == 225) { // left shift key key[0].broadcast (); } if (hidmsg.which == 229) { // right shift key if (lock == 0) { key[1].broadcast (); } } if (hidmsg.which == 44) { // space bar key key[2].broadcast (); } if ( (hidmsg.which == 42) | (hidmsg.which == 76) ) { 1 => exit; } } } } } } // Interface to mouse class mouse { // initialize HID Hid hid; HidMsg hidmsg; if (!hid.openMouse (mouse_device)) { <<<"Error mouse not found at device", mouse_device>>>; me.exit(); } else { <<< "mouse '" + hid.name () + "' ready.", "" >>>; } // launch the time loop spork ~ time_loop (); // time loop fun void time_loop () { while (true) { hid => now; while (hid.recv (hidmsg)) { if ( hidmsg.isMouseMotion () ) { // remember previous value mouse_x => prev_mouse_x; // deal with X changes (hidmsg.deltaX $ float) / 400.0 +=> mouse_x; if (mouse_x < 0) { // check lower limit on x 0 => mouse_x; } if (mouse_x > 1) { // check upper limit on x 1 => mouse_x; } mouse_x => extremeness[stage]; if (lock == 0) { // broadcast that a new value is available potentiometer.broadcast (); // print out if ( Math.floor(10*mouse_x) != Math.floor(10*prev_mouse_x) ) { // print the configuration print_object.print (); } } } } } } } // Interface to joystick class joystick { // parameters [100.0, 100.0, 100.0] @=> float acc_gain[]; // acceleration gain // variables float input[3]; // the input value float phi_pos; // vertical angular position int count[3]; // counts updates // initialize joystick message for (int i; i < joystick_msg.cap (); i++) { 0 => joystick_msg[i]; } 1 => joystick_msg[joystick_msg.cap () - 1]; // broadcast that a new accelerometer reading is available accelerometer.broadcast (); // initialize hid Hid hid; HidMsg hidmsg; if (!hid.openJoystick (joystick_device)) { <<<"JoyStick not found at device", joystick_device>>>; } else { <<< "Joystick '" + hid.name () + "' ready.", "" >>>; } // launch the time loop spork ~ time_loop (); // time loop fun void time_loop () { while (true) { hid => now; while (hid.recv (hidmsg)) { if (hidmsg.isAxisMotion ()) { (count[hidmsg.which] + 1) % 10 => count[hidmsg.which]; if (count[hidmsg.which] == 0) { // record the input value for debug purposes hidmsg.axisPosition => input[hidmsg.which]; // calculate angles Math.atan2 (input[0], input[1]) => phi_pos; // convert horiz and vert angles to control signals acc_gain[0] * input[0] => joystick_msg[0]; acc_gain[1] * input[1] => joystick_msg[1]; acc_gain[2] * input[2] => joystick_msg[2]; phi_pos => joystick_msg[3]; 1 => joystick_msg[4]; for (int i; i < joystick_msg.cap (); i++) { if (joystick_msg[i] < -1.0) { -1.0 => joystick_msg[i]; } if (joystick_msg[i] > 1.0) { 1.0 => joystick_msg[i]; } } // broadcast that a new accelerometer reading is available accelerometer.broadcast (); } } } } } } // reverb class class reverb { // variables int my_stage; // identifies the stage of this reverb 1 => float my_extremeness; // the extremeness of this reverb 0 => float my_control; // the control value of this reverb // the patch Gain input => NRev nrev => Gain output; // initialize effect my_extremeness * Math.fabs (my_control) => nrev.mix; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; my_extremeness * Math.fabs (my_control) => nrev.mix; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; my_extremeness * Math.fabs (my_control) => nrev.mix; } } } // wah class class wah { // parameters 100.0 => float freq_offset; // offset of frequency 4000.0 => float freq_gain; // gain of frequency 0.7 => float tau; // for smoothing frequency changes // variables int my_stage; // identifies the stage of this wah 1 => float my_extremeness; // the extremeness of this wah 0 => float my_control; // the control value of this wah float frequency; // the frequency setting float f; // the commanded frequency // the patch Gain input => LPF wah_lpf => Gain output; input => BPF wah_bpf => output; // the patch parameters freq_offset + freq_gain => wah_lpf.freq; freq_offset + freq_gain => wah_bpf.freq; 1.0 => wah_lpf.Q; 1.0 => wah_bpf.Q; 2.0 => wah_bpf.gain; // initialize effect freq_offset + freq_gain - freq_gain * my_extremeness * Math.fabs (my_control) => frequency; frequency => wah_lpf.freq; frequency => wah_bpf.freq; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; freq_offset + freq_gain - freq_gain * my_extremeness * Math.fabs (my_control) => f; tau * frequency + (1.0 - tau) * f => frequency; frequency => wah_lpf.freq; frequency => wah_bpf.freq; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; freq_offset + freq_gain - freq_gain * my_extremeness * Math.fabs (my_control) => f; tau * frequency + (1.0 - tau) * f => frequency; frequency => wah_lpf.freq; frequency => wah_bpf.freq; } } } // distortion class class distortion { // variables int my_stage; // identifies the stage of this distortion 1 => float my_extremeness; // the extremeness of this distortion 0 => float my_control; // the control value of this distortion // the patch Gain input => Gain boost => Gain divide => Gain output; input => FullRect fwr => Gain add => divide; Step step => add; // the patch parameters 1.0 => boost.gain; 4 => divide.op; // make it a divider 1.0 => step.next; // initialize effect 50.0 * my_extremeness * (0.1 + Math.fabs (my_control) ) => input.gain; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; 50.0 * my_extremeness * (0.1 + Math.fabs (my_control) ) => input.gain; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; 50.0 * my_extremeness * (0.1 + Math.fabs (my_control) ) => input.gain; } } } // tremolo class class tremolo { // parameters 2.0 => float frequency_depth; // how deep to vary frequency // variables int my_stage; // identifies the stage of this tremolo 1 => float my_extremeness; // the extremeness of this tremolo 0 => float my_control; // the control value of this tremolo // the patch Gain input => Gain multiply => Gain output; SinOsc sinosc => HalfRect hwr => multiply; // the patch parameters 3 => multiply.op; // make it multiply frequency_depth => sinosc.freq; // initialize effect my_extremeness * (1.0 - Math.fabs (my_control)) * frequency_depth => sinosc.freq; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; my_extremeness * (1.0 - Math.fabs (my_control)) * frequency_depth => sinosc.freq; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; my_extremeness * (1.0 - Math.fabs (my_control)) * frequency_depth => sinosc.freq; } } } // bass class class bass { // parameters 30.868/82.407 => float shift; // how deep to vary frequency // variables int my_stage; // identifies the stage of this bass 1 => float my_extremeness; // the extremeness of this bass 0 => float my_control; // the control value of this bass // the patch Gain input => PitShift pitshift => Gain output; // the patch parameters shift => pitshift.shift; 1 => pitshift.mix; // initialize effect // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; } } } // pitchshift class class pitchshift { // variables int my_stage; // identifies the stage of this pitchshift 1 => float my_extremeness; // the extremeness of this pitchshift 0 => float my_control; // the control value of this pitchshift // the patch Gain input => PitShift ps => Gain output; // the patch parameters 1 => ps.shift; 1 => ps.mix; // initialize effect my_extremeness * my_control + 1.0 => ps.shift; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; my_extremeness * my_control + 1.0 => ps.shift; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; my_extremeness * my_control + 1.0 => ps.shift; } } } // volume class class volume { // variables int my_stage; // identifies the stage of this volume 1 => float my_extremeness; // the extremeness of this volume 0 => float my_control; // the control value of this volume // the patch Gain input => Gain output; // initialize effect 10 * my_extremeness => input.gain; // potentiometer adjust function fun void potentiometer_adjust () { while (true) { potentiometer => now; extremeness[my_stage] => my_extremeness; 10 * my_extremeness => input.gain; } } // accelerometer adjust function fun void accelerometer_adjust () { while (true) { accelerometer => now; joystick_msg[axis[my_stage]] => my_control; 10 * my_extremeness => input.gain; } } }