Superparticular samchillian

From Xenharmonic Wiki
Revision as of 19:38, 7 June 2012 by Wikispaces>xenjacob (**Imported revision 343680102 - Original comment: **)
Jump to navigation Jump to search

IMPORTED REVISION FROM WIKISPACES

This is an imported revision from Wikispaces. The revision metadata is included below for reference:

This revision was by author xenjacob and made on 2012-06-07 19:38:40 UTC.
The original revision id was 343680102.
The revision comment was:

The revision contents are below, presented both in the original Wikispaces Wikitext format, and in HTML exactly as Wikispaces rendered it.

Original Wikitext content:

[[code format="java"]]

//ChucK code for Superparticular Samchillian
//Samchillian idea by Leon Gruenbaum
//superparticular-ratio implementation by Jacob Barton

//paste these lines into a new document in miniAudicle, or save text as a .ck to run in command-line

//change these to match your input/output device
0 => int inDeviceNum;
1 => int outDeviceNum;

class MicroRobinMidiIO
{
    MidiIn min;
    MidiOut mouse;
    MidiMsg inmsg, outmsg;
    0 => int ctr;
    
    //int rr[128][3]; don't think we need this now.
    // index = note number?
    // column 0 = channel sent to
    // column 1 = note number sent
    int chans[14]; // list of channels used
    float holds[16];     // pitches of on notes, zero if off.
    [0,1,2,3,4,5,6,7,8,10,11,12,13,14] @=> chans; //exclude channel 10 (drums) & 16 (send channel)
    
    //microtuning stuff
    
    // PitchBend
    // input: pitch (midi note number float) & velocity of desired note
    // action: sends appropriate pitchbend message
    //         (assuming pitchbend range = +/- 2 semitones)
    // output: note number required for correct frequency to be realized
    // sends pitchbend, assuming +/- wholestep pitchbend range
    // returns note number required for correct frequency
    fun int PitchBend(float pitch, int velocity)
    {
        //send pitchbend
        224 + chans[ctr] => outmsg.data1;
        0 => outmsg.data2;
        Math.round((pitch % 1.0) * 32.0 + 64.0) $ int => outmsg.data3;
        mouse.send(outmsg);
        return Math.floor(pitch) $ int;
    }
    
    // StartRelay
    // input: number of MIDI device, MidiTransform to be used
    // creates a loop ~ should be sporked
    fun void StartRelay(int deviceNum, MidiTransform mt)
    {
        
        if( !min.open(inDeviceNum)) me.exit();
        if( !mouse.open(outDeviceNum)) me.exit();
        
        // print out device that was opened
        <<< min.num(), " -> ", min.name() >>>;
        <<< mouse.num(), " -> ", mouse.name() >>>;
        
        while ( true)
        {
            min => now;
            
            while( min.recv(inmsg))
            {      
                if( inmsg.data1 % 16 == 0) // only receive on channel 1
                {
                    <<< "r ", inmsg.data1 / 16, inmsg.data1 % 16, inmsg.data2, inmsg.data3>>>;
                    
                    if( inmsg.data1 / 16 == 9)
                    {   
                        mt.NoteOn(inmsg.data2, inmsg.data3);
                    }
                    if( inmsg.data1 / 16 == 8)
                    {
                        mt.NoteOff(inmsg.data2, inmsg.data3);
                    }
                    if( inmsg.data1 / 16 == 12)
                    {
                        //prog change apply to channels 1-16
                        //works!
                        inmsg.data1 - (inmsg.data1 % 16) => int base;
                        for(0=>int i; i<15; i++)
                        {
                            base + chans[i] => outmsg.data1;
                            inmsg.data2 => outmsg.data2;
                            i++;
                            if( i == 15)  
                            { 
                                0 => outmsg.data3;
                                mouse.send(outmsg);
                                break; 
                            }
                            
                            base + chans[i] => outmsg.data3;
                            mouse.send(outmsg);
                            inmsg.data2 => outmsg.data1;
                            i++;
                            if( i == 15)
                            {
                                0 => outmsg.data2 => outmsg.data3;
                                mouse.send(outmsg);
                                break;
                            }
                            base + chans[i] => outmsg.data2;
                            inmsg.data2 => outmsg.data3;
                            mouse.send(outmsg);
                        }
                    }
                    
                    if( inmsg.data1 / 16 == 11)
                    {
                        //apply any controller data to channels 1-16
                        inmsg.data1 - (inmsg.data1 % 16) => int base;
                        inmsg.data2 => outmsg.data2;
                        inmsg.data3 => outmsg.data3;
                        for(0=>int i; i<16; i++)
                        {
                            base + i => outmsg.data1;
                            mouse.send(outmsg);
                        }
                    }
                }
            }
        }
    }
    // NoteOn
    // input: pitch in midi note-number extended, velocity
    // action: sends a MIDI pitchbend + note-on message to mouse on the current channel
    //     keeping track of holds
    fun void NoteOn(float nn, int velocity)
    {
        IncrementCtr();
        nn => holds[chans[ctr%14]];
        PitchBend(nn, velocity) => outmsg.data2;
        // note on, right channel
        144 + chans[ctr%14] => outmsg.data1; 
        
        velocity => outmsg.data3;
        mouse.send(outmsg);
        //<<< "s ", outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3>>>;
    }
    
    // increments mod-14 counter, skipping over channels with
    // notes already on them, if possible.
    fun void IncrementCtr()
    {
        ctr;
        0 => int i;
        for( i; i<14; i++)
        {
            if ( holds[chans[(ctr+i) % 14]] == 0.0)
            {    (ctr + i) % 14 => ctr; return; }
        }
        (ctr + 1) % 14 => ctr;
    }
    
