// This uses the FFT to pick out the N // highest peaks in the spectrum. // (N=10 here, but you can define it) // It drives a bank of SinOscs in a // really dumb way (so lots of clicks, and // "the bubbling and burbling of the bathtub bells"), // but it can print them out in the console when you // hit the space bar, so you can use them later. adc => FFT fft => blackhole; // draw samples through FFT Windowing.hamming(2048) => fft.window; 4096 => fft.size; 2048 => int halfsize; UAnaBlob blob; float peak,power; int peakloc; 10 => int N; float peaks[N]; float amps[N]; SinOsc s[N]; for (0 => int i;i < N; i++) { s[i] => dac; 0.0 => s[i].gain; } 0 => int spaceBar; spork ~ watchKeys(); while (1) { 1024 :: samp => now; // Hop size fft.upchuck() @=> blob; // Compute and blob.fvals() @=> float mag_spec[]; // store spectrum 0.0 => peak; 0.0 => power; 0 => peakloc; for (0 => int i; i < halfsize; 1 +=> i) { mag_spec[i]*mag_spec[i] +=> power; // Accumulate power if (mag_spec[i] > peak) { // Find peak mag_spec[i] => peak; i => peakloc; } } 22050.0 * peakloc / halfsize => peaks[0] => s[0].freq; // Set freq mag_spec[peakloc] => amps[0] => s[0].gain; for (1 => int j; j < N; j ++) { peakloc - 8 => int leftloc; if (leftloc < 0) 0 => leftloc; peakloc + 8 => int rightloc; if (rightloc > halfsize) halfsize => rightloc; for (leftloc => int k; k <= rightloc; k++) 0.0 => mag_spec[k]; 0.0 => peak; for (0 => int i; i < halfsize; 1 +=> i) { if (mag_spec[i] > peak) { // Find peak mag_spec[i] => peak; i => peakloc; } } 22050.0 * peakloc / halfsize => peaks[j] => s[j].freq; // Set freq mag_spec[peakloc] => amps[j] => s[j].gain; } if (spaceBar) { <<< "Here is a list of the ", N, " highest peaks:" >>>; for (0 => int j; j < N; j ++) <<< "Freq: ", peaks[j], " at Amplitude: ", amps[j] >>>; 0 => spaceBar; } } fun void watchKeys() { Hid kb; HidMsg msg; kb.openKeyboard(0); while(true) { kb => now; while(kb.recv(msg)) { // 32 == ASCII space if(msg.type == Hid.BUTTON_DOWN && msg.ascii == 32 ) 1 => spaceBar; } } }