Mercurial > hg > precise-onset-detection
diff ofxPreciseOnsetDetectorOffline/PreciseOnsetDetectorOffline.cpp @ 2:7ec1ed0b2eb0
Added offline precise onset detection, outputting precise locations in seconds to text file
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Mon, 30 Dec 2013 14:08:42 +0000 |
parents | |
children | 50f62c48b421 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ofxPreciseOnsetDetectorOffline/PreciseOnsetDetectorOffline.cpp Mon Dec 30 14:08:42 2013 +0000 @@ -0,0 +1,182 @@ +/* + * PreciseOnsetDetectorOffline.cpp + * ofxPreciseOnsetDetectionOffline + * + * Created by Andrew Robertson on 25/12/2013. + * Copyright 2013 QMUL. All rights reserved. + * + */ + + +//add a retrigger threshold + +#include "PreciseOnsetDetectorOffline.h" + +PreciseOnsetDetectorOffline::PreciseOnsetDetectorOffline(){ + frameSize = 1024; + hopSize = 512; + preciseLocator.setup(frameSize); + writeOutput = true;//write output to txt when loading file - stored at sample location as file +} + +PreciseOnsetDetectorOffline::~PreciseOnsetDetectorOffline(){ + +} + + +void PreciseOnsetDetectorOffline::load(std::string filename){ + + //name for output file is same dir and filename as aif/wav but with _preciseOnsets.txt added + //eg 'song.wav' is 'song.wav_preciseOnsets.txt' + + processAudioForBeatTimes(filename); +} + + + +int PreciseOnsetDetectorOffline::processAudioForBeatTimes(std::string audiofile){ + //originally from BeatAnnotationViewer project + + BeatWriter writer; + dfValues.clear(); + onsetLocations.clear(); + onsetPositionFrames.clear(); + + // static double frame[FRAMESIZE]; // to hold a single frame + double buffer[frameSize]; + double dfval; + + for (int i = 0;i < frameSize;i++) + { + buffer[i] = 0; + } + + //detfun = new df(1,(FRAMESIZE*2),0); + + // initialises with hopsize = 512, framesize = 1024, complex spectral difference DF and hanning window + detectionFunction = new OnsetDetectionFunction(); + + SNDFILE *infile, *outfile ; // define input and output sound files + + SF_INFO sfinfo ; // struct to hold info about sound file + int readcount ; // counts number of samples read from sound file + const char *infilename = audiofile.c_str(); + //"/Users/andrew/Music/Station To Station 2/3-03 Panic In Detroit (Live Nassau Coliseum '76).wav";//"ledzep.wav" ; // input file name + // const char *outfilename = "output.wav" ; // output file name + + + // Open Input File + if (! (infile = sf_open (infilename, SFM_READ, &sfinfo))) + { // Open failed + printf ("Not able to open input file %s.\n", infilename) ; + // Print the error message from libsndfile. + puts (sf_strerror (NULL)) ; + return 1; + } ; + + printf("opened '%s'\n", audiofile.c_str()); + loadedFilename = audiofile; + //STEREO OKAY + + //HERE IS THE CLASSIC LOADING FILE CODE + //DEALS WITH MORE THAN MONO + int channels = sfinfo.channels; + samples = sfinfo.frames; + printf("Number of channels %i, samples %i\n", channels, samples); + + //for writing output + std::string outputFilename = audiofile+"_preciseOnsets.txt"; + + if (writeOutput) + writer.openFile(outputFilename); + + + int blocksize = hopSize;//FRAMESIZE; + float buf [channels * blocksize] ; + float frame[blocksize]; + + int k, m; + readcount = 1; + int counter = 0; + + //DoubleVector d; + while ((readcount = sf_readf_float (infile, buf, blocksize)) > 0){ + for (k = 0 ; k < readcount ; k++){ + //d.clear(); + frame[k] = 0; + + for (m = 0 ; m < channels ; m++){ + frame[k] += buf[k*channels + 0];//sum the channels together + //d.push_back(buf [k * channels + m]); + } + + frame[k] /= channels;//average of the channels + } + + //add to our buffer for pocessing + for (int i = 0; i< frameSize-hopSize;i++) + { + buffer[i] = buffer[i+hopSize]; + buffer[i+hopSize] = frame[i]; + } + + // for (int i = 0; i < frameSize; i++) + // printf("buffer[%i] %.5f\n", i, buffer[i]); + + dfval = detectionFunction->getDFsample(buffer); // compute detection function sample + + dfValues.push_back(dfval); + + printf("det val %i: %f\n", counter, dfval); + + if (peakProcess.peakProcessing(dfval)){ + printf("BANG\n"); + onsetPositionFrames.push_back(counter); + int precisesample = preciseLocator.findExactOnset(&buffer[0]); + //so exact sample is + int exactsample = (counter-1)*hopSize;//chunks in from beginning + //as we have just added hopsize samples in, the beginning of the frame is -1 from counter + exactsample += precisesample; + //printf("PreciseSample %i, %i\n", precisesample, exactsample); + if (writeOutput) + writer.writeBeatTime(exactsample/44100.); + + onsetLocations.push_back(exactsample/44100.); + } + + counter++; + printf("read %i samples\n", readcount); + //was sf_write_double(outfile, frame, readcount) ; + + }//end readcount + //END STEREO OKAY + + // Close input file + sf_close (infile); + + if (writeOutput) + writer.closeFile(); + + delete detectionFunction; + detectionFunction = NULL; + + return 0; + +} + + + + +void PreciseOnsetDetectorOffline::update(){ + +} + + +void PreciseOnsetDetectorOffline::draw(){ + //do vizualisation in a specialised class +} + +void PreciseOnsetDetectorOffline::printOnsetLocations(){ + for (int i = 0; i < (int)onsetLocations.size(); i++) + printf("Onset[%i]: %.3f\n", i, onsetLocations[i]); +}