    // NoteOff
    // input: pitch & note-off velocity
    // action: finds the pitch & offs it.
    fun void NoteOff(float nn, int velocity)
    {
        0 => int c;
        for(c; c<16; c++)
        {
            if(holds[c] == nn) // we found the pitch!
            {
                128 + c => outmsg.data1;
                Math.floor(nn) $ int => outmsg.data2;
                velocity => outmsg.data3;
                mouse.send(outmsg);
                //<<< "s ", outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3>>>;
                0.0 => holds[c];
                return;
            }
        }
        <<<"MISS", nn>>>;
        // we couldn't find the pitch!
        // don't do anything.            
    }
    
    fun void ControlChange(int channel, int prognum, int val)
    {
        128 + channel => outmsg.data1;
        prognum => outmsg.data2;
        val => outmsg.data3;
    }
    
}

class MidiTransform
{
    // superclass for MIDI transformers to be used by MicroRobinMidiIO
    MicroRobinMidiIO myIO;
    fun void LinkToIO(MicroRobinMidiIO io)
    {
        io @=> myIO;
    }
    fun void NoteOn( int nn, int vel)
    {
        return;
    }
    fun void NoteOff( int nn, int vel)
    {
        return;
    }
}

class SuperparticularSamchillian extends MidiTransform
{
    57. => float resentFreq;
    57. => float prevFreq;  
    
    62 => int keyboardCenterNN;
    
    float prevFreqsByKey[128];
      
    //set pans funky
    //for(0=>int f; f<16; f++)
    //{
    //    myIO.ControlChange(f, 9, f*8);
    //}
    
    fun void NoteOn( int nn, int vel)
    {
        if(nn == keyboardCenterNN)
        {
            myIO.NoteOn( Std.ftom(prevFreq), vel);
        }
        else 
        {
            if(nn < keyboardCenterNN)
            {
                // superparticular!
                1. + 1./(keyboardCenterNN - nn) /=> prevFreq;
                myIO.NoteOn( Std.ftom(prevFreq), vel);
            }
            else
            { 
                if(nn > keyboardCenterNN)
                {
                    1. + 1./(nn - keyboardCenterNN) *=> prevFreq;
                    myIO.NoteOn( Std.ftom(prevFreq), vel);
                }
            }
        }
        Std.ftom(prevFreq) => prevFreqsByKey[nn];
    }
            
         
    fun void NoteOff( int nn, int vel)
    {
        myIO.NoteOff( prevFreqsByKey[nn], vel);
    }
    
}

MicroRobinMidiIO mrmio;
SuperparticularSamchillian easy;
easy.LinkToIO(mrmio);
spork ~ mrmio.StartRelay( 1, easy);

1::second => now;

KBHit kb; 

while(true)
{
    kb => now;
    
    while( kb.more() )
    {
        kb.getchar() => int c;
        <<< "ascii:", c>>>;
        easy.NoteOn(c, 88);
    }
}

[[code]]

Original HTML content:

