// Boolean2blobman7.ck // copyright 2007 Les Hall // This software released under the GNU General Protective License // experiments with creating music from base n sequences // for instruments in Boolean logic sequence // and animating them in POV-Ray // control variables 100 => float frequency; // fundamental frequency, all others proportional to this 2 => int n; // starting numeric base of the sequence 32 => int imax; // number of fft lines to draw 0*imax + 256 => int num_notes; // number of notes to record 6 => float notes_per_second; // 8th or 4th notes 4096 => int num_samples; // number of fft samples num_samples / 2 => int num_freq; // number of fft frequencies num_notes => int num_ffts; // number of ffts to take 0.001 => float noise_threshold; // below this is noise 32 => int k; // divisor of spectrum to visualize 1500 => float fmax; // maximum frequency 90 => float theta_max; // maximum blobman theta // gain of each instrument Gain g[6]; 0*0.05 => g[0].gain; // Heavy Metal 0.20 => g[1].gain; // Clarinet 0*0.20 => g[2].gain; // Bowed 0*0.20 => g[3].gain; // Bowed2 0.50 => g[4].gain; // Drums 0*0.20 => g[5].gain; // Guitar // the heavy metal instrument HevyMetl hm => g[0] => dac; 250 => hm.freq; 1.0 => hm.noteOff; float notes_hm[num_notes]; // the clarinet instrument Clarinet cl => g[1] => dac.right; 400 => cl.freq; 1.0 => cl.noteOff; float notes_cl[num_notes]; // the bowed instruments Bowed bw[8]; for (0 => int i; i < 4; i++) { bw[i] => g[2] => dac.left; // bass guitar bw[4+i] => g[3] => dac.right; // lead guitar 1.0 => bw[i].noteOff; 1.0 => bw[4+i].noteOff; } float notes_bw[num_notes]; float notes_bw2[num_notes]; // the drums Impulse imp; BPF bpf[4]; for (0 => int i; i < 4; i++) { imp => bpf[i] => g[4] => dac.left; 100 => bpf[i].Q; } float notes_bpf[num_notes]; // guitar Mandolin mn[4]; mn[0] => SinOsc so => g[5] => JCRev r1 => dac.right; mn[1] => so; mn[2] => so; mn[3] => so; for (0 => int i; i < 4; i++) { 100*(i+1) => mn[i].freq; 1.0 => mn[i].noteOn; } 2 => so.sync; 0.1 => r1.mix; // the FFT patch dac => FFT fft => blackhole; num_samples => fft.size; Windowing.hamming(num_samples) => fft.window; // declare variables int count; // the n-ary count complex samples[num_freq]; // one frequency sample set complex history[num_ffts][num_freq]; // complete history of ffts // time loop while (true) { // calculate the logic threshold (n-1) / 2.0 => float t; // start blowing on the clarinet 1.0 => cl.startBlowing; 1.0 => cl.noteOn; // loop in a 8-bit binary sequence and pluck the strings for (0 => int j15; j15 < n; j15++) { for (0 => int j14; j14 < n; j14++) { for (0 => int j13; j13 < n; j13++) { for (0 => int j12; j12 < n; j12++) { for (0 => int j11; j11 < n; j11++) { for (0 => int j10; j10 < n; j10++) { for (0 => int j9; j9 < n; j9++) { for (0 => int j8; j8 < n; j8++) { for (0 => int j7; j7 < n; j7++) { for (0 => int j6; j6 < n; j6++) { for (0 => int j5; j5 < n; j5++) { for (0 => int j4; j4 < n; j4++) { for (0 => int j3; j3 < n; j3++) { for (0 => int j2; j2 < n; j2++) { for (0 => int j1; j1 < n; j1++) { for (0 => int j0; j0 < n; j0++) { // the heavy metal instrument if ((j15 >= t) && (j14 >= t) || (j13 >= t) && (j12 >= t) || (j11 >= t) && (j10 >= t) || (j9 >= t) && (j8 >= t) || (j7 >= t) && (j6 >= t) || (j5 >= t) && (j4 >= t) || (j3 >= t) && (j2 >= t) || (j1 >= t) && (j0 >= t)) { (4+4*((j11>=t) + (j9>=t) + (j7>=t) + (j5>=t) + (j2>=t))/5.0) * frequency => hm.freq; 1.0 => hm.noteOn; } // the clarinet instrument if ((j15 >= t) && (j14 >= t) || (j13 >= t) && (j12 >= t) || (j11 >= t) && (j10 >= t) || (j9 >= t) && (j8 >= t) || (j7 >= t) && (j6 >= t) || (j5 >= t) && (j4 >= t) || (j3 >= t) && (j2 >= t) || (j1 >= t) && (j0 >= t)) { (4 + 6*((j15>=t) + (j14>=t) + (j13>=t) + (j12>=t) + (j11>=t) + (j10>=t) + (j9>=t) + (j8>=t) + (j7>=t) + (j6>=t) + (j5>=t) + (j4>=t) + (j3>=t) + (j2>=t) + (j1>=t) + (j0>=t))/16.0) * frequency => cl.freq; } // the first bowed instrument if ((j9 <= t) && (j8 <= t) || (j7 <= t) && (j6 <= t) || (j5 <= t) && (j4 <= t) || (j3 <= t) && (j2 <= t)) { (2 + ((j5>=t) && (j4>=t) || (j3>=t) && (j2>=t))/1.0) * frequency => bw[0].freq; for (1 => int i; i < 4; i++) { bw[0].freq() - 0.50*frequency*i => bw[i].freq; } for (0 => int i; i < 4; i++) { 1.0 => bw[i].noteOn; } } // the second bowed instrument if (((j7 >= 0) && (j5 >= 0) || (j6 >= t) && (j4 >= t)) && (j2 >= t) || (j1 >= t) && (j0 >= t)) { (2 + 4*(4*(j4<=t) + 2*(j2<=t) + 1*(j1<=t))/7.0) * frequency => bw[4].freq; for (5 => int i; i < 8; i++) { bw[4].freq() - 0.50*frequency*(i-4) => bw[i].freq; } for (4 => int i; i < 8; i++) { 1.0 => bw[i].noteOn; } } // the drums if ( (j0 >= t) ) { (2 + 2*(1*(j4 >= t) + 2*(j3 >= t) + 4*(j2 >= t) + 8*(j1 >= t))/15.0) * frequency => bpf[0].freq; for (1 => int i; i < 4; i++) { bpf[0].freq() - 0.50*frequency*i => bpf[i].freq; } 1000 => imp.next; } // the guitar if ((j8 <= t) && (j7 <= t) || (j6 <= t) && (j5 <= t) || (j4 <= t) && (j3 <= t) || (j2 <= t) && (j1 <= t)) { (2 + ((j5>=t) + 2*(j4>=t) + 2*(j3>=t) + (j2>=t))/6.0) * frequency => so.freq; for (0 => int i; i < 4; i++) { //1.0 => mn[i].noteOn; 1.0 => mn[i].pluck; } } 1::second / notes_per_second => now; // advance time (j15*Math.pow(n,15) + j14*Math.pow(n,14) + j13*Math.pow(n,13) + j12*Math.pow(n,12) + j11*Math.pow(n,11) + j10*Math.pow(n,10) + j9*Math.pow(n,9) + j8*Math.pow(n,8) + j7*Math.pow(n,7) + j6*Math.pow(n,6) + j5*Math.pow(n,5) + j4*Math.pow(n,4) + j3*Math.pow(n,3) + j2*Math.pow(n,2) + j1*Math.pow(n,1) + j0*Math.pow(n,0)) $ int => count; hm.freq() => notes_hm[count]; cl.freq() => notes_cl[count]; bw[0].freq() => notes_bw[count]; bw[4].freq() => notes_bw2[count]; bpf[0].freq() => notes_bpf[count]; if (count >= num_notes - 1) break; // take fft and remember it fft.upchuck().cvals() @=> samples; for (0 => int i; i < num_freq; i++) { samples[i] => history[count][i]; } } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; } if (count >= num_notes - 1) break; // stop blowing on the clarinet 1.0 => cl.stopBlowing; // increment the base number n++; // advance time between counting sequences 4::second => now; } // find average values of frequencies 0 => float avg_cl; 0 => float avg_hm; 0 => float avg_bw; 0 => float avg_bw2; 0 => float avg_bpf; 0 => float fmax_cl; 0 => float fmax_hm; 0 => float fmax_bw; 0 => float fmax_bw2; 0 => float fmax_bpf; 10*fmax => float fmin_cl; 10*fmax => float fmin_hm; 10*fmax => float fmin_bw; 10*fmax => float fmin_bw2; 10*fmax => float fmin_bpf; for (0 => int i; i < num_notes; i++) { notes_cl[i]/num_notes +=> avg_cl; notes_hm[i]/num_notes +=> avg_hm; notes_bw[i]/num_notes +=> avg_bw; notes_bw2[i]/num_notes +=> avg_bw2; notes_bpf[i]/num_notes +=> avg_bpf; if (notes_cl[i] > fmax_cl) { notes_cl[i] => fmax_cl; } if (notes_hm[i] > fmax_hm) { notes_hm[i] => fmax_hm; } if (notes_bw[i] > fmax_bw) { notes_bw[i] => fmax_bw; } if (notes_bw2[i] > fmax_bw2) { notes_bw2[i] => fmax_bw2; } if (notes_bpf[i] > fmax_bpf) { notes_bpf[i] => fmax_bpf; } if (notes_cl[i] < fmin_cl) { notes_cl[i] => fmin_cl; } if (notes_hm[i] < fmin_hm) { notes_hm[i] => fmin_hm; } if (notes_bw[i] < fmin_bw) { notes_bw[i] => fmin_bw; } if (notes_bw2[i] < fmin_bw2) { notes_bw2[i] => fmin_bw2; } if (notes_bpf[i] < fmin_bpf) { notes_bpf[i] => fmin_bpf; } } // print out the POV-Ray code // output header text // these are the include files <<<"#include \"colors.inc\"", " ">>>; <<<"#include \"textures.inc\"", " ">>>; <<<"#include \"finish.inc\"", " ">>>; // these are the settings <<<"global_settings", "{">>>; <<<" assumed_gamma", "1">>>; <<<" max_trace_level", "256">>>; <<<"}", " ">>>; // this is the camera <<<"camera { location <0, 0, -15000> look_at <0, 0, 0> rotate <0, -360*clock, 0>", "}">>>; // this is the light source <<<"light_source { <0, 10000, -10000>, rgb <1, 1, 1,>", " }">>>; // this is the sky sphere <<<"sky_sphere { pigment { rgb<1, 1, 1>", "} }">>>; <<<"#declare Heavy_Metal = array[", num_notes, "]{">>>; for (0 => int i; i< num_notes; i++) { <<>>; } <<<"}", " ">>>; <<<"#declare Clarinet = array[", num_notes, "]{">>>; for (0 => int i; i< num_notes; i++) { <<>>; } <<<"}", " ">>>; <<<"#declare Bowed = array[", num_notes, "]{">>>; for (0 => int i; i< num_notes; i++) { <<>>; } <<<"}", " ">>>; // save magnitude of fft history array to POV-Ray <<<"#declare fft_hist = array[", count+1, "][", num_freq/k, "]{">>>; for (0 => int t; t <= count; t++) { <<<"{", " ">>>; for (0 => int f; f < num_freq/k; f++) { if ((history[t][f] $ polar).mag < noise_threshold) { <<>>; } else { <<<(history[t][f] $ polar).mag, ",">>>; } } <<<"},", " ">>>; } <<<"}", " ">>>; // draw the three spheres //<<<"sphere {<-5000,4000,0>, Heavy_Metal[clock *", num_notes, "] pigment {Red}}">>>; //<<<"sphere {<0,4000,0>, Clarinet[clock *", num_notes, "] pigment {Green}}">>>; //<<<"sphere {<5000,4000,0>, Bowed[clock *", num_notes, "] pigment {Blue}}">>>; // draw FFT lines for (0 => int i; i < imax; i++) { for (0 => int f; f < num_freq/k-1; f++) { <<<"cylinder {<", -5000+10000*f/(num_freq $float)*k, ", -4000+100000*fft_hist[clock *", count+1-imax, "+", i, "][", f, "],", (10000/imax)*(i-imax/2.0), ">">>>; <<<" <", -5000+10000*(f+1)/(num_freq $float)*k, ", -4000+100000*fft_hist[clock *", count+1-imax, "+", i, "][", f+1, "],", (10000/imax)*(i-imax/2.0), ">, 32">>>; <<<" pigment { rgb<", 1-f/(num_freq/(k $ float)-1), ",", f/(num_freq/(k $ float)-1), ", 0>}", " ">>>; <<<"}", " ">>>; } } // introducing: Blob-Man! and Blob-Woman! <<<"#include \"bmpeople.inc\"", " ">>>; // declare arrays <<<"#declare angles1 = array[", num_notes, "]{">>>; for (0 => int i; i < num_notes; i++) { <<<"-1*<", theta_max*(notes_bpf[i]-fmin_bpf)/(fmax_bpf-fmin_bpf)-theta_max/2, ",", theta_max*(notes_bpf[i]-fmin_bpf)/(fmax_bpf-fmin_bpf)-theta_max/2, ",", theta_max*(notes_bpf[i]-fmin_bpf)/(fmax_bpf-fmin_bpf)-theta_max/2, ">,">>>; } <<<"}", " ">>>; <<<"#declare angles2 = array[", num_notes, "]{">>>; for (0 => int i; i < num_notes; i++) { <<<"-1*<", theta_max*(notes_cl[i]-fmin_cl)/(fmax_cl-fmin_cl)-theta_max/2, ",", theta_max*(notes_cl[i]-fmin_cl)/(fmax_cl-fmin_cl)-theta_max/2, ",", theta_max*(notes_cl[i]-fmin_cl)/(fmax_cl-fmin_cl)-theta_max/2, ">,">>>; } <<<"}", " ">>>; // animate blobman <<<"#declare BM_Head_Rot = <-0.5,0,0> * angles1[clock *", num_notes, "]+<", -theta_max/4, ", 0, 0>;">>>; <<<"#declare BM_RA_S2E = <0.5,0,-0.5> * angles1[clock *", num_notes, "]+<", theta_max/4, ", 0,", -theta_max/4, ">;">>>; <<<"#declare BM_LA_S2E = <0.5,0,0.5> * angles1[clock *", num_notes, "]+<", theta_max/4, ", 0,", theta_max/4, ">;">>>; <<<"#declare BM_RA_E2W = <1,0,0> * angles1[clock *", num_notes, "]+<", theta_max/2, ", 0, 0>;">>>; <<<"#declare BM_LA_E2W = <1,0,0> * angles1[clock *", num_notes, "]+<", theta_max/2, ", 0, 0>;">>>; <<<"#declare BM_RL_H2K = <0.8,0,-0.4> * angles1[clock *", num_notes, "]+<", 0.4*theta_max, ", 0,", -0.2*theta_max, ">;">>>; <<<"#declare BM_LL_H2K = <0.8,0,0.4> * angles1[clock *", num_notes, "]+<", 0.4*theta_max, ", 0,", 0.2*theta_max, ">;">>>; <<<"#declare BM_RL_K2A = <-0.8,0,0> * angles1[clock *", num_notes, "]+<", -0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_LL_K2A = <-0.8,0,0> * angles1[clock *", num_notes, "]+<", -0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_RF_Rot = <0.8,0,0> * angles1[clock *", num_notes, "]+<", 0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_LF_Rot = <0.8,0,0> * angles1[clock *", num_notes, "]+<", 0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_Torso_Rot= <-0.5,0,0> * angles1[clock *", num_notes, "]+<", -theta_max/4, ", 0, 0>;">>>; <<<"Blob_Man(Male,10000)", " ">>>; <<<"object {BlobMan", " ">>>; <<<" transform BMO_Foot_R", " ">>>; <<<" translate <-2500, -4000, 0>", " ">>>; <<<"}", " ">>>; // animate blobwoman <<<"#declare BM_Head_Rot = <-0.5,0,0> * angles2[clock *", num_notes, "]+<", -theta_max/4, ", 0, 0>;">>>; <<<"#declare BM_RA_S2E = <0.5,0,-0.5> * angles2[clock *", num_notes, "]+<", theta_max/4, ", 0,", -theta_max/4, ">;">>>; <<<"#declare BM_LA_S2E = <0.5,0,0.5> * angles2[clock *", num_notes, "]+<", theta_max/4, ", 0,", theta_max/4, ">;">>>; <<<"#declare BM_RA_E2W = <1,0,0> * angles2[clock *", num_notes, "]+<", theta_max/2, ", 0, 0>;">>>; <<<"#declare BM_LA_E2W = <1,0,0> * angles2[clock *", num_notes, "]+<", theta_max/2, ", 0, 0>;">>>; <<<"#declare BM_RL_H2K = <0.8,0,-0.4> * angles2[clock *", num_notes, "]+<", 0.4*theta_max, ", 0,", -0.2*theta_max, ">;">>>; <<<"#declare BM_LL_H2K = <0.8,0,0.4> * angles2[clock *", num_notes, "]+<", 0.4*theta_max, ", 0,", 0.2*theta_max, ">;">>>; <<<"#declare BM_RL_K2A = <-0.8,0,0> * angles2[clock *", num_notes, "]+<", -0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_LL_K2A = <-0.8,0,0> * angles2[clock *", num_notes, "]+<", -0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_RF_Rot = <0.8,0,0> * angles2[clock *", num_notes, "]+<", 0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_LF_Rot = <0.8,0,0> * angles2[clock *", num_notes, "]+<", 0.4*theta_max, ", 0, 0>;">>>; <<<"#declare BM_Torso_Rot= <-0.5,0,0> * angles2[clock *", num_notes, "]+<", -theta_max/4, ", 0, 0>;">>>; <<<"Blob_Man(Female,10000)", " ">>>; <<<"object {BlobMan", " ">>>; <<<" transform BMO_Foot_R", " ">>>; <<<" translate <2500, -4000, 0>", " ">>>; <<<"}", " ">>>;