// ----------------------------------------------------------------
// Mouse Bow (v1)
// by Jeff Lipscomb (February 9, 2010)
//
// The keyboard controls the pitch of this instrument,
// while the mouse controls both the loudness and the timbre.
// Clicking any button will turn the note on,
// while unclicking that button will turn it off.
// The SPEED of the left-right motion controls how loud the note is
// (the faster the motion, the louder it will be.)
// The up-down position of the mouse on the screen controls how
// bright/complex the note's timbre will be.
// (the higher up, the more brighter it will be.)
//
// (push key that wasn't mapped for a really cool sound, like '~')
// ----------------------------------------------------------------
//
// some tuning and timbre-related variables
600.0 => float cFrq;
18.07 => float nDiv;
2.01 => float mRat;
950.0 => float hFlt;
400.0 => float lFlt;
// initialize and test for a mouse
Hid hi;
HidMsg msg;
0 => int device;
if( me.args() ) me.arg(0) => Std.atoi => device;
if( !hi.openMouse( device ) ) me.exit();
// UGen guts
SinOsc mod => SinOsc car => ADSR e => LPF f1 => HPF f2 => Chorus c => JCRev r => dac;
e.set( 10::ms, 5::ms, .85, 10::ms );
e.keyOff();
// initial parameters for the UGens
cFrq => car.freq;
cFrq * mRat => mod.freq; //1.07aa
hFlt => f1.freq;
lFlt => f2.freq;
1000.0 => mod.gain;
0.0 => e.gain;
// sync is for an FM instrument
2 => car.sync;
// initializing variables for controlling function
int base;
float a0;
float a1;
float a2;
float a3;
int count;
// initialize keyboard array
// MIDI pitch numbers are assigned to most of the keys
// which are represented by their ASCII numbers
int kb[112];
49 => kb[90]; // z
50 => kb[88]; // x
51 => kb[67]; // c
52 => kb[86]; // v
53 => kb[66]; // b
54 => kb[78]; // n
55 => kb[77]; // m
56 => kb[44]; // ,
57 => kb[46]; // .
58 => kb[47]; // /
59 => kb[65]; // a
60 => kb[83]; // s
61 => kb[68]; // d
62 => kb[70]; // f
63 => kb[71]; // g
64 => kb[72]; // h
65 => kb[74]; // j
66 => kb[75]; // k
67 => kb[76]; // l
68 => kb[59]; // ;
69 => kb[81]; // q
70 => kb[87]; // w
71 => kb[69]; // e
72 => kb[82]; // r
73 => kb[84]; // t
74 => kb[89]; // y
75 => kb[85]; // u
76 => kb[73]; // i
77 => kb[79]; // o
78 => kb[80]; // p
79 => kb[49]; // 1
80 => kb[50]; // 2
81 => kb[51]; // 3
82 => kb[52]; // 4
83 => kb[53]; // 5
84 => kb[54]; // 6
85 => kb[55]; // 7
86 => kb[56]; // 8
87 => kb[57]; // 9
88 => kb[48]; // 0
// initialize tuning function
// for a 10-TET tuning scheme instead of 12-TET
fun float midiTune( int x )
{
return cFrq * Math.pow( 2.0, ( x - 69 ) / nDiv );
}
//the keyboard detect function
fun void thePits()
{
Hid hi2;
HidMsg msg2;
0 => int device2;
if( me.args() ) me.arg(0) => Std.atoi => device2;
if( !hi2.openKeyboard( device2 ) ) me.exit();
while( true )
{
hi2 => now;
while( hi2.recv( msg2 ) )
{
if( msg2.isButtonDown() )
{
midiTune( kb[msg2.ascii] ) => a3;
a3 * mRat => a2;
set( base, a0, a1, a2, a3 );
}
}
}
}
//sporking out the keyboard function
spork ~ thePits();
// custom function controls parameters of note
set( base, a0, a1, a2, a3 );
// infinite loop
while( true )
{
// time advances when the mouse does something
hi => now;
// determines how to respond when mouse does something
while( hi.recv( msg ) )
{
if( msg.isMouseMotion() )
{
// X-Axis controls how loud the note is
if( msg.deltaX )
{
Std.fabs( msg.deltaX ) * .0083 - .0083 => a1; //sets gain
set( base, a0, a1, a2, a3 );
}
// Y-Axis controls how bright the note is
if( msg.deltaY )
{
Std.fabs( -msg.deltaY * .0083 + a0 ) => a0; //sets index (brightness)
set( base, a0, a1, a2, a3 );
}
}
else if( msg.isWheelMotion() )
{
// for now the mouse wheel controls pitch
if( msg.deltaY )
{
msg.deltaY * .8333 + a2 => a2; //sets carrier freq
set( base, a0, a1, a2, a3 );
}
}
else if( msg.isButtonDown() )
{
// pressing button presses the "bow" into the "string"
msg.which => base;
count++;
if( count == 1 ) e.keyOn();
10::ms => now;
set( base, a0, a1, a2, a3 );
}
else if( msg.isButtonUp() )
{
// lifting button also lifts "bow" from the "string"
msg.which => base;
count--;
if( !count )
{
e.keyOff();
0.0 => a1; // just making sure each note starts from 0dB
}
}
}
}
fun void set( int base, float v0, float v1, float v2, float v3 )
{
//changes pitches
v3 => car.freq;
//changes mod freq
v2 => mod.freq;
//gain
v1 => e.gain;
//mod index
( 500 * ( v0 + 1 ) ) => mod.gain;
}