/** * PlaySpectrum * * Run an FFT on soundfile playback, and plot the spectrum in dB. * Based on http://processing.org/learning/libraries/forwardfft.html by ddf. * * 2010-02-03 Dan Ellis dpwe@ee.columbia.edu */ import ddf.minim.analysis.*; import ddf.minim.*; Minim minim; AudioPlayer sound; FFT fft; float gain = 40; // in dB float dB_scale = 2.0; // pixels per dB int buffer_size = 2048; // also sets FFT size (frequency resolution) int spectrum_height = 200; // determines range of dB shown int legend_height = 20; int spectrum_width = 512; // determines how much of spectrum we see int legend_width = 50; void setup() { size(legend_width+spectrum_width, spectrum_height+legend_height, P2D); textMode(SCREEN); textFont(createFont("SanSerif", 12)); minim = new Minim(this); sound = minim.loadFile("sound.mp3",buffer_size); // make it repeat sound.loop(); // create an FFT object that has a time-domain buffer // the same size as line-in's sample buffer fft = new FFT(sound.bufferSize(), sound.sampleRate()); // Tapered window important for log-domain display fft.window(FFT.HAMMING); } // Convert a spectrum value into a y pixel position int spectrum_y(float bandval) { float val; if (bandval > 0) { val = dB_scale*(20*((float)Math.log10(bandval)) + gain); } else { val = -200; // avoid log(0) } int y = spectrum_height - Math.round(val); if (y > spectrum_height) { y = spectrum_height; } return y; } void draw() { // clear window background(0); // perform a forward FFT on the samples in input buffer fft.forward(sound.mix); // now draw current spectrum in brighter blue stroke(64,192,255); noFill(); int y_prev = spectrum_y(fft.getBand(0)); for(int i = 1; i < spectrum_width; i++) { // draw the line for frequency band i using dB scale int y = spectrum_y(fft.getBand(i)); line(legend_width+i-1, y_prev, legend_width+i, y); y_prev = y; } // add legend // frequency axis fill(255); stroke(255); int y = spectrum_height; line(legend_width,y,legend_width+spectrum_width,y); // horizontal line // x,y address of text is immediately to the left of the middle of the letters textAlign(CENTER,TOP); for (float freq = 0.0; freq < sound.sampleRate()/2; freq += 2000.0) { int x = legend_width+fft.freqToIndex(freq); // which bin holds this frequency line(x,y,x,y+4); // tick mark text(Math.round(freq/1000) +"kHz", x, y+5); // add text label } // level axis int x = legend_width; line(x,0,x,spectrum_height); // vertical line textAlign(RIGHT,CENTER); for (float level = -100.0; level < 100.0; level += 20.0) { y = spectrum_height - (int)(dB_scale * (level+gain)); line(x,y,x-3,y); text((int)level+" dB",x-5,y); } } void keyReleased() { // +/- used to adjust gain on the fly if (key == '+' || key == '=') { gain = gain + 5.0; } else if (key == '-' || key == '_') { gain = gain - 5.0; } } void stop() { // always close Minim audio classes when you finish with them sound.close(); minim.stop(); super.stop(); }