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]);
+}