Mercurial > hg > precise-onset-detection
view ofxPreciseOnsetDetectorOffline/PreciseOnsetDetectorOffline.cpp @ 6:eb29c6b6dff8
added pointer version of visualiser
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Sun, 19 Jan 2014 23:07:13 +0000 |
parents | 93b9a9471011 |
children | b1c13e8bec26 |
line wrap: on
line source
/* * PreciseOnsetDetectorOffline.cpp * ofxPreciseOnsetDetectionOffline * * Created by Andrew Robertson on 25/12/2013. * Copyright 2013 QMUL. All rights reserved. * */ //add a retrigger threshold #include "PreciseOnsetDetectorOffline.h" const bool printingOn = false; 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(){ //delete infile; } int 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' return processAudioForBeatTimes(filename); } int PreciseOnsetDetectorOffline::processAudioForBeatTimes(std::string audiofile){ //originally from BeatAnnotationViewer project 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); 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); if (printingOn) printf("det val %i: %f\n", counter, dfval); if (peakProcess.peakProcessing(dfval)){ 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); onsetLocations.push_back(exactsample/44100.); if (printingOn) printf("BANG\n"); } 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); delete detectionFunction; detectionFunction = NULL; printf("Number of samples%i\n", samples); return 0; } double PreciseOnsetDetectorOffline::frameIndexToSeconds(const int& frameIndex){ return ((double)(frameIndex*hopSize) /44100.);//- (detectionFunction.framesize/2)?; } double PreciseOnsetDetectorOffline::secondsToFrameIndex(const double& seconds){ return (seconds*44100./(double)hopSize );//- (detectionFunction.framesize/2)?; } void PreciseOnsetDetectorOffline::exportOnsetTimes(){ exportOnsetTimes(0.0, samples/44100.0);//i.e. the whole file } void PreciseOnsetDetectorOffline::exportOnsetTimes(double startTime, double endTime){ //for writing output BeatWriter writer; std::string outputFilename = loadedFilename+"_preciseOnsets.txt"; if (writeOutput) writer.openFile(outputFilename); int index = 0; while (index < onsetLocations.size() && onsetLocations[index] < startTime) index++; while (index < onsetLocations.size() && onsetLocations[index] <= endTime){ writer.writeBeatTime(onsetLocations[index]); index++; } if (writeOutput) writer.closeFile(); } 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]); } double PreciseOnsetDetectorOffline::closestOnset(double& targetVal){ int bestIndex = 0; double bestDiff = 99999; double bestVal = -1; for (int testIndex = 0; testIndex < (int)onsetLocations.size(); testIndex++){ double testDiff = (onsetLocations[testIndex] - targetVal); if (fabs(testDiff) < bestDiff){ bestDiff = fabs(testDiff); bestVal = onsetLocations[testIndex]; bestIndex = testIndex; } } return bestVal; } void PreciseOnsetDetectorOffline::loadOnsetLocations(DoubleVector& beats){ //replaces onset locations with new vector onsetLocations.clear(); for (int i = 0; i < beats.size(); i++){ onsetLocations.push_back(beats[i]); } }