// KNoW Generator (Kijjaz No Wave) // Copyright 2008 Les Hall // This software is protected by the GNU General Public License // parameters 12 => int n; // number of bits and number of logic terms 12 => int k; // number of logic expressions in each song 1 => int num_guitar_strings; // max number of guitar strings // variables Math.pow (2, n) $ int => int m; // 2 ^ n 0 => int b; // the binary counter 0 => int c; // the song counter 4 => int num_inst; // number of instruments int l[num_inst][k]; // the logic expressions int mask; // bit mask int f; // the frequency index float v; // the drum velocity float h; // snare hit strength int sf; // sax frequency int sc; /// sax duration counter string s; // output string int x; // used in generating logic expression float strength; // strength of guitar string vibration int numStrings; // number of strings float stringDamping; // guitar parameter float bodySize; // guitar parameter float stringDetune; // guitar parameter 8 => float tempo; // beats per second 1 => int next_song; // 1 to change to next song 0 => int kb_device; // keyboard device float fbase; // frequency base float temp; // temporary variable int o; // number of octaves to scale int gsi; // guitar scale index int gbn; // guitar base note int gsa[k+1]; // guitar scale advancement int ssi; // sax scale index int sbn; // sax base note int ssa[k+1]; // sax scale advancement [0, 2, 4, 7, 9] @=> int maps[]; // major pentatonic scale [0, 3, 5, 7, 10] @=> int mips[]; // minor pentatonic scale [0, 3, 5, 6, 7, 9, 10] @=> int blues1[]; // blues scale 1 [0, 2, 3, 5, 6, 9, 10] @=> int blues2[]; // blues scale 2 [0, 3, 4, 5, 6, 7, 10] @=> int blues3[]; // blues scale 3 [0, 3, 4, 6, 7, 9, 10] @=> int blues4[]; // blues scale 4 int scl; // scale length int scale[12]; // the current scale int si; // the scale index float gg; // guitar gain float gdo; // guitar distortion level float bdg; // bass drum gain float sdg; // snare drum gain float sg; // sax gain 0.660::ms => dur max_delay; // maximum time delay between ears (1.0/2.0)*(pi/2.0) => float theta; // angle float power; // exponent for logic table // load scale advancement array(s) for (int i; i<=k; i++) { i => gsa[i] => ssa[i]; } // guitar patch guitar strat; // bass drum patch by kijjaz // // initial values 100 => float MAIN_FREQUENCY; 12 => float BODY_SUSTAIN; 100 => float MAIN_OVERDRIVE; 1900 => float NOISE_FREQ; 0.4 => float NOISE_Q; .08 => float NOISE_VOLUMN; 300 => float NOISE_SUSTAIN; 0.8 => float HUM_FEEDBACK; 800 => float HUM_FILTER_FREQ; 12 => float HUM_VOLUMN; // // mechanism: // // bass drum body Impulse im => LPF drum_body => Dyno limiter => SinOsc od => Gain drum_output; // // main noise Noise no => LPF n_f => Gain n_g => limiter; NOISE_VOLUMN => no.gain; 3 => n_g.op; n_f.set(NOISE_FREQ, NOISE_Q); // im => Gain g => Gain g_fb => g; g_fb.gain(1.0 - 1.0/NOISE_SUSTAIN); g => n_g; // // stringed-instrument-like sound n_g => DelayA d => LPF d_f => d => Gain d_g => od; d.max(second); d_f.set(HUM_FILTER_FREQ, .5); d_f.gain(HUM_FEEDBACK); d.delay(second/MAIN_FREQUENCY); HUM_VOLUMN => d_g.gain; drum_body.set(MAIN_FREQUENCY, BODY_SUSTAIN); pi => drum_body.gain; limiter.limit(); limiter.thresh(.1); limiter.ratio(1000); limiter.attackTime(30::ms); MAIN_OVERDRIVE => limiter.gain; // DRIVE GAIN od.sync(1); 0.3 => od.gain; // Snare class kjzSnare102 snare; snare.output => Gain snare_gain => drum_output; 0.1 => snare_gain.gain; // Saxophone patch Saxofony sax; // output patch // // guitar spatialization strat.output => dac.left; strat.output => DelayA guitar_delay => dac.right; max_delay => guitar_delay.max; max_delay * Math.sin(theta) => guitar_delay.delay; 1.0 - 0.2 * Math.sin(theta) => guitar_delay.gain; // // sax spatialization sax => dac.right; sax => DelayA sax_delay => dac.left; max_delay => sax_delay.max; max_delay * Math.sin(theta) => sax_delay.delay; 1.0 - 0.2 * Math.sin(theta) => sax_delay.gain; // // drums on center stage drum_output => dac; // master volume control 0.7 => dac.gain; // keyboard Hid hi; HidMsg msg; if (!hi.openKeyboard (kb_device) ) { me.exit (); } spork ~ keyboard (); // create initial song and auto-change generate_logic (); // set random logic expressions generate_frequency (); // set randoom frequency generate_scale (); // set random scale generate_timing (); // set random timing random_guitar (); // set random guitar random_sax (); // set random saxophone random_drums (); // set random drums spork ~ auto_pilot (); print_screen (); // time loop while (true) { // increment binary counter (b+1)%m => b; // calculate guitar frequency 0 => f; for (int i; i < k; i++) { if ((l[0][i] & b) == l[0][i]) { 1 +=> f; } } // calculate bass drum velocity 0 => v; for (int i; i < k/3; i++) { l[1][i]>>(n/4) => mask; if ((mask & b) == mask) { 1.0 / k +=> v; } } // calculate snare drum hit strength 0 => h; for (int i; i < k; i++) { l[2][i]>>(n/4) => mask; if ((mask & b) == mask) { 1.0 / k +=> h; } } // calculate sax frequency 0 => sf; for (int i; i < k; i++) { if ((l[3][i] & b) == l[3][i]) { 1 +=> sf; } } // play instruments if (f > 0) { // strum guitar if (si == 0) { // if no scale is selected strat.strum (fbase + (fbase*f) / (k $ float), 1.0 / (f $ float)); } if (si > 0) { // if a scale is selected (Math.pow(-1.0, Math.rand2(0, 1)) * gsa[f]) $ int +=> gsi; while (gsi < 0) { 1 +=> gsi; } while (gsi > (12*o-1) ) { 1 -=> gsi; } strat.strum (Math.mtof (NoteToMidi (gbn, gsi, scale) ), 1.0); } } if (v > 0) { // hit bass drum v => im.next; } if (h > 0) { // hit snare drum snare.hit (h); } if (sf > 0) { if (si == 0) { // if no scale is selected // change sax frequency 3.0 * fbase + fbase * sf / (k $ float) => sax.freq; } if (si > 0) { // if a scale is selected (Math.pow(-1.0, Math.rand2(0, 1)) * ssa[f]) $ int +=> ssi; while (ssi < 0) { 1 +=> ssi; } while (ssi > (12*o-1) ) { 1 -=> ssi; } Math.mtof (NoteToMidi (sbn, ssi, scale) ) => sax.freq; } 1.0 => sax.noteOn; 0 => sc; } else { if (sc > 3) { 1.0 => sax.noteOff; } else { 1 +=> sc; } } // time delay second / tempo => now; } // guitar based on kijjaz's model class guitar { // define guitar strings num_guitar_strings => int num_strings; Mandolin mandy[num_strings]; // // distortion Gain gd_in => Gain divide => Gain gd_out; gd_in => FullRect fwr => Gain add => divide; Step step => add; 4 => divide.op; // make it a divider 0.025 => step.next; // // hook up guitar and pedals // summ strings into pedal for (int i; i < num_strings; i++) { mandy[i] => gd_in; } gd_out => Gain output; fun void strum (float freq, float pluck) { for (int i; i < num_strings; i++) { freq * (((i $ float) + 1.0) / (num_strings $ float)) => mandy[i].freq; pluck => mandy[i].pluck; } } fun void set_guitar (int numStrings, float strength, float stringDamping, float bodySize, float stringDetune) { numStrings => num_strings; for (int i; i < num_strings; i++) { strength => mandy[i].gain; stringDamping => mandy[i].stringDamping; bodySize => mandy[i].bodySize; stringDetune => mandy[i].stringDetune; } } } // keyboard shred function void keyboard () { while (true) { hi => now; while (hi.recv (msg) ) { //<<>>; if (msg.isButtonDown () ) { if (msg.ascii == 55) { // 7 key random_drums (); print_screen (); } if (msg.ascii == 50) { // 2 key generate_frequency (); print_screen (); } if (msg.ascii == 51) { // 3 key generate_timing (); print_screen (); } if (msg.ascii == 54) { // 6 key generate_scale (); print_screen (); } if (msg.ascii == 49) { // 1 key generate_logic (); print_screen (); } if (msg.ascii == 52) { // 4 key random_guitar (); print_screen (); } if (msg.ascii == 53) { // 5 key random_sax (); print_screen (); } } } } } // with some approvements from 101: snare ringing in the body class kjzSnare102 { // note: connect output to external sources to connect Noise s => Gain s_env => LPF s_f => Gain output; // white noise source Impulse i => Gain g => Gain g_fb => g => LPF g_f => s_env; s_env => DelayA ringing => Gain ringing_fb => ringing => LPF ringing_f => output; 3 => s_env.op; // make s envelope a multiplier s_f.set(3000, 4); // set default drum filter g_fb.gain(1.0 - 1.0/3000); // set default drum decay g_f.set(200, 1); // set default drum attack ringing.max(second); ringing.delay((1.0 / 440) :: second); // set default: base ringing frequency = 440Hz ringing_fb.gain(0.35); // set default ringing feedback ringing_f.set(1500, 1); // set default ringing LPF ringing_f.gain(0.6); // set default ringing vol fun void setFilter(float f, float Q) { s_f.set(f, Q); } fun void setDecay(float decay) { g_fb.gain(1.0 - 1.0 / decay); // decay unit: samples! } fun void setAttack(float attack) { g_f.freq(attack); // attack unit: Hz! } fun void hit(float velocity) { velocity => i.next; } fun void setRingingGain(float g) { g => ringing_f.gain; } fun void setRingingFreq(float f) { (1.0 / f)::second => ringing.delay; } fun void setRingingFeedback(float g) { g => ringing_fb.gain; } fun void setRingingFilter(float f, float Q) { ringing_f.set(f, Q); } } // set random guitar function void random_guitar () { Math.rand2 (25, 35) => gbn; // set guitar base note Math.rand2f (0.8, 1.0) => strength; Math.rand2 (1, num_guitar_strings) => numStrings; Math.rand2f (0.3, 1.0) => stringDamping; Math.rand2f (0.2, 0.4) => bodySize; Math.rand2f (0.0, 0.3) => stringDetune; //0.95 => stringDamping; //0.0 => stringDetune; strat.set_guitar (numStrings, strength, stringDamping, bodySize, stringDetune); Math.rand2f (0.01, 0.3) => gdo; gdo => strat.step.next; Math.rand2f (0.7, 1.0) => gg; 0.3 * gg => strat.output.gain; // set guitar gain } // set random drums function void random_drums () { Math.rand2f (30.0, 120.0) => MAIN_FREQUENCY; d.delay(second/MAIN_FREQUENCY); drum_body.set(MAIN_FREQUENCY, BODY_SUSTAIN); Math.rand2f (40.0, 60.0) => MAIN_OVERDRIVE; MAIN_OVERDRIVE => limiter.gain; // DRIVE GAIN Math.rand2f (0.5, 1.0) => bdg; 2.0 * bdg => od.gain; // set bass drum gain Math.rand2f (0.5, 1.0) => sdg; 1.0 * sdg => snare_gain.gain; // set snare drum gain } // set random saxophone function void random_sax () { Math.rand2 (30, 40) => sbn; // set sax base note Math.rand2f (0.5, 1.0) => sax.stiffness; Math.rand2f (0.2, 0.5) => sax.aperture; Math.rand2f (0.0, 1.0) => sax.noiseGain; Math.rand2f (0.0, 1.0) => sax.blowPosition; Math.rand2f (0.1, 15.0) => sax.vibratoFreq; Math.rand2f (0.0, 1.0) => sax.vibratoGain; Math.rand2f (0.5, 1.0) => sax.pressure; Math.rand2f (0.7, 1.0) => sg; 0.25 * sg => sax.gain; // set sax gain } function void generate_scale () { (si + 1) % 7 => si; if (si == 1) { maps @=> scale; maps.cap () => scl; } if (si == 2) { mips @=> scale; mips.cap () => scl; } if (si == 3) { blues1 @=> scale; blues1.cap () => scl; } if (si == 4) { blues2 @=> scale; blues2.cap () => scl; } if (si == 5) { blues3 @=> scale; blues3.cap () => scl; } if (si == 6) { blues4 @=> scale; blues4.cap () => scl; } } // generate logic expressions function void generate_logic () { // generate logic table Math.rand2f(0.3, 0.7) => power; for (int in; in l[in][i]; while (l[in][i] == 0) { for (int j; j < n; j++) { if (Math.rand2f(0,1) > 0.8/(Math.pow(Math.fabs(j/(n $ float)-i/(k $ float)), power)+1.0)) { Math.pow (2,j) $ int +=> l[in][i]; } } } } } } // set frequency base function void generate_frequency () { // set unstructured frequency 50.0 + Math.rand2f (0.0, 50.0) => fbase; // set number of octaves to scale Math.rand2(1, 2) => o; } // generate timing function void generate_timing () { 2 * Math.rand2(2, 3) => tempo; } // print screen function void print_screen () { // clear screeen for (int i; i<10; i++) { <<<"", "">>>; } <<<"KNoW: Kijjaz No Wave", "">>>; <<<"Let's make noise for peace. - kijjaz", "">>>; // print logic table <<<"", "">>>; <<<"---Logic Table", "">>>; for (int i; i < k; i++) { "" => s; for (int j; j < n; j++) { if ((l[0][i]>>j)&1) { "1"+s => s; } else { "0"+s => s; } " "+s => s; } <<>>; } <<<"power: ", power>>>; // print timing parameters <<<"", "">>>; <<<"---Timing Parameters", "">>>; <<<"fbase: ", fbase $ int>>>; <<<"octaves =", o>>>; if (si == 0) { <<<"scale = free form", "">>>; } if (si == 1) { <<<"scale = major pentatonic", "">>>; } if (si == 2) { <<<"scale = minor pentatonic", "">>>; } if (si == 3) { <<<"scale = blues 1", "">>>; } if (si == 4) { <<<"scale = blues 2", "">>>; } if (si == 5) { <<<"scale = blues 3", "">>>; } if (si == 6) { <<<"scale = blues 4", "">>>; } <<<"tempo: ", tempo $ int>>>; // print guitar parameters <<<"", "">>>; <<<"---Guitar Parameters", "">>>; <<<"base note =", gbn>>>; <<<"strength =", strength>>>; <<<"numStrings =", numStrings>>>; <<<"stringDamping =", stringDamping>>>; <<<"bodySize =", bodySize>>>; <<<"stringDetune =", stringDetune>>>; <<<"distortion =", gdo>>>; <<<"gain =", gg>>>; // print drum parameters <<<"", "">>>; <<<"---Drum Parameters", "">>>; <<<"bass drum main freq =", MAIN_FREQUENCY>>>; <<<"bass drum main overdrive =", MAIN_OVERDRIVE>>>; <<<"bass drum gain =", bdg>>>; <<<"snare drum gain =", sdg>>>; // print sax parameters <<<"", "">>>; <<<"---Sax Parameters", "" >>>; <<<"base note =", sbn>>>; <<<"stiffness:", sax.stiffness() >>>; <<<"aperture:", sax.aperture() >>>; <<<"noiseGain:", sax.noiseGain() >>>; <<<"blowPosition:", sax.blowPosition() >>>; <<<"vibratoFreq:", sax.vibratoFreq() >>>; <<<"vibratoGain:", sax.vibratoGain() >>>; <<<"pressure:", sax.pressure() >>>; <<<"gain =", sg>>>; // print instructions <<<"", "">>>; <<<"1: generate new logic table", "">>>; <<<"2: generate new frequency", "">>>; <<<"3: generate new timing", "">>>; <<<"4: generate new guitar", "">>>; <<<"5: generate new sax", "">>>; <<<"6: generate new note scale", "">>>; <<<"7: generate new drums", "">>>; } fun float NoteToMidi(int key, int note, int scale[]) { note / scl => int octave; note % scl => note; return (key + octave * 12 + scale[note]) $ float; } fun void auto_pilot () { int selection; while (true) { Math.rand2(0, 6) => selection; if (selection == 0) { generate_logic (); // set random logic expressions } if (selection == 1) { generate_frequency (); // set randoom frequency } if (selection == 2) { generate_scale (); // set random scale } if (selection == 3) { generate_timing (); // set random timing } if (selection == 4) { random_guitar (); // set random guitar } if (selection == 5) { random_sax (); // set random saxophone } if (selection == 6) { random_drums (); // set random drums } Math.rand2f(1.0, 440.0)::second/tempo => now; } }