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