// markov chain distribution // add a couple more oscilators // ** envelopes add // *** envelopes before reverb work even better Blit s => ADSR e => JCRev r => dac; Blit s1 => ADSR e1 => JCRev r1 => dac; Blit s2 => ADSR e2 => JCRev r2 => dac; // set the harmonics 2 => s.harmonics; 2 => s1.harmonics; 2 => s2.harmonics; // ** envelope set 40::ms => dur declick => e.attackTime => e1.attackTime => e2.attackTime; 250::ms => e.decayTime => e1.decayTime => e2.decayTime; .1 => e.sustainLevel => e1.sustainLevel => e2.sustainLevel; 400::ms => e.releaseTime => e1.releaseTime => e2.releaseTime; // make the added oscilators a bit dry. 0.1 => r.mix; 0.05 => r1.mix; 0.05 => r2.mix; // start with only the first osc audible. 0.3 => s.gain; 0.0 => s1.gain; 0.0 => s2.gain; // *** adding a display (not an interface) MAUI_View view; MAUI_Slider slider1; MAUI_Slider slider2; MAUI_Slider slider3; slider1.range( 0, 8 ); slider2.range( 0, 8 ); slider3.range( 0, 8 ); slider1.name( "Pitch 1" ); slider2.name( "Pitch 2" ); slider3.name( "Pitch 3" ); slider1.position(0, 0); slider2.position(0, slider1.height()); slider3.position(0, slider2.y() + slider2.height()); view.addElement(slider1); view.addElement(slider2); view.addElement(slider3); MAUI_LED l1, l2, l3; l1.color( l1.red ); l2.color( l2.red ); l3.color( l3.red ); l1.size( 50, 50 ); l2.size( 50, 50 ); l3.size( 50, 50 ); l1.position( slider1.width(), slider1.y() ); l2.position( slider2.width(), slider2.y() ); l3.position( slider3.width(), slider3.y() ); view.addElement(l1); view.addElement(l2); view.addElement(l3); l1.light(); view.size( l1.x() + l1.width(), slider3.y()+slider3.height()); view.display(); // three sets of notes for three osc. chosen pretty much blindly. //[[ 60, 62, 64, 67, 69, 72, 74, 76, 79, 81], // [ 43, 45, 48, 50, 52, 55, 57, 60, 62, 64], // [ 36, 38, 40, 43, 45, 48, 50, 52, 55, 57]] @=> int pitches[][]; // ** adaptation (b, phase, c, phase-octave, some doubling)... // ** ... top is rough sung melody from "prospectus" by s lacy //[[ 67, 74, 58, 48, 56, 52, 55, 52, 50, 46, 44], // [ 48, 56, 52, 55, 52, 50, 46, 44, 67, 74, 58], // [ 36, 44, 40, 43, 40, 38, 34, 32, 43, 50, 46]] @=> int pitches[][]; // *** messing with/up al's pitches /* [[ 46, 62, 52, 67, 48, 70, 67, 86, 76], [ 48, 56, 52, 55, 46, 44, 58, 67, 74], [ 36, 46, 50, 43, 38, 40, 40, 43, 44]] @=> int pitches[][]; */ [[ 46, 50, 52, 54, 48, 58, 66, 74, 76], [ 48, 56, 52, 54, 46, 44, 58, 66, 74], [ 36, 46, 50, 42, 38, 40, 40, 42, 44]] @=> int pitches[][]; // groups[] determines which oscilators are on, based on what // pitch the first oscilator is at. the further down the array // that oscilator is, the more other oscilators are made audible. [ 0, 0, 0, 1, 1, 1, 2, 2, 2] @=> int groups[]; // i made this table from crap, i mean scratch. the first // oscilator basically steps through the array of pitches, // but towards the middle of the array, it's more likely to go // back and forth. towards the end, it gets locked into step so // the last three notes will definitely happen in a row. no note // ever follows itself, so there's always a constant pulse. [[0.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00], [0.10, 0.00, 0.90, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00], [0.00, 0.10, 0.00, 0.90, 0.00, 0.00, 0.00, 0.00, 0.00], [0.00, 0.00, 0.20, 0.00, 0.80, 0.00, 0.00, 0.00, 0.00], [0.00, 0.00, 0.00, 0.30, 0.00, 0.70, 0.00, 0.00, 0.00], [0.00, 0.00, 0.00, 0.00, 0.50, 0.00, 0.50, 0.00, 0.00], [0.00, 0.00, 0.00, 0.00, 0.00, 0.40, 0.00, 0.60, 0.00], [0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00], [1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00]] @=> float markov[][]; // convert to cumulative distributions for each row for (0 => int i; i < 8; i++) { for (1 => int j; j < 8; j++) { markov[i][j] + markov[i][j-1] => markov[i][j]; } } 0 => int i_cur; 0 => int j_cur; 0 => int k_cur; while (true) { std.rand2f(0, 1) => float rand; 0 => int i; while (markov[i_cur][i] < rand) i++; // determine the frequencies of the 2nd and 3rd sinosc, at random std.rand2f(0, 1) => rand; 0 => int j; while (markov[j_cur][j] < rand) j++; std.rand2f(0, 1) => rand; 0 => int k; while (markov[k_cur][k] < rand) k++; // forced the 2nd and 3rd to loop back if the first does if(i_cur == 8 && i == 0){ 0 => i_cur; 0 => j_cur; 0 => k_cur; } else { i => i_cur; j => j_cur; k => k_cur; } std.mtof(pitches[0][i_cur]) => s.freq; std.mtof(pitches[1][j_cur]) => s1.freq; std.mtof(pitches[2][j_cur]) => s2.freq; // *** update the sliders slider1.value(i_cur); slider2.value(j_cur); slider3.value(k_cur); // ** draft timing change includes envelope, slight irregularity Math.randf() * .2 => float stutter; e.keyOn(); e1.keyOn(); e2.keyOn(); 200::ms - 15::ms + stutter::ms => now; e.keyOff(); e1.keyOff(); e2.keyOff(); // ** time advance moved to here declick => now; //determine the gains of the three melodies, // based on groups[curIndex] 0.45 => s.gain; if(groups[i_cur] >= 1){ 0.45 => s.gain; 0.25 => s1.gain; l2.light(); } else { 0.0 => s1.gain; l2.unlight(); } if(groups[i_cur] >= 2){ 0.45 => s.gain; 0.15 => s1.gain; 0.15 => s2.gain; l3.light(); } else { 0.0 => s2.gain; l3.unlight(); } }