Superparticular samchillian: Difference between revisions

Wikispaces>xenjacob
**Imported revision 343572870 - Original comment: **
 
BudjarnLambeth (talk | contribs)
mNo edit summary
 
(5 intermediate revisions by 4 users not shown)
Line 1: Line 1:
<h2>IMPORTED REVISION FROM WIKISPACES</h2>
{{todo|link}}
This is an imported revision from Wikispaces. The revision metadata is included below for reference:<br>
<pre>
: This revision was by author [[User:xenjacob|xenjacob]] and made on <tt>2012-06-07 12:40:57 UTC</tt>.<br>
//ChucK code for Superparticular Samchillian
: The original revision id was <tt>343572870</tt>.<br>
//Samchillian idea by Leon Gruenbaum
: The revision comment was: <tt></tt><br>
//superparticular-ratio implementation by Jacob Barton
The revision contents are below, presented both in the original Wikispaces Wikitext format, and in HTML exactly as Wikispaces rendered it.<br>
<h4>Original Wikitext content:</h4>
<div style="width:100%; max-height:400pt; overflow:auto; background-color:#f8f9fa; border: 1px solid #eaecf0; padding:0em"><pre style="margin:0px;border:none;background:none;word-wrap:break-word;white-space: pre-wrap ! important" class="old-revision-html">&lt;span class="s1"&gt;// ChucK code for Superparticular Samchillian&lt;/span&gt;
&lt;span class="s1"&gt;// Samchillian idea by Leon Gruenbaum&lt;/span&gt;
&lt;span class="s1"&gt;// superparticular-ratio implementation by Jacob Barton&lt;/span&gt;


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


&lt;span class="s1"&gt;// change these to match your input/output device&lt;/span&gt;
//change these to match your input/output device
&lt;span class="s1"&gt;0 =&gt; int inDeviceNum;&lt;/span&gt;
0 => int inDeviceNum;
&lt;span class="s1"&gt;1 =&gt; int outDeviceNum;&lt;/span&gt;
1 => int outDeviceNum;


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


&lt;span class="s1"&gt;class&lt;/span&gt; MidiTransform
    fun void NoteOff( int nn, int vel)
{
    {
// superclass for MIDI transformers to be used by MicroRobinMidiIO
        myIO.NoteOff( prevFreqsByKey[nn], vel);
MicroRobinMidiIO myIO;
    }
&lt;span class="s1"&gt;fun void&lt;/span&gt; LinkToIO(MicroRobinMidiIO io)
{
io @=&gt; myIO;
}
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOn( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)
{
&lt;span class="s1"&gt;return&lt;/span&gt;;
}
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOff( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)
{
&lt;span class="s1"&gt;return&lt;/span&gt;;
}
}


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


Line 241: Line 259:
SuperparticularSamchillian easy;
SuperparticularSamchillian easy;
easy.LinkToIO(mrmio);
easy.LinkToIO(mrmio);
&lt;span class="s1"&gt;spork&lt;/span&gt; ~ mrmio.StartRelay( &lt;span class="s2"&gt;1&lt;/span&gt;, easy);
spork ~ mrmio.StartRelay( 1, easy);


&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="s3"&gt;::&lt;/span&gt;second&lt;span class="s3"&gt; =&gt; &lt;/span&gt;now&lt;span class="s3"&gt;;&lt;/span&gt;
1::second => now;


KBHit kb;  
KBHit kb;


