Mercurial > hg > audio-file-loader
view chromagramm/Chromagram.cpp @ 1:ba2a17cf81bf
first working version of audio file loder. Loads bach clip from the apps->audio-file-loader->bin->data->sounds foler. Three classes: SoundFileLoader does the loading and parsing of thefile with libSndFile. audio samples are kept in AudioFile and analysis of features are kept in AudioAnalysis, at this stage just chromagramm and basic energy
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Sun, 04 Sep 2011 22:45:35 +0100 |
parents | bcb0d40158f4 |
children |
line wrap: on
line source
#include "Chromagram.h" #include <iostream> #include <math.h> using namespace std; Chromagram :: Chromagram() { pi = 3.14159265; bsize = 8192; // array init buffer = new float[8192]; // make audio buffer wbuffer = new float[8192]; // to hold windowed audio buffer win = new float[8192]; d_frame = new float[128]; hop = new float[1024]; mag = new float[(bsize/2)+1]; maximumChromaValue = 0; float base = 130.81278265; for (int i = 0;i < 12;i++) { note[i] = base*pow(2,(((float) i)/12)); } harmonics = 2; octaves = 2; search = 2; // p is number of bins either side of target to search for other peaks out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * bsize); // complex array to hold fft p = fftwf_plan_dft_r2c_1d(bsize,wbuffer,out,FFTW_FORWARD*-1); // plan for executing fft of wbuffer chromaready = 0; } //-------------------------------------------------------------------------------------- // destructor Chromagram :: ~Chromagram() { // destroy fft plan fftwf_destroy_plan(p); // deallocate memory win = NULL; delete [] win; buffer = NULL; delete [] buffer; wbuffer = NULL; delete [] wbuffer; } //-------------------------------------------------------------------------------------- // Initialises all framesize dependent variables. Should be called to properly initialise variables and anytime the frame size changes. void Chromagram :: initialise(int framesize,int hsize) { fsize = framesize; hopsize = hsize; d_frame = new float[fsize/4]; hop = new float[hopsize]; calcrate = (hopsize*4)/fsize; count = 0; //fsize = framesize; // set frame size ratio = ((float) 11025) / ((float) 8192); hamming(bsize); // define a hanning window offline } //-------------------------------------------------------------------------------------- // Processes a single frame void Chromagram :: processframe(float frame[]) { int i; int j; int c; chromaready = 0; // default case that chroma isn't ready // downsample frame downsampleframe(frame); if (count < calcrate) { c = count*(fsize/4); j = 0; for (i = c;i < c+(fsize/4);i++) { hop[i] = d_frame[j]; j++; } count = count + 1; } if (count == calcrate) { for (i=0;i < 8192-hopsize;i++) { buffer[i] = buffer[i+hopsize]; } j = 0; for (i=8192-hopsize;i < bsize;i++) { buffer[i] = hop[j]; j++; } chromacalc(buffer); count = 0; } } //-------------------------------------------------------------------------------------- // Processes a single frame void Chromagram :: downsampleframe(float frame[]) { float filt_frame[fsize]; float b0,b1,b2,a1,a2; float x_1,x_2,y_1,y_2; b0 = 0.2929; b1 = 0.5858; b2 = 0.2929; a1 = -0.0000; a2 = 0.1716; x_1 = 0; x_2 = 0; y_1 = 0; y_2 = 0; for (int i=0;i < fsize;i++) { filt_frame[i] = frame[i]*b0 + x_1*b1 + x_2*b2 - y_1*a1 - y_2*a2; x_2 = x_1; x_1 = frame[i]; y_2 = y_1; y_1 = filt_frame[i]; } for (int i=0;i < (fsize/4);i++) { d_frame[i] = filt_frame[i*4]; } } //-------------------------------------------------------------------------------------- // main function to be called with 8192 sample frame at 11025 Hz void Chromagram :: chromacalc(float frame[]) { int i; // apply hanning window to buffer for (i = 0; i < bsize;i++) { wbuffer[i] = frame[i] * win[i]; } getmagspectrum(); generatechromagram(); chromaready = 1; // for (i = 0;i < 12;i++) // { // cout << chroma[i] << " "; // } // // cout << endl; //cout << "root: " << root << " type: " << type << " features: " << features << endl; //cout << root << " " << quality << " " << intervals << endl; } //-------------------------------------------------------------------------------------- // creates a chromagram from the magnitude spectrum of the input signal void Chromagram :: generatechromagram() { int i; float sum; float notesum = 0; float noteval; int index; float maxval = 0; int searchlength; for (i = 0;i < 12;i++) { sum = 0; for (int oct = 1;oct <= octaves;oct++) { noteval = (note[i]/ratio)*((float) oct); notesum = 0; for (int h = 1;h <= harmonics;h++) { index = round(noteval*((float) h)); searchlength = search*h; maxval = 0; for (int n = (index-searchlength);n <= index+searchlength;n++) { if (mag[n] > maxval) { maxval = mag[n]; } } notesum = notesum+(maxval*(1/((float) h))); } sum = sum + notesum; if (oct == 1) { chroma_low[i] = notesum; } } chroma[i] = sum; rawChroma[i] = sum; if (sum > maximumChromaValue) maximumChromaValue = sum; } // normalise chromagram maxval = max(chroma,12); for (i = 0;i < 12;i++) { chroma[i] = chroma[i] / maxval; } } //-------------------------------------------------------------------------------------- // main function to be called with 8192 sample frame at 11025 Hz void Chromagram :: hamming(int N) { int n; // apply hanning window to buffer for (n = 0; n < N;n++) { win[n] = 0.54 - 0.46*cos(2*pi*(((float) n)/((float) N))); } } //-------------------------------------------------------------------------------------- // finds mag spectrum of input void Chromagram :: getmagspectrum() { int i = 0; // execute fft plan, i.e. compute fft of buffer fftwf_execute(p); // compute first (N/2)+1 mag values for (i = 0;i < (bsize/2)+1;i++) { mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2)); mag[i] = sqrt(mag[i]); } } //-------------------------------------------------------------------------------------- // returns max value of an array float Chromagram :: max(float array[],int length) { float max = 0; for (int i=0;i < length;i++) { if (array[i] > max) { max = array[i]; } } return max; } //-------------------------------------------------------------------------------------- // returns index of minimum value of array int Chromagram :: minindex(float array[],int length) { float min = 10000; int minindex = 0; int i; for (i = 0;i < length;i++) { if (array[i] < min) { min = array[i]; minindex = i; } } return minindex; }