Superparticular samchillian: Difference between revisions
Wikispaces>xenjacob **Imported revision 343572870 - Original comment: ** |
Wikispaces>xenjacob **Imported revision 343680102 - Original comment: ** |
||
Line 1: | Line 1: | ||
<h2>IMPORTED REVISION FROM WIKISPACES</h2> | <h2>IMPORTED REVISION FROM WIKISPACES</h2> | ||
This is an imported revision from Wikispaces. The revision metadata is included below for reference:<br> | This is an imported revision from Wikispaces. The revision metadata is included below for reference:<br> | ||
: This revision was by author [[User:xenjacob|xenjacob]] and made on <tt>2012-06-07 | : This revision was by author [[User:xenjacob|xenjacob]] and made on <tt>2012-06-07 19:38:40 UTC</tt>.<br> | ||
: The original revision id was <tt> | : The original revision id was <tt>343680102</tt>.<br> | ||
: The revision comment was: <tt></tt><br> | : The revision comment was: <tt></tt><br> | ||
The revision contents are below, presented both in the original Wikispaces Wikitext format, and in HTML exactly as Wikispaces rendered it.<br> | 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> | <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"> | <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">[[code format="java"]] | ||
// | //ChucK code for Superparticular Samchillian | ||
//Samchillian idea by Leon Gruenbaum | |||
//superparticular-ratio implementation by Jacob Barton | |||
//paste these lines into a new document in miniAudicle, or save text as a .ck to run in command-line | |||
//change these to match your input/output device | |||
0 => int inDeviceNum; | |||
1 => int outDeviceNum; | |||
class MicroRobinMidiIO | |||
{ | { | ||
MidiIn min; | |||
MidiOut mouse; | |||
MidiMsg inmsg, outmsg; | |||
0 => int ctr; | |||
//int rr[128][3]; don't think we need this now. | |||
// index = note number? | |||
// column 0 = channel sent to | |||
// column 1 = note number sent | |||
& | int chans[14]; // list of channels used | ||
float holds[16]; // pitches of on notes, zero if off. | |||
// | [0,1,2,3,4,5,6,7,8,10,11,12,13,14] @=> chans; //exclude channel 10 (drums) & 16 (send channel) | ||
//microtuning stuff | |||
// PitchBend | |||
// input: pitch (midi note number float) & velocity of desired note | |||
// action: sends appropriate pitchbend message | |||
mouse. | // (assuming pitchbend range = +/- 2 semitones) | ||
// output: note number required for correct frequency to be realized | |||
// sends pitchbend, assuming +/- wholestep pitchbend range | |||
// returns note number required for correct frequency | |||
fun int PitchBend(float pitch, int velocity) | |||
{ | |||
//send pitchbend | |||
224 + chans[ctr] => outmsg.data1; | |||
0 => outmsg.data2; | |||
// | Math.round((pitch % 1.0) * 32.0 + 64.0) $ int => outmsg.data3; | ||
mouse.send(outmsg); | |||
< | return Math.floor(pitch) $ int; | ||
{ | } | ||
// StartRelay | |||
// input: number of MIDI device, MidiTransform to be used | |||
// | // creates a loop ~ should be sporked | ||
fun void StartRelay(int deviceNum, MidiTransform mt) | |||
{ | |||
if( !min.open(inDeviceNum)) me.exit(); | |||
if( !mouse.open(outDeviceNum)) me.exit(); | |||
// print out device that was opened | |||
<<< min.num(), " -> ", min.name() >>>; | |||
{ | <<< mouse.num(), " -> ", mouse.name() >>>; | ||
& | while ( true) | ||
{ | |||
min => now; | |||
while( min.recv(inmsg)) | |||
{ | |||
if( inmsg.data1 % 16 == 0) // only receive on channel 1 | |||
} | { | ||
<<< "r ", inmsg.data1 / 16, inmsg.data1 % 16, inmsg.data2, inmsg.data3>>>; | |||
// | |||
// | if( inmsg.data1 / 16 == 9) | ||
{ | |||
{ | mt.NoteOn(inmsg.data2, inmsg.data3); | ||
} | |||
if( inmsg.data1 / 16 == 8) | |||
{ | { | ||
mt.NoteOff(inmsg.data2, inmsg.data3); | |||
{ | } | ||
if( inmsg.data1 / 16 == 12) | |||
Math.floor(nn) $ & | { | ||
velocity => outmsg.data3; | //prog change apply to channels 1-16 | ||
mouse.send(outmsg); | //works! | ||
//<<< "s ", outmsg.data1 / 16, outmsg.data1 % 16, outmsg.data2, outmsg.data3>>>; | 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; | |||
} | |||
prognum => outmsg.data2; | |||
val => outmsg.data3; | 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 | // superclass for MIDI transformers to be used by MicroRobinMidiIO | ||
MicroRobinMidiIO myIO; | MicroRobinMidiIO myIO; | ||
fun void LinkToIO(MicroRobinMidiIO io) | |||
{ | { | ||
io @=> myIO; | 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; | ||
myIO.NoteOn( Std.ftom(prevFreq), vel); | 57. => float prevFreq; | ||
} | |||
} | 62 => int keyboardCenterNN; | ||
} | |||
Std.ftom(prevFreq) => prevFreqsByKey[nn]; | float prevFreqsByKey[128]; | ||
} | |||
//set pans funky | |||
{ | //for(0=>int f; f<16; f++) | ||
myIO.NoteOff( prevFreqsByKey[nn], vel); | //{ | ||
} | // 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); | |||
} | |||
} | } | ||
Line 241: | Line 266: | ||
SuperparticularSamchillian easy; | SuperparticularSamchillian easy; | ||
easy.LinkToIO(mrmio); | easy.LinkToIO(mrmio); | ||
spork ~ mrmio.StartRelay( 1, easy); | |||
1::second => now; | |||
KBHit kb; | KBHit kb; | ||
while | while(true) | ||
{ | { | ||
kb = | kb => now; | ||
{ | while( kb.more() ) | ||
kb.getchar() = | { | ||
<<< | kb.getchar() => int c; | ||
easy.NoteOn(c, | <<< "ascii:", c>>>; | ||
easy.NoteOn(c, 88); | |||
} | |||
} | } | ||
[[code]]</pre></div> | |||
<h4>Original HTML content:</h4> | <h4>Original HTML 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;width:200%;white-space: pre-wrap ! important" class="old-revision-html"><html><head><title>superparticular samchillian</title></head><body><!-- ws:start:WikiTextCodeRule:0: | |||
&lt;pre class=&quot;java&quot;&gt;//ChucK code for Superparticular Samchillian&lt;br/&gt;//Samchillian idea by Leon Gruenbaum&lt;br/&gt;//superparticular-ratio implementation by Jacob Barton&lt;br/&gt;&lt;br/&gt;//paste these lines into a new document in miniAudicle, or save text as a .ck to run in command-line&lt;br/&gt;&lt;br/&gt;//change these to match your input/output device& | |||