while&lt;span class="s3"&gt;(&lt;/span&gt;true&lt;span class="s3"&gt;)&lt;/span&gt;
while(true)
{
{
kb =&gt; &lt;span class="s1"&gt;now&lt;/span&gt;;
    kb => now;
&lt;span class="s1"&gt;while&lt;/span&gt;( kb.more() )
 
{
    while( kb.more() )
kb.getchar() =&gt; &lt;span class="s1"&gt;int&lt;/span&gt; c;
    {
&lt;&lt;&lt; &lt;span class="s4"&gt;"ascii:"&lt;/span&gt;, c&gt;&gt;&gt;;
        kb.getchar() => int c;
easy.NoteOn(c, &lt;span class="s2"&gt;88&lt;/span&gt;);
        <<< "ascii:", c>>>;
        easy.NoteOn(c, 88);
    }
}
}
}</pre></div>
</pre>
<h4>Original HTML content:</h4>
== See also ==
<div style="width:100%; max-height:400pt; overflow:auto; background-color:#f8f9fa; border: 1px solid #eaecf0; padding:0em"><pre style="margin:0px;border:none;background:none;word-wrap:break-word;width:200%;white-space: pre-wrap ! important" class="old-revision-html">&lt;html&gt;&lt;head&gt;&lt;title&gt;superparticular samchillian&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;span class="s1"&gt;&lt;em&gt; ChucK code for Superparticular Samchillian&lt;/span&gt;&lt;br /&gt;
* [[Jacob Barton]]
&lt;span class="s1"&gt;&lt;/em&gt; Samchillian idea by Leon Gruenbaum&lt;/span&gt;&lt;br /&gt;
* [[Software]]
&lt;span class="s1"&gt;&lt;em&gt; superparticular-ratio implementation by Jacob Barton&lt;/span&gt;&lt;br /&gt;
 
