// Vocoder, imposes adc spectrum on wavefile // By PRC, March 2009 // Our basic FFT, IFFT chain, // with an additional fft // just hold on, you'll see soon. SndBuf instr => FFT fftInstr =^ IFFT ifftInstr => dac; // we're gonna process this adc => FFT fftVoice => blackhole; // we're gonna analyze this "shuffle.wav" => instr.read; // our "source" file 1 => instr.loop; 128 => int FFT_SIZE; // This will give us 64 bands FFT_SIZE => fftInstr.size; // All ffts FFT_SIZE => ifftInstr.size; // are the FFT_SIZE => fftVoice.size; // same size Windowing.hamming(FFT_SIZE/4) => fftInstr.window; // Zero pad some (window=32) Windowing.hamming(FFT_SIZE/4) => fftVoice.window; // 'cause we're filtering UAnaBlob blobVoice; // Make blob so we can get to data UAnaBlob blobInstr; // Make blob so we can get to data float magNorm; float temp; while (1) { 16 :: samp => now; // Hop size = window/2 fftInstr.upchuck() @=> blobInstr; // Get data fftVoice.upchuck() @=> blobVoice; // Get data blobInstr.fvals() @=> float instMag[]; blobVoice.fvals() @=> float voiceMag[]; for (0 => int i; i < FFT_SIZE/2 ; i++) { if (instMag[i] < 0.001) 0.001 => instMag[i]; // beware divide by zero energy!! voiceMag[i] / instMag[i] => magNorm; // per bin gain factor magNorm *=> blobInstr.cvals()[i]; // impose new spectrum } ifftInstr.upchuck(); // Inverse FFT and output to dac }