FFT

The Fast Fourrier Transform analysis.

Your browser does not support the canvas element.
	var audio = new maximJs.maxiAudio();
	audio.init();

	var fft = new maximJs.maxiFFT();
	var mfcc = new maximJs.maxiMFCC();
	var oct = new maximJs.maxiFFTOctaveAnalyzer();

	var nAverages = 12;

	// for storing fft values
	/* 
	required as passing a vector from one class 
	to another isn't currently working
	*/
	var magnitudes = new Module.VectorFloat();
	var magnitudesDB = new Module.VectorFloat();

	// will store mfcc output
	var mfccs = new Module.VectorDouble(); 

	var osc = new maximJs.maxiOsc();

	// if you want to play a sample...
	// var samplePlayer = new maximJs.maxiSample();
	// audio.loadSample("./audio/beat2.wav", samplePlayer);


	var fftSize = 1024;
	var sampleRate = 44100;

	var magMult = 6;

	var fftDraw = {
	barsBottom: 600,
	barsLeft: 50,
	barsSize:1,
	magMult: 6
};

var mfccDraw = {
barsBottom: 350,
barsLeft: 350,
barsSize:10,
magMult: 24
};

var octDraw = {
barsBottom: 150,
barsLeft: 350,
barsSize:10,
magMult: 0.5
};

var amtAvgs = 15;
var pitchHist = [];

window.onload = setup;
function setup(){
fft.setup(fftSize, 512, 256);
mfcc.setup(512, 42, 13, 20, 20000, sampleRate);
oct.setup(sampleRate, fftSize/2, nAverages);

for(var i = 0; i < 13; ++i){
mfccs.push_back(0);
}

for(var i = 0; i < fftSize/2; ++i){
magnitudes.push_back(0);
}

// This gets the window in the browser
var canvas=document.getElementById("myCanvas");

// This creates a 2d drawing context in it.
context=canvas.getContext("2d");

//finally, we return setInterval, which wants a function to call,
//and a period in milliseconds to wait between calling it.  
return setInterval(draw, 40);
}

audio.play = function(){
// create wave for fft
var wave = osc.square(220);

// or use a sample
// var wave = samplePlayer.isReady() ? samplePlayer.play() : 0.0;

// process wave
if(fft.process(wave)){
fft.magsToDB();

// 	// sorry, this is not nice
Module.vectorTools.clearVectorFloat(magnitudes);
Module.vectorTools.clearVectorFloat(magnitudesDB);

for(var i = 0; i < fftSize/2; ++i){
magnitudes.push_back(fft.getMagnitude(i));
magnitudesDB.push_back(fft.getMagnitudeDB(i));
}

// 	// pass magnitudes to mfcc and store in mfccs vector
mfcc.mfcc(magnitudes, mfccs);
oct.calculate(magnitudesDB);
}

this.output = wave; 

}


//The stuff inside the script tag is very similar to processing code.
function draw() {
//This is basically the same as any other 2D processing draw routine.
//clear the screen
context.clearRect(0,0,700,700);

// fft
context.fillStyle="#FF0000";
context.font = "30px Arial";
context.fillText("FFT",70,200);

for(var i=0; i < fftSize / 2; i++) {
context.beginPath();
context.rect(
fftDraw.barsLeft + i,
fftDraw.barsBottom,
fftDraw.barsSize,
-(fft.getMagnitude(i) * fftDraw.magMult)); 
context.fill();
context.closePath();
}

// mfcc
context.fillStyle="rgba(0, 220, 0, 0.5)"
context.font = "30px Arial";
context.fillText("MFCC",350,250);
for(var i=0; i < 13; i++) {
context.beginPath();

context.rect(
mfccDraw.barsLeft + i*mfccDraw.barsSize,
mfccDraw.barsBottom,
mfccDraw.barsSize,
(mfccs.get(i) * mfccDraw.magMult)); 
context.fill();
context.closePath();
}

// octave analyser
var j = 0;
for(var i=0; i < amtAvgs; ++i) {
pitchHist[i] = 0;
}

for (var i = 0; i < oct.nAverages; ++i) {
pitchHist[j] += oct.getAverage(i);
j++;
j = j % amtAvgs;
}

context.fillStyle="rgba(0, 0, 255, 0.5)"
context.font = "30px Arial";
context.fillText("OCT",350,50);
for(var i=0; i < amtAvgs; i++) {
context.beginPath();
context.rect(
octDraw.barsLeft + i*(octDraw.barsSize*1.5),
octDraw.barsBottom,
octDraw.barsSize,
-(pitchHist[i] * octDraw.magMult)); 
context.fill();
context.closePath();
}
}