//Cross synthesize mic with synthesized robot //FFT for mic input adc => Gain g => FFT fftx => blackhole; //high gain for headset mic //30 => g.gain; //FFT for sound buffer FFT ffty => blackhole; // ifft transforms back into audio IFFT ifft => JCRev j => dac; .00 => j.mix; // set FFT size 2048 => fftx.size => ffty.size => int FFT_SIZE; // desired hop size FFT_SIZE / 8 => int HOP_SIZE; // set window and window size Windowing.hann(512) => fftx.window; Windowing.hann(512) => ffty.window; //source is "robot" saw waves BlitSaw b => ffty; BlitSaw b2 => ffty; BlitSaw b3 => ffty; BlitSaw b4 => ffty; 0 => b.harmonics => b2.harmonics => b3.harmonics => b4.harmonics; .4 => b.gain => b2.gain => b3.gain => b4.gain; //starting frequencies, in MIDI #s Std.mtof(60-12) => b.freq; Std.mtof(61-12) => b2.freq; Std.mtof(66-12) => b3.freq; Std.mtof(69-12) => b4.freq; //change pitches? //spork ~ onset_pitch_changes(); // use this to hold contents of spectral computation complex Z[FFT_SIZE/2]; second/samp => float srate; srate / 2. / FFT_SIZE => float bin_width; // control loop while( true ) { // take fft fftx.upchuck() @=> UAnaBlob X; //spectrum from adc ffty.upchuck() @=> UAnaBlob Y; //spectrum from buffer // bin by bin: for( int i; i < FFT_SIZE/2; i++ ) { (X.cval(i)$polar).mag => float m; if (m > .0001) Math.pow((X.cval(i)$polar).mag, .4) * Y.cval(i) => Z[i]; else 0 * Y.cval(i) => Z[i]; } // take ifft ifft.transform( Z ); // advance time HOP_SIZE::samp => now; } //change pitches randomly with mic "onset" function void onset_pitch_changes() { Std.ftom(b.freq())$int => int last_base; fftx =^ Flux f; while (true) { f.upchuck() @=> UAnaBlob fblob; //change when new onset detected if (fblob.fval(0) >= .6) { //pick new base pitch last_base + (Std.rand2(1, 2)) * (maybe * 2 - 1) => int new_mid => last_base; <<< "New base pitch: ", new_mid>>>; //update frequencies accordingly Std.mtof(new_mid) => b.freq; Std.mtof(new_mid+1) => b2.freq; Std.mtof(new_mid+6+maybe) => b3.freq; Std.mtof(new_mid+9+maybe) => b4.freq; } 4 * HOP_SIZE::samp => now; } }