<html><head><title>superparticular samchillian</title></head><body><!-- ws:start:WikiTextCodeRule:0:
&lt;pre class=&quot;java&quot;&gt;//ChucK code for Superparticular Samchillian&lt;br/&gt;//Samchillian idea by Leon Gruenbaum&lt;br/&gt;//superparticular-ratio implementation by Jacob Barton&lt;br/&gt;&lt;br/&gt;//paste these lines into a new document in miniAudicle, or save text as a .ck to run in command-line&lt;br/&gt;&lt;br/&gt;//change these to match your input/output device&lt;br/&gt;0 =&amp;gt; int inDeviceNum;&lt;br/&gt;1 =&amp;gt; int outDeviceNum;&lt;br/&gt;&lt;br/&gt;class MicroRobinMidiIO&lt;br/&gt;{&lt;br/&gt;    MidiIn min;&lt;br/&gt;    MidiOut mouse;&lt;br/&gt;    MidiMsg inmsg, outmsg;&lt;br/&gt;    0 =&amp;gt; int ctr;&lt;br/&gt;    &lt;br/&gt;    //int rr[128][3]; don't think we need this now.&lt;br/&gt;    // index = note number?&lt;br/&gt;    // column 0 = channel sent to&lt;br/&gt;    // column 1 = note number sent&lt;br/&gt;    int chans[14]; // list of channels used&lt;br/&gt;    float holds[16];     // pitches of on notes, zero if off.&lt;br/&gt;    [0,1,2,3,4,5,6,7,8,10,11,12,13,14] @=&amp;gt; chans; //exclude channel 10 (drums) &amp;amp; 16 (send channel)&lt;br/&gt;    &lt;br/&gt;    //microtuning stuff&lt;br/&gt;    &lt;br/&gt;    // PitchBend&lt;br/&gt;    // input: pitch (midi note number float) &amp;amp; velocity of desired note&lt;br/&gt;    // action: sends appropriate pitchbend message&lt;br/&gt;    //         (assuming pitchbend range = +/- 2 semitones)&lt;br/&gt;    // output: note number required for correct frequency to be realized&lt;br/&gt;    // sends pitchbend, assuming +/- wholestep pitchbend range&lt;br/&gt;    // returns note number required for correct frequency&lt;br/&gt;    fun int PitchBend(float pitch, int velocity)&lt;br/&gt;    {&lt;br/&gt;        //send pitchbend&lt;br/&gt;        224 + chans[ctr] =&amp;gt; outmsg.data1;&lt;br/&gt;        0 =&amp;gt; outmsg.data2;&lt;br/&gt;        Math.round((pitch % 1.0) * 32.0 + 64.0) $ int =&amp;gt; outmsg.data3;&lt;br/&gt;        mouse.send(outmsg);&lt;br/&gt;        return Math.floor(pitch) $ int;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    // StartRelay&lt;br/&gt;    // input: number of MIDI device, MidiTransform to be used&lt;br/&gt;    // creates a loop ~ should be sporked&lt;br/&gt;    fun void StartRelay(int deviceNum, MidiTransform mt)&lt;br/&gt;    {&lt;br/&gt;        &lt;br/&gt;        if( !min.open(inDeviceNum)) me.exit();&lt;br/&gt;        if( !mouse.open(outDeviceNum)) me.exit();&lt;br/&gt;        &lt;br/&gt;        // print out device that was opened&lt;br/&gt;        &amp;lt;&amp;lt;&amp;lt; min.num(), &amp;quot; -&amp;gt; &amp;quot;, min.name() &amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;        &amp;lt;&amp;lt;&amp;lt; mouse.num(), &amp;quot; -&amp;gt; &amp;quot;, mouse.name() &amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;        &lt;br/&gt;        while ( true)&lt;br/&gt;        {&lt;br/&gt;            min =&amp;gt; now;&lt;br/&gt;            &lt;br/&gt;            while( min.recv(inmsg))&lt;br/&gt;            {      &lt;br/&gt;                if( inmsg.data1 % 16 == 0) // only receive on channel 1&lt;br/&gt;                {&lt;br/&gt;                    &amp;lt;&amp;lt;&amp;lt; &amp;quot;r &amp;quot;, inmsg.data1 / 16, inmsg.data1 % 16, inmsg.data2, inmsg.data3&amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;                    &lt;br/&gt;                    if( inmsg.data1 / 16 == 9)&lt;br/&gt;                    {   &lt;br/&gt;                        mt.NoteOn(inmsg.data2, inmsg.data3);&lt;br/&gt;                    }&lt;br/&gt;                    if( inmsg.data1 / 16 == 8)&lt;br/&gt;                    {&lt;br/&gt;                        mt.NoteOff(inmsg.data2, inmsg.data3);&lt;br/&gt;                    }&lt;br/&gt;                    if( inmsg.data1 / 16 == 12)&lt;br/&gt;                    {&lt;br/&gt;                        //prog change apply to channels 1-16&lt;br/&gt;                        //works!&lt;br/&gt;                        inmsg.data1 - (inmsg.data1 % 16) =&amp;gt; int base;&lt;br/&gt;                        for(0=&amp;gt;int i; i&amp;lt;15; i++)&lt;br/&gt;                        {&lt;br/&gt;                            base + chans[i] =&amp;gt; outmsg.data1;&lt;br/&gt;                            inmsg.data2 =&amp;gt; outmsg.data2;&lt;br/&gt;                            i++;&lt;br/&gt;                            if( i == 15)  &lt;br/&gt;                            { &lt;br/&gt;                                0 =&amp;gt; outmsg.data3;&lt;br/&gt;                                mouse.send(outmsg);&lt;br/&gt;                                break; &lt;br/&gt;                            }&lt;br/&gt;                            &lt;br/&gt;                            base + chans[i] =&amp;gt; outmsg.data3;&lt;br/&gt;                            mouse.send(outmsg);&lt;br/&gt;                            inmsg.data2 =&amp;gt; outmsg.data1;&lt;br/&gt;                            i++;&lt;br/&gt;                            if( i == 15)&lt;br/&gt;                            {&lt;br/&gt;                                0 =&amp;gt; outmsg.data2 =&amp;gt; outmsg.data3;&lt;br/&gt;                                mouse.send(outmsg);&lt;br/&gt;                                break;&lt;br/&gt;                            }&lt;br/&gt;                            base + chans[i] =&amp;gt; outmsg.data2;&lt;br/&gt;                            inmsg.data2 =&amp;gt; outmsg.data3;&lt;br/&gt;                            mouse.send(outmsg);&lt;br/&gt;                        }&lt;br/&gt;                    }&lt;br/&gt;                    &lt;br/&gt;                    if( inmsg.data1 / 16 == 11)&lt;br/&gt;                    {&lt;br/&gt;                        //apply any controller data to channels 1-16&lt;br/&gt;                        inmsg.data1 - (inmsg.data1 % 16) =&amp;gt; int base;&lt;br/&gt;                        inmsg.data2 =&amp;gt; outmsg.data2;&lt;br/&gt;                        inmsg.data3 =&amp;gt; outmsg.data3;&lt;br/&gt;                        for(0=&amp;gt;int i; i&amp;lt;16; i++)&lt;br/&gt;                        {&lt;br/&gt;                            base + i =&amp;gt; outmsg.data1;&lt;br/&gt;                            mouse.send(outmsg);&lt;br/&gt;                        }&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    // NoteOn&lt;br/&gt;    // input: pitch in midi note-number extended, velocity&lt;br/&gt;    // action: sends a MIDI pitchbend + note-on message to mouse on the current channel&lt;br/&gt;    //     keeping track of holds&lt;br/&gt;    fun void NoteOn(float nn, int velocity)&lt;br/&gt;    {&lt;br/&gt;        IncrementCtr();&lt;br/&gt;        nn =&amp;gt; holds[chans[ctr%14]];&lt;br/&gt;        PitchBend(nn, velocity) =&amp;gt; outmsg.data2;&lt;br/&gt;        // note on, right channel&lt;br/&gt;        144 + chans[ctr%14] =&amp;gt; outmsg.data1; &lt;br/&gt;        &lt;br/&gt;        velocity =&amp;gt; outmsg.data3;&lt;br/&gt;        mouse.send(outmsg);&lt;br/&gt;        //&amp;lt;&amp;lt;&amp;lt; &amp;quot;s &amp;quot;, outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3&amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    // increments mod-14 counter, skipping over channels with&lt;br/&gt;    // notes already on them, if possible.&lt;br/&gt;    fun void IncrementCtr()&lt;br/&gt;    {&lt;br/&gt;        ctr;&lt;br/&gt;        0 =&amp;gt; int i;&lt;br/&gt;        for( i; i&amp;lt;14; i++)&lt;br/&gt;        {&lt;br/&gt;            if ( holds[chans[(ctr+i) % 14]] == 0.0)&lt;br/&gt;            {    (ctr + i) % 14 =&amp;gt; ctr; return; }&lt;br/&gt;        }&lt;br/&gt;        (ctr + 1) % 14 =&amp;gt; ctr;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    // NoteOff&lt;br/&gt;    // input: pitch &amp;amp; note-off velocity&lt;br/&gt;    // action: finds the pitch &amp;amp; offs it.&lt;br/&gt;    fun void NoteOff(float nn, int velocity)&lt;br/&gt;    {&lt;br/&gt;        0 =&amp;gt; int c;&lt;br/&gt;        for(c; c&amp;lt;16; c++)&lt;br/&gt;        {&lt;br/&gt;            if(holds[c] == nn) // we found the pitch!&lt;br/&gt;            {&lt;br/&gt;                128 + c =&amp;gt; outmsg.data1;&lt;br/&gt;                Math.floor(nn) $ int =&amp;gt; outmsg.data2;&lt;br/&gt;                velocity =&amp;gt; outmsg.data3;&lt;br/&gt;                mouse.send(outmsg);&lt;br/&gt;                //&amp;lt;&amp;lt;&amp;lt; &amp;quot;s &amp;quot;, outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3&amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;                0.0 =&amp;gt; holds[c];&lt;br/&gt;                return;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        &amp;lt;&amp;lt;&amp;lt;&amp;quot;MISS&amp;quot;, nn&amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;        // we couldn't find the pitch!&lt;br/&gt;        // don't do anything.            &lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    fun void ControlChange(int channel, int prognum, int val)&lt;br/&gt;    {&lt;br/&gt;        128 + channel =&amp;gt; outmsg.data1;&lt;br/&gt;        prognum =&amp;gt; outmsg.data2;&lt;br/&gt;        val =&amp;gt; outmsg.data3;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;class MidiTransform&lt;br/&gt;{&lt;br/&gt;    // superclass for MIDI transformers to be used by MicroRobinMidiIO&lt;br/&gt;    MicroRobinMidiIO myIO;&lt;br/&gt;    fun void LinkToIO(MicroRobinMidiIO io)&lt;br/&gt;    {&lt;br/&gt;        io @=&amp;gt; myIO;&lt;br/&gt;    }&lt;br/&gt;    fun void NoteOn( int nn, int vel)&lt;br/&gt;    {&lt;br/&gt;        return;&lt;br/&gt;    }&lt;br/&gt;    fun void NoteOff( int nn, int vel)&lt;br/&gt;    {&lt;br/&gt;        return;&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;class SuperparticularSamchillian extends MidiTransform&lt;br/&gt;{&lt;br/&gt;    57. =&amp;gt; float resentFreq;&lt;br/&gt;    57. =&amp;gt; float prevFreq;  &lt;br/&gt;    &lt;br/&gt;    62 =&amp;gt; int keyboardCenterNN;&lt;br/&gt;    &lt;br/&gt;    float prevFreqsByKey[128];&lt;br/&gt;      &lt;br/&gt;    //set pans funky&lt;br/&gt;    //for(0=&amp;gt;int f; f&amp;lt;16; f++)&lt;br/&gt;    //{&lt;br/&gt;    //    myIO.ControlChange(f, 9, f*8);&lt;br/&gt;    //}&lt;br/&gt;    &lt;br/&gt;    fun void NoteOn( int nn, int vel)&lt;br/&gt;    {&lt;br/&gt;        if(nn == keyboardCenterNN)&lt;br/&gt;        {&lt;br/&gt;            myIO.NoteOn( Std.ftom(prevFreq), vel);&lt;br/&gt;        }&lt;br/&gt;        else &lt;br/&gt;        {&lt;br/&gt;            if(nn &amp;lt; keyboardCenterNN)&lt;br/&gt;            {&lt;br/&gt;                // superparticular!&lt;br/&gt;                1. + 1./(keyboardCenterNN - nn) /=&amp;gt; prevFreq;&lt;br/&gt;                myIO.NoteOn( Std.ftom(prevFreq), vel);&lt;br/&gt;            }&lt;br/&gt;            else&lt;br/&gt;            { &lt;br/&gt;                if(nn &amp;gt; keyboardCenterNN)&lt;br/&gt;                {&lt;br/&gt;                    1. + 1./(nn - keyboardCenterNN) *=&amp;gt; prevFreq;&lt;br/&gt;                    myIO.NoteOn( Std.ftom(prevFreq), vel);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        Std.ftom(prevFreq) =&amp;gt; prevFreqsByKey[nn];&lt;br/&gt;    }&lt;br/&gt;            &lt;br/&gt;         &lt;br/&gt;    fun void NoteOff( int nn, int vel)&lt;br/&gt;    {&lt;br/&gt;        myIO.NoteOff( prevFreqsByKey[nn], vel);&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;MicroRobinMidiIO mrmio;&lt;br/&gt;SuperparticularSamchillian easy;&lt;br/&gt;easy.LinkToIO(mrmio);&lt;br/&gt;spork ~ mrmio.StartRelay( 1, easy);&lt;br/&gt;&lt;br/&gt;1::second =&amp;gt; now;&lt;br/&gt;&lt;br/&gt;KBHit kb; &lt;br/&gt;&lt;br/&gt;while(true)&lt;br/&gt;{&lt;br/&gt;    kb =&amp;gt; now;&lt;br/&gt;    &lt;br/&gt;    while( kb.more() )&lt;br/&gt;    {&lt;br/&gt;        kb.getchar() =&amp;gt; int c;&lt;br/&gt;        &amp;lt;&amp;lt;&amp;lt; &amp;quot;ascii:&amp;quot;, c&amp;gt;&amp;gt;&amp;gt;;&lt;br/&gt;        easy.NoteOn(c, 88);&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;
 -->
