Superparticular samchillian: Difference between revisions

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