&lt;br /&gt;
[[Category:chuck]]
&lt;/em&gt; paste these into a new document in miniAudicle, or save text as a .ck to run in command-line&lt;br /&gt;
[[Category:code]]
&lt;br /&gt;
[[Category:todo:link]]
&lt;span class="s1"&gt;&lt;em&gt; change these to match your input/output device&lt;/span&gt;&lt;br /&gt;
&lt;span class="s1"&gt;0 =&amp;gt; int inDeviceNum;&lt;/span&gt;&lt;br /&gt;
&lt;span class="s1"&gt;1 =&amp;gt; int outDeviceNum;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="s1"&gt;class&lt;/span&gt; MicroRobinMidiIO&lt;br /&gt;
{&lt;br /&gt;
MidiIn min;&lt;br /&gt;
MidiOut mouse;&lt;br /&gt;
MidiMsg inmsg, outmsg;&lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; ctr;&lt;br /&gt;
&lt;/em&gt;int rr[128][3]; don't think we need this now.&lt;br /&gt;
&lt;em&gt; index = note number?&lt;br /&gt;
&lt;/em&gt; column 0 = channel sent to&lt;br /&gt;
&lt;em&gt; column 1 = note number sent&lt;br /&gt;
&lt;span class="s1"&gt;int&lt;/span&gt;&lt;span class="s3"&gt; chans[&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="s3"&gt;]; &lt;/span&gt;&lt;/em&gt; list of channels used&lt;br /&gt;
&lt;span class="s1"&gt;float&lt;/span&gt;&lt;span class="s3"&gt; holds[&lt;/span&gt;&lt;span class="s2"&gt;16&lt;/span&gt;&lt;span class="s3"&gt;]; &lt;/span&gt;&lt;em&gt; pitches of on notes, zero if off.&lt;br /&gt;
&lt;span class="s3"&gt; [&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;7&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;11&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;12&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;13&lt;/span&gt;&lt;span class="s3"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="s3"&gt;] @=&amp;gt; chans; &lt;/span&gt;&lt;/em&gt;exclude channel 10 (drums) &amp;amp; 16 (send channel)&lt;br /&gt;
&lt;em&gt;microtuning stuff&lt;br /&gt;
&lt;/em&gt; PitchBend&lt;br /&gt;
&lt;em&gt; input: pitch (midi note number float) &amp;amp; velocity of desired note&lt;br /&gt;
&lt;/em&gt; action: sends appropriate pitchbend message&lt;br /&gt;
&lt;em&gt; (assuming pitchbend range = +/- 2 semitones)&lt;br /&gt;
&lt;/em&gt; output: note number required for correct frequency to be realized&lt;br /&gt;
&lt;em&gt; sends pitchbend, assuming +/- wholestep pitchbend range&lt;br /&gt;
&lt;/em&gt; returns note number required for correct frequency&lt;br /&gt;
&lt;span class="s1"&gt;fun int&lt;/span&gt; PitchBend(&lt;span class="s1"&gt;float&lt;/span&gt; pitch, &lt;span class="s1"&gt;int&lt;/span&gt; velocity)&lt;br /&gt;
{&lt;br /&gt;
&lt;em&gt;send pitchbend&lt;br /&gt;
&lt;span class="s2"&gt;224&lt;/span&gt; + chans[ctr] =&amp;gt; outmsg.data1;&lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; outmsg.data2;&lt;br /&gt;
Math.round((pitch % &lt;span class="s2"&gt;1&lt;/span&gt;.&lt;span class="s2"&gt;0&lt;/span&gt;) * &lt;span class="s2"&gt;32&lt;/span&gt;.&lt;span class="s2"&gt;0&lt;/span&gt; + &lt;span class="s2"&gt;64&lt;/span&gt;.&lt;span class="s2"&gt;0&lt;/span&gt;) $ &lt;span class="s1"&gt;int&lt;/span&gt; =&amp;gt; outmsg.data3;&lt;br /&gt;
mouse.send(outmsg);&lt;br /&gt;
&lt;span class="s1"&gt;return&lt;/span&gt; Math.floor(pitch) $ &lt;span class="s1"&gt;int&lt;/span&gt;;&lt;br /&gt;
}&lt;br /&gt;
&lt;/em&gt; StartRelay&lt;br /&gt;
&lt;em&gt; input: number of MIDI device, MidiTransform to be used&lt;br /&gt;
&lt;/em&gt; creates a loop ~ should be sporked&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; StartRelay(&lt;span class="s1"&gt;int&lt;/span&gt; deviceNum, MidiTransform mt)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( !min.open(&lt;span class="s2"&gt;inDeviceNum&lt;/span&gt;)) &lt;span class="s1"&gt;me&lt;/span&gt;.exit();&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( !mouse.open(outDeviceNum)) &lt;span class="s1"&gt;me&lt;/span&gt;.exit();&lt;br /&gt;
&lt;em&gt; print out device that was opened&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; min.num(), &lt;span class="s4"&gt;&amp;quot; -&amp;gt; &amp;quot;&lt;/span&gt;, min.name() &amp;gt;&amp;gt;&amp;gt;;&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; mouse.num(), &lt;span class="s4"&gt;&amp;quot; -&amp;gt; &amp;quot;&lt;/span&gt;, mouse.name() &amp;gt;&amp;gt;&amp;gt;;&lt;br /&gt;
&lt;span class="s1"&gt;while&lt;/span&gt; ( &lt;span class="s1"&gt;true&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
min =&amp;gt; &lt;span class="s1"&gt;now&lt;/span&gt;;&lt;br /&gt;
&lt;span class="s1"&gt;while&lt;/span&gt;( min.recv(inmsg))&lt;br /&gt;
{ &lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( inmsg.data1 % &lt;span class="s2"&gt;16&lt;/span&gt; == &lt;span class="s2"&gt;0&lt;/span&gt;) &lt;span class="s5"&gt;&lt;/em&gt; only receive on channel 1&lt;/span&gt;&lt;br /&gt;
{&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; &lt;span class="s4"&gt;&amp;quot;r &amp;quot;&lt;/span&gt;, inmsg.data1 / &lt;span class="s2"&gt;16&lt;/span&gt;, inmsg.data1 % &lt;span class="s2"&gt;16&lt;/span&gt;, inmsg.data2, inmsg.data3&amp;gt;&amp;gt;&amp;gt;;&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( inmsg.data1 / &lt;span class="s2"&gt;16&lt;/span&gt; == &lt;span class="s2"&gt;9&lt;/span&gt;)&lt;br /&gt;
{ &lt;br /&gt;
mt.NoteOn(inmsg.data2, inmsg.data3);&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( inmsg.data1 / &lt;span class="s2"&gt;16&lt;/span&gt; == &lt;span class="s2"&gt;8&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
mt.NoteOff(inmsg.data2, inmsg.data3);&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;( inmsg.data1 / &lt;span class="s2"&gt;16&lt;/span&gt; == &lt;span class="s2"&gt;12&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&lt;em&gt;prog change apply to channels 1-16&lt;br /&gt;
&lt;span class="s5"&gt;&lt;/em&gt;works!&lt;/span&gt;&lt;br /&gt;
inmsg.data1 - (inmsg.data1 % &lt;span class="s2"&gt;16&lt;/span&gt;) =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; base;&lt;br /&gt;
&lt;span class="s1"&gt;for&lt;/span&gt;(&lt;span class="s2"&gt;0&lt;/span&gt;=&amp;gt;&lt;span class="s1"&gt;int&lt;/span&gt; i; i&amp;lt;&lt;span class="s2"&gt;15&lt;/span&gt;; 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;
&lt;span class="s1"&gt;if&lt;/span&gt;( i == &lt;span class="s2"&gt;15&lt;/span&gt;) &lt;br /&gt;
{ &lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; outmsg.data3;&lt;br /&gt;
mouse.send(outmsg);&lt;br /&gt;
&lt;span class="s1"&gt;break&lt;/span&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;
&lt;span class="s1"&gt;if&lt;/span&gt;( i == &lt;span class="s2"&gt;15&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; outmsg.data2 =&amp;gt; outmsg.data3;&lt;br /&gt;
mouse.send(outmsg);&lt;br /&gt;
&lt;span class="s1"&gt;break&lt;/span&gt;;&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;span class="s1"&gt;if&lt;/span&gt;( inmsg.data1 / &lt;span class="s2"&gt;16&lt;/span&gt; == &lt;span class="s2"&gt;11&lt;/span&gt;)&lt;br /&gt;
{&lt;br /&gt;
&lt;em&gt;apply any controller data to channels 1-16&lt;br /&gt;
inmsg.data1 - (inmsg.data1 % &lt;span class="s2"&gt;16&lt;/span&gt;) =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; base;&lt;br /&gt;
inmsg.data2 =&amp;gt; outmsg.data2;&lt;br /&gt;
inmsg.data3 =&amp;gt; outmsg.data3;&lt;br /&gt;
&lt;span class="s1"&gt;for&lt;/span&gt;(&lt;span class="s2"&gt;0&lt;/span&gt;=&amp;gt;&lt;span class="s1"&gt;int&lt;/span&gt; i; i&amp;lt;&lt;span class="s2"&gt;16&lt;/span&gt;; 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;
&lt;/em&gt; NoteOn&lt;br /&gt;
&lt;em&gt; input: pitch in midi note-number extended, velocity&lt;br /&gt;
&lt;/em&gt; action: sends a MIDI pitchbend + note-on message to mouse on the current channel&lt;br /&gt;
&lt;em&gt; keeping track of holds&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOn(&lt;span class="s1"&gt;float&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; velocity)&lt;br /&gt;
{&lt;br /&gt;
IncrementCtr();&lt;br /&gt;
nn =&amp;gt; holds[chans[ctr%&lt;span class="s2"&gt;14&lt;/span&gt;]];&lt;br /&gt;
PitchBend(nn, velocity) =&amp;gt; outmsg.data2;&lt;br /&gt;
&lt;/em&gt; note on, right channel&lt;br /&gt;
&lt;span class="s2"&gt;144&lt;/span&gt; + chans[ctr%&lt;span class="s2"&gt;14&lt;/span&gt;] =&amp;gt; outmsg.data1; &lt;br /&gt;
velocity =&amp;gt; outmsg.data3;&lt;br /&gt;
mouse.send(outmsg);&lt;br /&gt;
&lt;em&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;/em&gt; increments mod-14 counter, skipping over channels with&lt;br /&gt;
&lt;em&gt; notes already on them, if possible.&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; IncrementCtr()&lt;br /&gt;
{&lt;br /&gt;
ctr;&lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; i;&lt;br /&gt;
&lt;span class="s1"&gt;for&lt;/span&gt;( i; i&amp;lt;&lt;span class="s2"&gt;14&lt;/span&gt;; i++)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt; ( holds[chans[(ctr+i) % &lt;span class="s2"&gt;14&lt;/span&gt;]] == &lt;span class="s2"&gt;0&lt;/span&gt;.&lt;span class="s2"&gt;0&lt;/span&gt;)&lt;br /&gt;
{ (ctr + i) % &lt;span class="s2"&gt;14&lt;/span&gt; =&amp;gt; ctr; &lt;span class="s1"&gt;return&lt;/span&gt;; }&lt;br /&gt;
}&lt;br /&gt;
(ctr + &lt;span class="s2"&gt;1&lt;/span&gt;) % &lt;span class="s2"&gt;14&lt;/span&gt; =&amp;gt; ctr;&lt;br /&gt;
}&lt;br /&gt;
&lt;/em&gt; NoteOff&lt;br /&gt;
&lt;em&gt; input: pitch &amp;amp; note-off velocity&lt;br /&gt;
&lt;/em&gt; action: finds the pitch &amp;amp; offs it.&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOff(&lt;span class="s1"&gt;float&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; velocity)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; c;&lt;br /&gt;
&lt;span class="s1"&gt;for&lt;/span&gt;(c; c&amp;lt;&lt;span class="s2"&gt;16&lt;/span&gt;; c++)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;(holds[c] == nn) &lt;span class="s5"&gt;&lt;em&gt; we found the pitch!&lt;/span&gt;&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;128&lt;/span&gt; + c =&amp;gt; outmsg.data1;&lt;br /&gt;
Math.floor(nn) $ &lt;span class="s1"&gt;int&lt;/span&gt; =&amp;gt; outmsg.data2;&lt;br /&gt;
velocity =&amp;gt; outmsg.data3;&lt;br /&gt;
mouse.send(outmsg);&lt;br /&gt;
&lt;/em&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;span class="s2"&gt;0&lt;/span&gt;.&lt;span class="s2"&gt;0&lt;/span&gt; =&amp;gt; holds[c];&lt;br /&gt;
&lt;span class="s1"&gt;return&lt;/span&gt;;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt;&lt;span class="s4"&gt;&amp;quot;MISS&amp;quot;&lt;/span&gt;, nn&amp;gt;&amp;gt;&amp;gt;;&lt;br /&gt;
&lt;em&gt; we couldn't find the pitch!&lt;br /&gt;
&lt;/em&gt; don't do anything. &lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; ControlChange(&lt;span class="s1"&gt;int&lt;/span&gt; channel, &lt;span class="s1"&gt;int&lt;/span&gt; prognum, &lt;span class="s1"&gt;int&lt;/span&gt; val)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;128&lt;/span&gt; + 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;span class="s1"&gt;class&lt;/span&gt; MidiTransform&lt;br /&gt;
{&lt;br /&gt;
&lt;em&gt; superclass for MIDI transformers to be used by MicroRobinMidiIO&lt;br /&gt;
MicroRobinMidiIO myIO;&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; LinkToIO(MicroRobinMidiIO io)&lt;br /&gt;
{&lt;br /&gt;
io @=&amp;gt; myIO;&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOn( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;return&lt;/span&gt;;&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOff( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;return&lt;/span&gt;;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;span class="s1"&gt;class&lt;/span&gt; SuperparticularSamchillian &lt;span class="s1"&gt;extends&lt;/span&gt; MidiTransform&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;57&lt;/span&gt;. =&amp;gt; &lt;span class="s1"&gt;float&lt;/span&gt; resentFreq;&lt;br /&gt;
&lt;span class="s2"&gt;57&lt;/span&gt;. =&amp;gt; &lt;span class="s1"&gt;float&lt;/span&gt; prevFreq; &lt;br /&gt;
&lt;span class="s2"&gt;62&lt;/span&gt; =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; keyboardCenterNN;&lt;br /&gt;
&lt;span class="s1"&gt;float&lt;/span&gt; prevFreqsByKey[&lt;span class="s2"&gt;128&lt;/span&gt;];&lt;br /&gt;
&lt;/em&gt;set pans funky&lt;br /&gt;
&lt;em&gt;for(0=&amp;gt;int f; f&amp;lt;16; f++)&lt;br /&gt;
&lt;span class="s5"&gt;&lt;/em&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;em&gt; myIO.ControlChange(f, 9, f*8);&lt;br /&gt;
&lt;span class="s5"&gt;&lt;/em&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span class="s1"&gt;fun void&lt;/span&gt; NoteOn( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;(nn == keyboardCenterNN)&lt;br /&gt;
{&lt;br /&gt;
myIO.NoteOn( Std.ftom(prevFreq), vel);&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;else&lt;/span&gt;&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;(nn &amp;lt; keyboardCenterNN)&lt;br /&gt;
{&lt;br /&gt;
// superparticular!&lt;br /&gt;
&lt;span class="s2"&gt;1&lt;/span&gt;. + &lt;span class="s2"&gt;1&lt;/span&gt;./(keyboardCenterNN - nn) /=&amp;gt; prevFreq;&lt;br /&gt;
myIO.NoteOn( Std.ftom(prevFreq), vel);&lt;br /&gt;
}&lt;br /&gt;
&lt;span class="s1"&gt;else&lt;/span&gt;&lt;br /&gt;
{ &lt;br /&gt;
&lt;span class="s1"&gt;if&lt;/span&gt;(nn &amp;gt; keyboardCenterNN)&lt;br /&gt;
{&lt;br /&gt;
&lt;span class="s2"&gt;1&lt;/span&gt;. + &lt;span class="s2"&gt;1&lt;/span&gt;./(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;span class="s1"&gt;fun void&lt;/span&gt; NoteOff( &lt;span class="s1"&gt;int&lt;/span&gt; nn, &lt;span class="s1"&gt;int&lt;/span&gt; vel)&lt;br /&gt;
{&lt;br /&gt;
myIO.NoteOff( prevFreqsByKey[nn], vel);&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;
&lt;span class="s1"&gt;spork&lt;/span&gt; ~ mrmio.StartRelay( &lt;span class="s2"&gt;1&lt;/span&gt;, easy);&lt;br /&gt;
&lt;br /&gt;
&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="s3"&gt;::&lt;/span&gt;second&lt;span class="s3"&gt; =&amp;gt; &lt;/span&gt;now&lt;span class="s3"&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
KBHit kb; &lt;br /&gt;
&lt;br /&gt;
while&lt;span class="s3"&gt;(&lt;/span&gt;true&lt;span class="s3"&gt;)&lt;/span&gt;&lt;br /&gt;
{&lt;br /&gt;
kb =&amp;gt; &lt;span class="s1"&gt;now&lt;/span&gt;;&lt;br /&gt;
&lt;span class="s1"&gt;while&lt;/span&gt;( kb.more() )&lt;br /&gt;
{&lt;br /&gt;
kb.getchar() =&amp;gt; &lt;span class="s1"&gt;int&lt;/span&gt; c;&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt; &lt;span class="s4"&gt;&amp;quot;ascii:&amp;quot;&lt;/span&gt;, c&amp;gt;&amp;gt;&amp;gt;;&lt;br /&gt;
easy.NoteOn(c, &lt;span class="s2"&gt;88&lt;/span&gt;);&lt;br /&gt;
}&lt;br /&gt;
}&lt;/body&gt;&lt;/html&gt;</pre></div>