<style type="text/css"><!--
/**
 * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
 * (http://qbnz.com/highlighter/ and http://geshi.org/)
 */
.java  {font-family:monospace;}
.java .imp {font-weight: bold; color: red;}
.java .kw1 {color: #000000; font-weight: bold;}
.java .kw2 {color: #000066; font-weight: bold;}
.java .kw3 {color: #003399;}
.java .kw4 {color: #000066; font-weight: bold;}
.java .co1 {color: #666666; font-style: italic;}
.java .co2 {color: #006699;}
.java .co3 {color: #008000; font-style: italic; font-weight: bold;}
.java .coMULTI {color: #666666; font-style: italic;}
.java .es0 {color: #000099; font-weight: bold;}
.java .br0 {color: #009900;}
.java .sy0 {color: #339933;}
.java .st0 {color: #0000ff;}
.java .nu0 {color: #cc66cc;}
.java .me1 {color: #006633;}
.java .me2 {color: #006633;}
.java span.xtra { display:block; }

-->
</style><pre class="java">&nbsp;
<span class="co1">//ChucK code for Superparticular Samchillian</span>
<span class="co1">//Samchillian idea by Leon Gruenbaum</span>
<span class="co1">//superparticular-ratio implementation by Jacob Barton</span>
&nbsp;
<span class="co1">//paste these lines into a new document in miniAudicle, or save text as a .ck to run in command-line</span>
&nbsp;
<span class="co1">//change these to match your input/output device</span>
<span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> inDeviceNum<span class="sy0">;</span>
<span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> outDeviceNum<span class="sy0">;</span>
&nbsp;
<span class="kw1">class</span> MicroRobinMidiIO
<span class="br0">&#123;</span>
    MidiIn min<span class="sy0">;</span>
    MidiOut mouse<span class="sy0">;</span>
    MidiMsg inmsg, outmsg<span class="sy0">;</span>
    <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> ctr<span class="sy0">;</span>
&nbsp;
    <span class="co1">//int rr[128][3]; don't think we need this now.</span>
    <span class="co1">// index = note number?</span>
    <span class="co1">// column 0 = channel sent to</span>
    <span class="co1">// column 1 = note number sent</span>
    <span class="kw4">int</span> chans<span class="br0">&#91;</span><span class="nu0">14</span><span class="br0">&#93;</span><span class="sy0">;</span> <span class="co1">// list of channels used</span>
    <span class="kw4">float</span> holds<span class="br0">&#91;</span><span class="nu0">16</span><span class="br0">&#93;</span><span class="sy0">;</span>     <span class="co1">// pitches of on notes, zero if off.</span>
    <span class="br0">&#91;</span><span class="nu0">0</span>,<span class="nu0">1</span>,<span class="nu0">2</span>,<span class="nu0">3</span>,<span class="nu0">4</span>,<span class="nu0">5</span>,<span class="nu0">6</span>,<span class="nu0">7</span>,<span class="nu0">8</span>,<span class="nu0">10</span>,<span class="nu0">11</span>,<span class="nu0">12</span>,<span class="nu0">13</span>,<span class="nu0">14</span><span class="br0">&#93;</span> @<span class="sy0">=&gt;</span> chans<span class="sy0">;</span> <span class="co1">//exclude channel 10 (drums) &amp; 16 (send channel)</span>
&nbsp;
    <span class="co1">//microtuning stuff</span>
&nbsp;
    <span class="co1">// PitchBend</span>
    <span class="co1">// input: pitch (midi note number float) &amp; velocity of desired note</span>
    <span class="co1">// action: sends appropriate pitchbend message</span>
    <span class="co1">//         (assuming pitchbend range = +/- 2 semitones)</span>
    <span class="co1">// output: note number required for correct frequency to be realized</span>
    <span class="co1">// sends pitchbend, assuming +/- wholestep pitchbend range</span>
    <span class="co1">// returns note number required for correct frequency</span>
    fun <span class="kw4">int</span> PitchBend<span class="br0">&#40;</span><span class="kw4">float</span> pitch, <span class="kw4">int</span> velocity<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="co1">//send pitchbend</span>
        <span class="nu0">224</span> <span class="sy0">+</span> chans<span class="br0">&#91;</span>ctr<span class="br0">&#93;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
        <span class="nu0">0</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
        <span class="kw3">Math</span>.<span class="me1">round</span><span class="br0">&#40;</span><span class="br0">&#40;</span>pitch <span class="sy0">%</span> <span class="nu0">1.0</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">32.0</span> <span class="sy0">+</span> <span class="nu0">64.0</span><span class="br0">&#41;</span> $ <span class="kw4">int</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
        mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw1">return</span> <span class="kw3">Math</span>.<span class="me1">floor</span><span class="br0">&#40;</span>pitch<span class="br0">&#41;</span> $ <span class="kw4">int</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// StartRelay</span>
    <span class="co1">// input: number of MIDI device, MidiTransform to be used</span>
    <span class="co1">// creates a loop ~ should be sporked</span>
    fun <span class="kw4">void</span> StartRelay<span class="br0">&#40;</span><span class="kw4">int</span> deviceNum, MidiTransform mt<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
&nbsp;
        <span class="kw1">if</span><span class="br0">&#40;</span> <span class="sy0">!</span>min.<span class="me1">open</span><span class="br0">&#40;</span>inDeviceNum<span class="br0">&#41;</span><span class="br0">&#41;</span> me.<span class="me1">exit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span> <span class="sy0">!</span>mouse.<span class="me1">open</span><span class="br0">&#40;</span>outDeviceNum<span class="br0">&#41;</span><span class="br0">&#41;</span> me.<span class="me1">exit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span class="co1">// print out device that was opened</span>
        <span class="sy0">&lt;&lt;&lt;</span> min.<span class="me1">num</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="st0">&quot; -&gt; &quot;</span>, min.<span class="me1">name</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&gt;&gt;&gt;;</span>
        <span class="sy0">&lt;&lt;&lt;</span> mouse.<span class="me1">num</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="st0">&quot; -&gt; &quot;</span>, mouse.<span class="me1">name</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">&gt;&gt;&gt;;</span>
&nbsp;
        <span class="kw1">while</span> <span class="br0">&#40;</span> <span class="kw2">true</span><span class="br0">&#41;</span>
        <span class="br0">&#123;</span>
            min <span class="sy0">=&gt;</span> now<span class="sy0">;</span>
&nbsp;
            <span class="kw1">while</span><span class="br0">&#40;</span> min.<span class="me1">recv</span><span class="br0">&#40;</span>inmsg<span class="br0">&#41;</span><span class="br0">&#41;</span>
            <span class="br0">&#123;</span>      
                <span class="kw1">if</span><span class="br0">&#40;</span> inmsg.<span class="me1">data1</span> <span class="sy0">%</span> <span class="nu0">16</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="co1">// only receive on channel 1</span>
                <span class="br0">&#123;</span>
                    <span class="sy0">&lt;&lt;&lt;</span> <span class="st0">&quot;r &quot;</span>, inmsg.<span class="me1">data1</span> <span class="sy0">/</span> <span class="nu0">16</span>, inmsg.<span class="me1">data1</span> <span class="sy0">%</span> <span class="nu0">16</span>, inmsg.<span class="me1">data2</span>, inmsg.<span class="me1">data3</span><span class="sy0">&gt;&gt;&gt;;</span>
&nbsp;
                    <span class="kw1">if</span><span class="br0">&#40;</span> inmsg.<span class="me1">data1</span> <span class="sy0">/</span> <span class="nu0">16</span> <span class="sy0">==</span> <span class="nu0">9</span><span class="br0">&#41;</span>
                    <span class="br0">&#123;</span>   
                        mt.<span class="me1">NoteOn</span><span class="br0">&#40;</span>inmsg.<span class="me1">data2</span>, inmsg.<span class="me1">data3</span><span class="br0">&#41;</span><span class="sy0">;</span>
                    <span class="br0">&#125;</span>
                    <span class="kw1">if</span><span class="br0">&#40;</span> inmsg.<span class="me1">data1</span> <span class="sy0">/</span> <span class="nu0">16</span> <span class="sy0">==</span> <span class="nu0">8</span><span class="br0">&#41;</span>
                    <span class="br0">&#123;</span>
                        mt.<span class="me1">NoteOff</span><span class="br0">&#40;</span>inmsg.<span class="me1">data2</span>, inmsg.<span class="me1">data3</span><span class="br0">&#41;</span><span class="sy0">;</span>
                    <span class="br0">&#125;</span>
                    <span class="kw1">if</span><span class="br0">&#40;</span> inmsg.<span class="me1">data1</span> <span class="sy0">/</span> <span class="nu0">16</span> <span class="sy0">==</span> <span class="nu0">12</span><span class="br0">&#41;</span>
                    <span class="br0">&#123;</span>
                        <span class="co1">//prog change apply to channels 1-16</span>
                        <span class="co1">//works!</span>
                        inmsg.<span class="me1">data1</span> <span class="sy0">-</span> <span class="br0">&#40;</span>inmsg.<span class="me1">data1</span> <span class="sy0">%</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> base<span class="sy0">;</span>
                        <span class="kw1">for</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">=&gt;</span><span class="kw4">int</span> i<span class="sy0">;</span> i<span class="sy0">&lt;</span><span class="nu0">15</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
                        <span class="br0">&#123;</span>
                            base <span class="sy0">+</span> chans<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
                            inmsg.<span class="me1">data2</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
                            i<span class="sy0">++;</span>
                            <span class="kw1">if</span><span class="br0">&#40;</span> i <span class="sy0">==</span> <span class="nu0">15</span><span class="br0">&#41;</span>  
                            <span class="br0">&#123;</span> 
                                <span class="nu0">0</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                                mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                                <span class="kw1">break</span><span class="sy0">;</span> 
                            <span class="br0">&#125;</span>
&nbsp;
                            base <span class="sy0">+</span> chans<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                            mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                            inmsg.<span class="me1">data2</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
                            i<span class="sy0">++;</span>
                            <span class="kw1">if</span><span class="br0">&#40;</span> i <span class="sy0">==</span> <span class="nu0">15</span><span class="br0">&#41;</span>
                            <span class="br0">&#123;</span>
                                <span class="nu0">0</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                                mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                                <span class="kw1">break</span><span class="sy0">;</span>
                            <span class="br0">&#125;</span>
                            base <span class="sy0">+</span> chans<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
                            inmsg.<span class="me1">data2</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                            mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                        <span class="br0">&#125;</span>
                    <span class="br0">&#125;</span>
&nbsp;
                    <span class="kw1">if</span><span class="br0">&#40;</span> inmsg.<span class="me1">data1</span> <span class="sy0">/</span> <span class="nu0">16</span> <span class="sy0">==</span> <span class="nu0">11</span><span class="br0">&#41;</span>
                    <span class="br0">&#123;</span>
                        <span class="co1">//apply any controller data to channels 1-16</span>
                        inmsg.<span class="me1">data1</span> <span class="sy0">-</span> <span class="br0">&#40;</span>inmsg.<span class="me1">data1</span> <span class="sy0">%</span> <span class="nu0">16</span><span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> base<span class="sy0">;</span>
                        inmsg.<span class="me1">data2</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
                        inmsg.<span class="me1">data3</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                        <span class="kw1">for</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">=&gt;</span><span class="kw4">int</span> i<span class="sy0">;</span> i<span class="sy0">&lt;</span><span class="nu0">16</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
                        <span class="br0">&#123;</span>
                            base <span class="sy0">+</span> i <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
                            mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                        <span class="br0">&#125;</span>
                    <span class="br0">&#125;</span>
                <span class="br0">&#125;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
    <span class="co1">// NoteOn</span>
    <span class="co1">// input: pitch in midi note-number extended, velocity</span>
    <span class="co1">// action: sends a MIDI pitchbend + note-on message to mouse on the current channel</span>
    <span class="co1">//     keeping track of holds</span>
    fun <span class="kw4">void</span> NoteOn<span class="br0">&#40;</span><span class="kw4">float</span> nn, <span class="kw4">int</span> velocity<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        IncrementCtr<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        nn <span class="sy0">=&gt;</span> holds<span class="br0">&#91;</span>chans<span class="br0">&#91;</span>ctr<span class="sy0">%</span>14<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="sy0">;</span>
        PitchBend<span class="br0">&#40;</span>nn, velocity<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
        <span class="co1">// note on, right channel</span>
        <span class="nu0">144</span> <span class="sy0">+</span> chans<span class="br0">&#91;</span>ctr<span class="sy0">%</span>14<span class="br0">&#93;</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span> 
&nbsp;
        velocity <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
        mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="co1">//&lt;&lt;&lt; &quot;s &quot;, outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3&gt;&gt;&gt;;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// increments mod-14 counter, skipping over channels with</span>
    <span class="co1">// notes already on them, if possible.</span>
    fun <span class="kw4">void</span> IncrementCtr<span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        ctr<span class="sy0">;</span>
        <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> i<span class="sy0">;</span>
        <span class="kw1">for</span><span class="br0">&#40;</span> i<span class="sy0">;</span> i<span class="sy0">&lt;</span><span class="nu0">14</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
        <span class="br0">&#123;</span>
            <span class="kw1">if</span> <span class="br0">&#40;</span> holds<span class="br0">&#91;</span>chans<span class="br0">&#91;</span><span class="br0">&#40;</span>ctr<span class="sy0">+</span>i<span class="br0">&#41;</span> <span class="sy0">%</span> <span class="nu0">14</span><span class="br0">&#93;</span><span class="br0">&#93;</span> <span class="sy0">==</span> <span class="nu0">0.0</span><span class="br0">&#41;</span>
            <span class="br0">&#123;</span>    <span class="br0">&#40;</span>ctr <span class="sy0">+</span> i<span class="br0">&#41;</span> <span class="sy0">%</span> <span class="nu0">14</span> <span class="sy0">=&gt;</span> ctr<span class="sy0">;</span> <span class="kw1">return</span><span class="sy0">;</span> <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
        <span class="br0">&#40;</span>ctr <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy0">%</span> <span class="nu0">14</span> <span class="sy0">=&gt;</span> ctr<span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// NoteOff</span>
    <span class="co1">// input: pitch &amp; note-off velocity</span>
    <span class="co1">// action: finds the pitch &amp; offs it.</span>
    fun <span class="kw4">void</span> NoteOff<span class="br0">&#40;</span><span class="kw4">float</span> nn, <span class="kw4">int</span> velocity<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> c<span class="sy0">;</span>
        <span class="kw1">for</span><span class="br0">&#40;</span>c<span class="sy0">;</span> c<span class="sy0">&lt;</span><span class="nu0">16</span><span class="sy0">;</span> c<span class="sy0">++</span><span class="br0">&#41;</span>
        <span class="br0">&#123;</span>
            <span class="kw1">if</span><span class="br0">&#40;</span>holds<span class="br0">&#91;</span>c<span class="br0">&#93;</span> <span class="sy0">==</span> nn<span class="br0">&#41;</span> <span class="co1">// we found the pitch!</span>
            <span class="br0">&#123;</span>
                <span class="nu0">128</span> <span class="sy0">+</span> c <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
                <span class="kw3">Math</span>.<span class="me1">floor</span><span class="br0">&#40;</span>nn<span class="br0">&#41;</span> $ <span class="kw4">int</span> <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
                velocity <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
                mouse.<span class="me1">send</span><span class="br0">&#40;</span>outmsg<span class="br0">&#41;</span><span class="sy0">;</span>
                <span class="co1">//&lt;&lt;&lt; &quot;s &quot;, outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3&gt;&gt;&gt;;</span>
                <span class="nu0">0.0</span> <span class="sy0">=&gt;</span> holds<span class="br0">&#91;</span>c<span class="br0">&#93;</span><span class="sy0">;</span>
                <span class="kw1">return</span><span class="sy0">;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
        <span class="sy0">&lt;&lt;&lt;</span><span class="st0">&quot;MISS&quot;</span>, nn<span class="sy0">&gt;&gt;&gt;;</span>
        <span class="co1">// we couldn't find the pitch!</span>
        <span class="co1">// don't do anything.            </span>
    <span class="br0">&#125;</span>
&nbsp;
    fun <span class="kw4">void</span> ControlChange<span class="br0">&#40;</span><span class="kw4">int</span> channel, <span class="kw4">int</span> prognum, <span class="kw4">int</span> val<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="nu0">128</span> <span class="sy0">+</span> channel <span class="sy0">=&gt;</span> outmsg.<span class="me1">data1</span><span class="sy0">;</span>
        prognum <span class="sy0">=&gt;</span> outmsg.<span class="me1">data2</span><span class="sy0">;</span>
        val <span class="sy0">=&gt;</span> outmsg.<span class="me1">data3</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">class</span> MidiTransform
<span class="br0">&#123;</span>
    <span class="co1">// superclass for MIDI transformers to be used by MicroRobinMidiIO</span>
    MicroRobinMidiIO myIO<span class="sy0">;</span>
    fun <span class="kw4">void</span> LinkToIO<span class="br0">&#40;</span>MicroRobinMidiIO io<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        io @<span class="sy0">=&gt;</span> myIO<span class="sy0">;</span>
    <span class="br0">&#125;</span>
    fun <span class="kw4">void</span> NoteOn<span class="br0">&#40;</span> <span class="kw4">int</span> nn, <span class="kw4">int</span> vel<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="kw1">return</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
    fun <span class="kw4">void</span> NoteOff<span class="br0">&#40;</span> <span class="kw4">int</span> nn, <span class="kw4">int</span> vel<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="kw1">return</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">class</span> SuperparticularSamchillian <span class="kw1">extends</span> MidiTransform
<span class="br0">&#123;</span>
    <span class="nu0">57</span>. <span class="sy0">=&gt;</span> <span class="kw4">float</span> resentFreq<span class="sy0">;</span>
    <span class="nu0">57</span>. <span class="sy0">=&gt;</span> <span class="kw4">float</span> prevFreq<span class="sy0">;</span>  
&nbsp;
    <span class="nu0">62</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> keyboardCenterNN<span class="sy0">;</span>
&nbsp;
    <span class="kw4">float</span> prevFreqsByKey<span class="br0">&#91;</span><span class="nu0">128</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">//set pans funky</span>
    <span class="co1">//for(0=&gt;int f; f&lt;16; f++)</span>
    <span class="co1">//{</span>
    <span class="co1">//    myIO.ControlChange(f, 9, f*8);</span>
    <span class="co1">//}</span>
&nbsp;
    fun <span class="kw4">void</span> NoteOn<span class="br0">&#40;</span> <span class="kw4">int</span> nn, <span class="kw4">int</span> vel<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span>nn <span class="sy0">==</span> keyboardCenterNN<span class="br0">&#41;</span>
        <span class="br0">&#123;</span>
            myIO.<span class="me1">NoteOn</span><span class="br0">&#40;</span> Std.<span class="me1">ftom</span><span class="br0">&#40;</span>prevFreq<span class="br0">&#41;</span>, vel<span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
        <span class="kw1">else</span> 
        <span class="br0">&#123;</span>
            <span class="kw1">if</span><span class="br0">&#40;</span>nn <span class="sy0">&lt;</span> keyboardCenterNN<span class="br0">&#41;</span>
            <span class="br0">&#123;</span>
                <span class="co1">// superparticular!</span>
                <span class="nu0">1</span>. <span class="sy0">+</span> <span class="nu0">1</span>.<span class="sy0">/</span><span class="br0">&#40;</span>keyboardCenterNN <span class="sy0">-</span> nn<span class="br0">&#41;</span> <span class="sy0">/=&gt;</span> prevFreq<span class="sy0">;</span>
                myIO.<span class="me1">NoteOn</span><span class="br0">&#40;</span> Std.<span class="me1">ftom</span><span class="br0">&#40;</span>prevFreq<span class="br0">&#41;</span>, vel<span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span>
            <span class="kw1">else</span>
            <span class="br0">&#123;</span> 
                <span class="kw1">if</span><span class="br0">&#40;</span>nn <span class="sy0">&gt;</span> keyboardCenterNN<span class="br0">&#41;</span>
                <span class="br0">&#123;</span>
                    <span class="nu0">1</span>. <span class="sy0">+</span> <span class="nu0">1</span>.<span class="sy0">/</span><span class="br0">&#40;</span>nn <span class="sy0">-</span> keyboardCenterNN<span class="br0">&#41;</span> <span class="sy0">*=&gt;</span> prevFreq<span class="sy0">;</span>
                    myIO.<span class="me1">NoteOn</span><span class="br0">&#40;</span> Std.<span class="me1">ftom</span><span class="br0">&#40;</span>prevFreq<span class="br0">&#41;</span>, vel<span class="br0">&#41;</span><span class="sy0">;</span>
                <span class="br0">&#125;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
        Std.<span class="me1">ftom</span><span class="br0">&#40;</span>prevFreq<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> prevFreqsByKey<span class="br0">&#91;</span>nn<span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
&nbsp;
    fun <span class="kw4">void</span> NoteOff<span class="br0">&#40;</span> <span class="kw4">int</span> nn, <span class="kw4">int</span> vel<span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        myIO.<span class="me1">NoteOff</span><span class="br0">&#40;</span> prevFreqsByKey<span class="br0">&#91;</span>nn<span class="br0">&#93;</span>, vel<span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span>
&nbsp;
MicroRobinMidiIO mrmio<span class="sy0">;</span>
SuperparticularSamchillian easy<span class="sy0">;</span>
easy.<span class="me1">LinkToIO</span><span class="br0">&#40;</span>mrmio<span class="br0">&#41;</span><span class="sy0">;</span>
spork ~ mrmio.<span class="me1">StartRelay</span><span class="br0">&#40;</span> <span class="nu0">1</span>, easy<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="nu0">1</span><span class="sy0">::</span>second <span class="sy0">=&gt;</span> now<span class="sy0">;</span>
&nbsp;
KBHit kb<span class="sy0">;</span> 
&nbsp;
<span class="kw1">while</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    kb <span class="sy0">=&gt;</span> now<span class="sy0">;</span>
&nbsp;
    <span class="kw1">while</span><span class="br0">&#40;</span> kb.<span class="me1">more</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        kb.<span class="me1">getchar</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="kw4">int</span> c<span class="sy0">;</span>
        <span class="sy0">&lt;&lt;&lt;</span> <span class="st0">&quot;ascii:&quot;</span>, c<span class="sy0">&gt;&gt;&gt;;</span>
        easy.<span class="me1">NoteOn</span><span class="br0">&#40;</span>c, <span class="nu0">88</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>

<!-- ws:end:WikiTextCodeRule:0 --></body></html>