Mercurial > hg > vamp-onsetsds-plugin
view onsetsds/onsetsdshelpers.c @ 0:635e8745ccc9
* First commit of plugin using Dan Stowell's OnsetsDS library code
author | cannam |
---|---|
date | Thu, 19 Jun 2008 12:30:15 +0000 |
parents | |
children |
line wrap: on
line source
/* OnsetsDS - real time musical onset detection library. Copyright (c) 2007 Dan Stowell. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "onsetsdshelpers.h" #include <stdlib.h> #include <sndfile.h> #include <fftw3.h> void onsetsds_init_audiodata(OnsetsDSAudioBuf *odsbuf, OnsetsDS *ods, /* size_t framesize, */ size_t hopsize){ odsbuf->ods = ods; odsbuf->buflen = ods->fftsize; odsbuf->hopsize = hopsize; size_t framesizebytes = ods->fftsize * sizeof(float); // malloc odsbuf.data, odsbuf.window, odsbuf.windoweddata odsbuf->data = (float*) malloc(framesizebytes); odsbuf->window = (float*) malloc(framesizebytes); odsbuf->windoweddata = (float*) fftwf_malloc(framesizebytes); odsbuf->fftbuf = (float*) fftwf_malloc(framesizebytes); // Create the FFTW plan odsbuf->fftplan = fftwf_plan_r2r_1d(ods->fftsize, odsbuf->windoweddata, odsbuf->fftbuf, FFTW_R2HC, FFTW_ESTIMATE); // zero odsbuf.data memset(odsbuf->data, 0, framesizebytes); // Create the FFT window double pi = acos(-1.); double winc = pi / ods->fftsize; int i; for (i=0; i<ods->fftsize; ++i) { double w = i * winc; odsbuf->window[i] = sin(w); } odsbuf->sampsElapsed = 0L; odsbuf->writepos = 0; } void onsetsds_destroy_audiodata(OnsetsDSAudioBuf *odsbuf){ // take down the FFTW stuff fftwf_destroy_plan(odsbuf->fftplan); // free mem free(odsbuf->data); free(odsbuf->window); fftwf_free(odsbuf->windoweddata); fftwf_free(odsbuf->fftbuf); } void onsetsds_process_audiodata(OnsetsDSAudioBuf* odsbuf, float* data, size_t datalen, ODSDataCallback callback){ if(datalen==0){ printf("onsetsds_process_audiodata GRRRRRR: no audio data sent (datalen==0)\n"); return; }else{ } size_t datareadpos = 0; size_t dataleft = datalen; size_t numtocopy; int i; while(dataleft > 0){ // Read the smaller of how-much-available and how-much-to-fill-the-buffer numtocopy = ods_min(dataleft, odsbuf->buflen - odsbuf->writepos); // printf("onsetsds_process_audiodata: datalen = %i, dataleft = %i, buflen = %i, about to copy %i values to position %i\n", // datalen, dataleft, odsbuf->buflen, numtocopy, odsbuf->writepos); memcpy(&odsbuf->data[odsbuf->writepos], &data[datareadpos], numtocopy * sizeof(float)); odsbuf->writepos += numtocopy; // If the buffer is full, do all the FFT and stuff if(odsbuf->writepos >= odsbuf->buflen){ // Copy the data into the buffer where windowing and FFT takes place memcpy(odsbuf->windoweddata, odsbuf->data, odsbuf->buflen * sizeof(float)); // Shunt the audio data (and the writepos) down to make room for the next lot memcpy(odsbuf->data, &odsbuf->data[odsbuf->hopsize], (odsbuf->buflen - odsbuf->hopsize) * sizeof(float)); //printf("onsetsds_process_audiodata: moving writepos from %i to %i(==hopsize)\n", odsbuf->writepos, odsbuf->hopsize); odsbuf->writepos = odsbuf->hopsize; // Windowing for(i=0; i<odsbuf->buflen; i++){ odsbuf->windoweddata[i] *= odsbuf->window[i]; } // FFT fftwf_execute(odsbuf->fftplan); // Onset detection if(onsetsds_process(odsbuf->ods, odsbuf->fftbuf)){ // Call the callback! callback(odsbuf, datareadpos); } } // End buffer-is-filled datareadpos += numtocopy; dataleft -= numtocopy; } // End of still-some-data-to-push } void onsetsds_process_audiofile_CALLBACK(OnsetsDSAudioBuf* odsbuf, size_t onsetsamplepos); void onsetsds_process_audiofile_CALLBACK(OnsetsDSAudioBuf* odsbuf, size_t onsetsamplepos){ // Convert the sample pos into a seconds position through the whole file double secs = (odsbuf->sampsElapsed + onsetsamplepos) / odsbuf->samplerate; // Now call the file-level callback (odsbuf->filecallback)(odsbuf->ods, secs); } int onsetsds_process_audiofile(OnsetsDSAudioBuf* odsbuf, const char *infilename, ODSFileCallback callback){ SNDFILE *insndfile ; SF_INFO sfinfo ; memset (&sfinfo, 0, sizeof (sfinfo)); // Attempt to get the input file if ((insndfile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL){ printf ("onsetsds_process_audiofile ERROR: Not able to open input file %s.\n", infilename) ; fflush (stdout) ; return 100; } if(sfinfo.channels != 1){ printf("onsetsds_process_audiofile ERROR: Only mono audio files can be processed. Num channels = %i. Exiting.\n", sfinfo.channels); sf_close(insndfile); return 200; }else{ printf("onsetsds_process_audiofile: mono audio file, sample rate %i Hz.\n", sfinfo.samplerate); } odsbuf->sampsElapsed = 0L; odsbuf->samplerate = (double) sfinfo.samplerate; odsbuf->filecallback = callback; // Create a buffer for reading the raw data into float* data = malloc(odsbuf->buflen * sizeof(float)); sf_count_t numread; //printf("onsetsds_process_audiofile: Processing audio data\n", numread); while((numread = sf_read_float(insndfile, data, odsbuf->buflen)) > 0){ //printf("Read %i audio frames (requested %i)\n", numread, odsbuf->buflen); //printf("Calling onsetsds_process_audiodata\n"); onsetsds_process_audiodata(odsbuf, data, numread, onsetsds_process_audiofile_CALLBACK); //printf("Called onsetsds_process_audiodata\n"); odsbuf->sampsElapsed += numread; } sf_close(insndfile); free(data); // Indicate success return 0; }