andrewm@0: /*
andrewm@0:  * spear_parser.cpp v1.2
andrewm@0:  *
andrewm@0:  *  Created on: May 6, 2014
andrewm@0:  *      Author: Victor Zappi
andrewm@0:  */
andrewm@0: 
andrewm@0: #include "spear_parser.h"
andrewm@0: 
andrewm@0: using namespace std;
andrewm@0: 
andrewm@0: //#define DO_CHECKS
andrewm@0: 
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: // partials
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: 
andrewm@0: Partials::Partials()
andrewm@0: {
andrewm@0: 	partialFrequencies	= NULL;
andrewm@0: //	partialAmplitudes	= NULL;
andrewm@0: //	partialNumFrames	= NULL;
andrewm@0: //	partialStartSample	= NULL;
andrewm@0: //	partialEndSample	= NULL;
andrewm@0: //	partialCurrentFrame	= NULL;
andrewm@0: //	partialFreqDelta	= NULL;
andrewm@0: //	partialAmpDelta	= NULL;
andrewm@0: 
andrewm@0: 
andrewm@0: 	activePartialNum	= NULL;
andrewm@0: //	activePartials		= NULL;
andrewm@0: 
andrewm@0: 	currentSample = -1;
andrewm@0: }
andrewm@0: 
andrewm@0: Partials::~Partials()
andrewm@0: {
andrewm@0: 	if(partialFrequencies != NULL)			// check on one is enough
andrewm@0: 	{
andrewm@0: 		if(partialFrequencies[0] != NULL)	// check on one is enough
andrewm@0: 		{
andrewm@0: 			for(unsigned int i=0; i<parNum; i++)
andrewm@0: 			{
andrewm@0: 				delete[] partialFrequencies[i];
andrewm@0: 				delete[] partialAmplitudes[i];
andrewm@0: 				delete[] partialFreqDelta[i];
andrewm@0: 				delete[] partialAmpDelta[i];
andrewm@0: 
andrewm@0: 			}
andrewm@0: 		}
andrewm@0: 
andrewm@0: 		delete[] partialFrequencies;
andrewm@0: 		delete[] partialAmplitudes;
andrewm@0: 		delete[] partialNumFrames;
andrewm@0: 		delete[] partialFreqDelta;
andrewm@0: 		delete[] partialAmpDelta;
andrewm@0: 		delete[] partialFreqMean;
andrewm@0: 	}
andrewm@0: 
andrewm@0: 	if(activePartialNum != NULL)
andrewm@0: 	{
andrewm@0: 		for(unsigned int i=0; i<hopNum+1; i++)
andrewm@0: 			delete[] activePartials[i];
andrewm@0: 
andrewm@0: 		delete[] activePartialNum;
andrewm@0: 		delete[] activePartials ;
andrewm@0: 	}
andrewm@0: }
andrewm@0: 
andrewm@0: void Partials::init(int parN, int hopS, bool isDBX)
andrewm@0: {
andrewm@0: 	if(!isDBX)
andrewm@0: 	{
andrewm@0: 		parNum	= parN;
andrewm@0: 		hopSize	= hopS;
andrewm@0: 
andrewm@0: 		partialFrequencies	= new float *[parNum];
andrewm@0: 		partialAmplitudes	= new float *[parNum];
andrewm@0: 		partialNumFrames	= new unsigned int[parNum];
andrewm@0: 		partialStartFrame	= new unsigned int[parNum];
andrewm@0: 		partialStartSample	= new unsigned int[parNum];
andrewm@0: 		partialEndSample	= new unsigned int[parNum];
andrewm@0: 		partialFreqDelta	= new float *[parNum];
andrewm@0: 		partialAmpDelta		= new float *[parNum];
andrewm@0: 		partialFreqMean		= new float[parNum];
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 		// init in one shot
andrewm@0: 		fill(partialFreqMean, partialFreqMean+parNum, 0);			// mean is zero
andrewm@0: 
andrewm@0: 		partialFrequencies[0] 	= NULL;								// for free check
andrewm@0: 	}
andrewm@0: 	else
andrewm@0: 	{
andrewm@0: 		parNum	= parN;
andrewm@0: 		hopSize	= hopS;
andrewm@0: 
andrewm@0: 		partialFrequencies	= new float *[parNum];
andrewm@0: 		partialAmplitudes	= new float *[parNum];
andrewm@0: 		partialNumFrames	= new unsigned int[parNum];
andrewm@0: 		partialStartFrame	= new unsigned int[parNum];
andrewm@0: 		partialFreqDelta	= new float *[parNum];
andrewm@0: 		partialAmpDelta		= new float *[parNum];
andrewm@0: 		partialFreqMean		= new float[parNum];
andrewm@0: 
andrewm@0: 		partialFrequencies[0] 	= NULL;								// for free check
andrewm@0: 	}
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: void Partials::update(int parIndex, int frameNum)
andrewm@0: {
andrewm@0: 	partialFrequencies[parIndex] = new float[frameNum];
andrewm@0: 	partialAmplitudes[parIndex]	 = new float[frameNum];
andrewm@0: 	partialFreqDelta[parIndex]	 = new float[frameNum];
andrewm@0: 	partialAmpDelta[parIndex]	 = new float[frameNum];
andrewm@0: 
andrewm@0: 	fill(partialFreqDelta[parIndex], partialFreqDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
andrewm@0: 	fill(partialAmpDelta[parIndex], partialAmpDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: // spear parser
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: Spear_parser::Spear_parser()
andrewm@0: {
andrewm@0: 	// some default values
andrewm@0: 	hopSize			= -1;
andrewm@0: 	fileSampleRate	= -1;
andrewm@0: }
andrewm@0: 
andrewm@0: Spear_parser::~Spear_parser()
andrewm@0: {
andrewm@0: }
andrewm@0: 
andrewm@0: void Spear_parser::calculateHopSize(char *filename)
andrewm@0: {
andrewm@0: 	int index 		= 0;
andrewm@0: 	bool prevWas_ 	= false;
andrewm@0: 	bool found_h	= false;
andrewm@0: 	int n 			= 0;
andrewm@0: 
andrewm@0: 	hopSize 		= 0;
andrewm@0: 
andrewm@0: 	do
andrewm@0: 	{
andrewm@0: 		// check if '_'
andrewm@0: 		if(filename[index] == '_')
andrewm@0: 			prevWas_ = true;
andrewm@0: 		else if( (filename[index] == 'h') && prevWas_) // if it is not, but it is 'h' and previous was '_', found "_h"!
andrewm@0: 		{
andrewm@0: 			found_h = true;
andrewm@0: 			while(filename[index] != '\0')
andrewm@0: 			{
andrewm@0: 				index++;
andrewm@0: 				if( (filename[index] == '.') || (filename[index] == '_'))
andrewm@0: 					break;
andrewm@0: 				else // i am not checking if char are digits...!
andrewm@0: 				{
andrewm@0: 					n = filename[index];
andrewm@0: 					hopSize =  hopSize*10+(n-48);
andrewm@0: 				}
andrewm@0: 			}
andrewm@0: 		}
andrewm@0: 		else	// else, nothing
andrewm@0: 			prevWas_ = false;
andrewm@0: 		index++;
andrewm@0: 	}
andrewm@0: 	while( (filename[index] != '\0') && !found_h );
andrewm@0: 
andrewm@0: 	if( !found_h || (hopSize<1) )
andrewm@0: 		hopSize = 551;	// default val
andrewm@0: 
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: bool Spear_parser::parser(char *filename, int hopsize, int samplerate)
andrewm@0: {
andrewm@0: 	string name = string(filename);
andrewm@0: 	int len		= name.length();
andrewm@0: 	// invoke correct parser according to the type of file...just checking the extension, crude but functional
andrewm@0: 	if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
andrewm@0: 		return DBXparser(filename, samplerate);				// .dbox
andrewm@0: 	else
andrewm@0: 		return TXTparser(filename, hopSize, samplerate);	// .txt, or whatever
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: bool Spear_parser::DBXparser(char *filename, int samplerate)
andrewm@0: {
andrewm@0: 	fileSampleRate 	= samplerate;
andrewm@0: 
andrewm@0: 	// working vars
andrewm@0: 	int parNum		= 0;	// total num of partials
andrewm@0: 	int hopNum		= 0;	// total num of hops
andrewm@0: 
andrewm@0: 	//----------------------------------------------------------------------------------------
andrewm@0: 	// open a file
andrewm@0: 	ifstream fin;
andrewm@0: 	fin.open(filename, ios::in | ios::binary);
andrewm@0: 	if (!fin.good())
andrewm@0: 	{
andrewm@0: 		cout << "Parser Error: file not found" << endl;	// exit if file not found
andrewm@0: 		return false;
andrewm@0: 	}
andrewm@0: 
andrewm@0: 	gettimeofday(&start, NULL);
andrewm@0: 	//----------------------------------------------------------------------------------------
andrewm@0: 	// general data
andrewm@0: 
andrewm@0: 	// look for partial count
andrewm@0: 	fin.read((char *) &parNum, sizeof(int));
andrewm@0: 	partials.parNum 		= parNum;
andrewm@0: 
andrewm@0: 	// look for hop count
andrewm@0: 	fin.read((char *) &hopNum, sizeof(int));
andrewm@0: 	partials.setHopNum(hopNum);
andrewm@0: 
andrewm@0: 	// look for hop size
andrewm@0: 	fin.read((char *) &hopSize, sizeof(int));
andrewm@0: 	partials.hopSize 		= hopSize;		// it's handy for both classes to know it
andrewm@0: 
andrewm@0: 	// init partials data structure
andrewm@0: 	partials.init(parNum, hopSize, true);
andrewm@0: 
andrewm@0: 	// look for max active par num
andrewm@0: 	fin.read((char *) &(partials.maxActiveParNum), sizeof(int));
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 	// partial data
andrewm@0: 
andrewm@0: 	// start frame of each partial
andrewm@0: 	fin.read((char *) partials.partialStartFrame, sizeof(int)*parNum);
andrewm@0: 
andrewm@0: 	// num of frames of each partial
andrewm@0: 	fin.read((char *) partials.partialNumFrames, sizeof(int)*parNum);
andrewm@0: 
andrewm@0: 	// frequency mean of each partial
andrewm@0: 	fin.read((char *) partials.partialFreqMean, sizeof(int)*parNum);
andrewm@0: 
andrewm@0: 	for(int par=0; par<parNum; par++)
andrewm@0: 	{
andrewm@0: 		int frameNum = partials.partialNumFrames[par];
andrewm@0: 		partials.update(par, frameNum);
andrewm@0: 		fin.read((char *)partials.partialAmplitudes[par], sizeof(float)*frameNum);		// amplitude of each partial in each frame
andrewm@0: 		fin.read((char *)partials.partialFrequencies[par], sizeof(float)*frameNum);		// frequency of each partial in each frame
andrewm@0: 		fin.read((char *)partials.partialAmpDelta[par], sizeof(float)*frameNum);			// amplitude delta of each partial in each frame
andrewm@0: 		fin.read((char *)partials.partialFreqDelta[par], sizeof(float)*frameNum);			// frequency delta of each partial in each frame
andrewm@0: 	}
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 	// frame data
andrewm@0: 
andrewm@0: 	// number of active partial per each frame
andrewm@0: 	fin.read((char *) partials.activePartialNum, sizeof(short)*(hopNum+1));
andrewm@0: 	// init array
andrewm@0: 	for(int frame=0; frame<hopNum+1; frame++)
andrewm@0: 	{
andrewm@0: 		partials.activePartials[frame] = new unsigned int[partials.activePartialNum[frame]];
andrewm@0: 		fin.read((char *)partials.activePartials[frame], sizeof(int)*partials.activePartialNum[frame]);			// active partials per each frame
andrewm@0: 	}
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 	gettimeofday(&stop, NULL);
andrewm@0: 	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
andrewm@0: 
andrewm@0: 
andrewm@0: 	printf("\n-----------------------\n");
andrewm@0: 	printf("\nFile: %s\n", filename);
andrewm@0: 	printf("\n-----------------------\n");
andrewm@0: 	printf("Profiler\n");
andrewm@0: 	printf("-----------------------\n");
andrewm@0: 	printf("File parser:\t\t\t%lu usec\n", parserT);
andrewm@0: 	printf("\n\nTotal:\t\t%lu usec\n", parserT);
andrewm@0: 	printf("-----------------------\n");
andrewm@0: 
andrewm@0: 	fin.close();
andrewm@0: 
andrewm@0: 	return true;
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: bool Spear_parser::TXTparser(char *filename, int hopsize, int samplerate)
andrewm@0: {
andrewm@0: 	hopSize 		= hopsize;
andrewm@0: 	fileSampleRate 	= samplerate;
andrewm@0: 	if(hopsize<0)
andrewm@0: 	{
andrewm@0: 		gettimeofday(&start, NULL);
andrewm@0: 		calculateHopSize(filename);
andrewm@0: 		gettimeofday(&stop, NULL);
andrewm@0: 		hopSizeT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
andrewm@0: 	}
andrewm@0: 	else
andrewm@0: 		hopSizeT = 0;
andrewm@0: 
andrewm@0: 	calculateDeltaTime();
andrewm@0: 
andrewm@0: 	// working vars
andrewm@0: 	char * token;			// where to save single figures from file
andrewm@0: 	string s		= "";	// where to save lines from file
andrewm@0: 	int parNum		= 0;	// total num of partials
andrewm@0: 	int parIndex	= -1;	// index of current partial
andrewm@0: 	int frameNum	= 0;	// total num of frames
andrewm@0: 	int frameIndex	= -1;	// index of current frame
andrewm@0: 	int startSample	= -1;	// sample value for first frame of partials
andrewm@0: 	int endSample	= -1;	// sample value for last frame of partials
andrewm@0: 	int maxSample	= 0;	// to calculate total number of hops in file
andrewm@0: 	int missSampCnt = 0;	// number of mising samples
andrewm@0: 	double freq		= 0;	// to calculate frequency delta
andrewm@0: 	double prevFreq	= 0;	// to calculate frequency delta
andrewm@0: 	double amp		= 0;	// to calculate amplitude delta
andrewm@0: 	double prevAmp	= 0;	// to calculate amplitude delta
andrewm@0: 
andrewm@0: 
andrewm@0: 	//----------------------------------------------------------------------------------------
andrewm@0: 	// open a file
andrewm@0: 	ifstream fin;
andrewm@0: 	fin.open(filename);
andrewm@0: 	if (!fin.good())
andrewm@0: 	{
andrewm@0: 		cout << "Parser Error: file not found" << endl;	// exit if file not found
andrewm@0: 		return false;
andrewm@0: 	}
andrewm@0: 
andrewm@0: 	gettimeofday(&start, NULL);
andrewm@0: 	//----------------------------------------------------------------------------------------
andrewm@0: 	// init partials data structure
andrewm@0: 	getline(fin, s);
andrewm@0: 	getline(fin, s);
andrewm@0: 	getline(fin, s);	// third line is the first we are interested into
andrewm@0: 
andrewm@0: 	// look for partial count
andrewm@0: 	token = strtok((char *)s.c_str(), " ");
andrewm@0: 	// check if first token is there
andrewm@0: 	if(token)
andrewm@0: 	{
andrewm@0: 		token = strtok(0, " ");
andrewm@0: 		// check if second token is there
andrewm@0: 		if(token)
andrewm@0: 			parNum = atoi(token);
andrewm@0: 		#ifdef DO_CHECKS
andrewm@0: 		else
andrewm@0: 		{
andrewm@0: 			cout << "Parser Error: partial count not found, bad file format" << endl;	// exit if value not found
andrewm@0: 			return false;
andrewm@0: 		}
andrewm@0: 		#endif
andrewm@0: 	}
andrewm@0: 	#ifdef DO_CHECKS
andrewm@0: 	else
andrewm@0: 	{
andrewm@0: 		cout << "Parser Error: partial count not found, bad file format" << endl;		// exit if value not found
andrewm@0: 		return false;
andrewm@0: 	}
andrewm@0: 	#endif
andrewm@0: 	// from now on we take for granted that format is correct
andrewm@0: 
andrewm@0: 	// init partials data structure
andrewm@0: 	partials.init(parNum, hopSize);
andrewm@0: 
andrewm@0: 	//----------------------------------------------------------------------------------------
andrewm@0: 	// fill in partials data structure
andrewm@0: 	getline(fin, s);		// get rid of intro line "partials-data"
andrewm@0: 	getline(fin, s);		// first important line
andrewm@0: 
andrewm@0: 	while (!fin.eof())
andrewm@0: 	{
andrewm@0: 		//-------------------------------------
andrewm@0: 		// partial specific info
andrewm@0: 		token		= strtok((char *)s.c_str(), " ");
andrewm@0: 		parIndex	= atoi(token);						// partial index
andrewm@0: 
andrewm@0: 		token		= strtok(0, " ");					// num of frames, not used, cos we will do linear interpolation for missing frames
andrewm@0: //		frameNum	= atoi(token);
andrewm@0: //		partials.partialNumFrames[parIndex]	= frameNum;
andrewm@0: 
andrewm@0: 		token		= strtok(0, " ");					// time of first frame, still char *
andrewm@0: 		startSample = fromTimeToSamples(atof(token));	// convert time to samples
andrewm@0: 		partials.partialStartSample[parIndex]	= startSample;
andrewm@0: 
andrewm@0: 		token		= strtok(0, " ");					// time of last frame, still char *
andrewm@0: 		endSample	= fromTimeToSamples(atof(token)); 	// convert time to samples
andrewm@0: 		partials.partialEndSample[parIndex]		= endSample;
andrewm@0: 
andrewm@0: 		frameNum	= ((endSample-startSample)/hopSize) + 1;	// num of frames, including missing consecutive ones [+1 one cos we count frames, not hops]
andrewm@0: 		partials.partialNumFrames[parIndex]		= frameNum;
andrewm@0: 
andrewm@0: 
andrewm@0: 		// check if this is the highest sample value so far
andrewm@0: 		if(endSample > maxSample)
andrewm@0: 			maxSample = endSample;
andrewm@0: 
andrewm@0: 		// update data structure
andrewm@0: 		partials.update(parIndex, frameNum);
andrewm@0: 
andrewm@0: 
andrewm@0: 		//-------------------------------------
andrewm@0: 		// frames
andrewm@0: 		getline(fin, s);
andrewm@0: 		token		= strtok((char *)s.c_str(), " ");	// frame time
andrewm@0: 		frameIndex	= -1;
andrewm@0: 
andrewm@0: 		// unroll first iteration, so that in the following loop we save the check on the last frame to calculate increments
andrewm@0: 		if(token)						// all frames data are on one line, in groups of 3 entries
andrewm@0: 		{
andrewm@0: 			frameIndex++;
andrewm@0: 
andrewm@0: 			endSample	= fromTimeToSamples(atof(token));
andrewm@0: 
andrewm@0: 			token		= strtok(0, " ");	// frame frequency
andrewm@0: 			prevFreq	= atof(token);
andrewm@0: 			partials.partialFrequencies[parIndex][frameIndex]	= (float)prevFreq;
andrewm@0: 			partials.partialFreqMean[parIndex] 					+= prevFreq;		// for frequency mean
andrewm@0: 
andrewm@0: 			token	 	= strtok(0, " ");	// frame amplitude
andrewm@0: 			prevAmp  	= atof(token);
andrewm@0: 			partials.partialAmplitudes[parIndex][frameIndex]	= (float)prevAmp;
andrewm@0: 
andrewm@0: 			token 		= strtok(0, " ");	// next frame frequency, to be checked
andrewm@0: 		}
andrewm@0: 
andrewm@0: 		// here the loop starts
andrewm@0: 		while(token)						// all frames data are on one line, in groups of 3 entries
andrewm@0: 		{
andrewm@0: 			frameIndex++;
andrewm@0: 			missSampCnt 	= 0;
andrewm@0: 
andrewm@0: 			startSample		= fromTimeToSamples(atof(token));
andrewm@0: 
andrewm@0: 			token			= strtok(0, " ");	// frame frequency
andrewm@0: 			freq			= atof(token);
andrewm@0: 
andrewm@0: 			token			= strtok(0, " ");	// frame amplitude
andrewm@0: 			amp				= atof(token);
andrewm@0: 			// now we know all about the current frame, but we want to know if some frames are missing between this and the last one
andrewm@0: 
andrewm@0: 			// while current frame sample is farther than one hopsize...
andrewm@0: 			while(startSample > endSample+hopSize)
andrewm@0: 			{
andrewm@0: 				missSampCnt++;				// ...one sample is missing
andrewm@0: 				endSample += hopSize;		// move to next hop
andrewm@0: 			}
andrewm@0: 
andrewm@0: 			// if frames are missing do interpolation and update indices
andrewm@0: 			if(missSampCnt>0)
andrewm@0: 				startSample = interpolateSamples(parIndex, &frameIndex, missSampCnt, endSample+hopSize, freq, amp, &prevFreq, &prevAmp);
andrewm@0: 
andrewm@0: 			partials.partialFrequencies[parIndex][frameIndex]	= (float)freq;
andrewm@0: 			partials.partialFreqMean[parIndex] 					+= freq;			// for frequency mean
andrewm@0: 			partials.setFreqDelta(parIndex, frameIndex-1, (freq-prevFreq)/hopSize);	// freq delta between prev and current frame
andrewm@0: 			prevFreq 	= freq;
andrewm@0: 
andrewm@0: 			partials.partialAmplitudes[parIndex][frameIndex]	= (float)amp;
andrewm@0: 			partials.setAmpDelta(parIndex, frameIndex-1, (amp-prevAmp)/hopSize);	// amp delta between prev and current frame
andrewm@0: 			prevAmp		= amp;
andrewm@0: 
andrewm@0: 			endSample	= startSample;
andrewm@0: 			token		= strtok(0, " ");	// next frame frequency, to be checked
andrewm@0: 		}
andrewm@0: 		#ifdef DO_CHECKS
andrewm@0: 		if(frameIndex != (frameNum-1))
andrewm@0: 		{
andrewm@0: 			cout << "Parser Error: frame count mismatch on partial " << parIndex << ", bad file format"  << endl;	// exit if mismatch
andrewm@0: 			cout << "frameIndex: " << frameIndex << endl;
andrewm@0: 			cout << "frameNum: " << frameNum << endl;
andrewm@0: 			return false;
andrewm@0: 		}
andrewm@0: 		#endif
andrewm@0: 
andrewm@0: 		partials.partialFreqMean[parIndex] /= partials.partialNumFrames[parIndex];									// frequency mean
andrewm@0: 
andrewm@0: 		getline(fin, s);					// next partial line, to check
andrewm@0: 	}
andrewm@0: 	#ifdef DO_CHECKS
andrewm@0: 	if(parIndex != (parNum-1))
andrewm@0: 	{
andrewm@0: 		cout << "Parser Error: partial count mismatch, bad file format"  << endl;									// exit if mismatch
andrewm@0: 		return false;
andrewm@0: 	}
andrewm@0: 	#endif
andrewm@0: 
andrewm@0: 	partials.setHopNum(maxSample/hopSize);
andrewm@0: 
andrewm@0: 	gettimeofday(&stop, NULL);
andrewm@0: 	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
andrewm@0: 
andrewm@0: 	gettimeofday(&start, NULL);
andrewm@0: 	staticCalculations();
andrewm@0: 	gettimeofday(&stop, NULL);
andrewm@0: 	staticT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
andrewm@0: 
andrewm@0: 	fin.close();
andrewm@0: 
andrewm@0: 
andrewm@0: 	printf("\n-----------------------\n");
andrewm@0: 	printf("\nFile: %s\n", filename);
andrewm@0: 	printf("\n-----------------------\n");
andrewm@0: 	printf("Profiler\n");
andrewm@0: 	printf("-----------------------\n");
andrewm@0: 	printf("Hop size parser:\t\t%lu usec\n", hopSizeT);
andrewm@0: 	printf("File parser:\t\t\t%lu usec\n", parserT);
andrewm@0: 	printf("Static calculations:\t\t%lu usec\n", staticT);
andrewm@0: 	printf("\n\nTotal:\t\t%lu usec\n", hopSizeT+parserT+staticT);
andrewm@0: 	printf("-----------------------\n");
andrewm@0: 
andrewm@0: 	return true;
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: int Spear_parser::interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample, double nextFreq, double nextAmp, double *prevFreq, double *prevAmp)
andrewm@0: {
andrewm@0: 	int frame			= *frameIndex;						// current frame index
andrewm@0: 	int sample			= nextSample - (hopSize*(missCnt)); // move from next real frame sample to first missing frame sample
andrewm@0: 	double freq			= *prevFreq;						// freq of the prev real frame
andrewm@0: 	double freqStep		= (nextFreq-*prevFreq)/(missCnt+1);	// fixed freq step between hops, for missing frames [linear interpolation]
andrewm@0: 	double deltaFreq	= freqStep/hopSize;					// fixed hop freq step in samples
andrewm@0: 	double amp			= *prevAmp;							// same for amp...
andrewm@0: 	double ampStep		= (nextAmp-*prevAmp)/(missCnt+1);
andrewm@0: 	double deltaAmp		= ampStep/hopSize;
andrewm@0: 
andrewm@0: 	// for each missing frame
andrewm@0: 	for(int i=0; i<missCnt; i++)
andrewm@0: 	{
andrewm@0: 		// calculate values for current missing frame
andrewm@0: 		freq	+= freqStep;
andrewm@0: 		amp		+= ampStep;
andrewm@0: 		// save values
andrewm@0: 		partials.partialFrequencies[parIndex][frame]	= freq;
andrewm@0: 		partials.partialAmplitudes[parIndex][frame]		= amp;
andrewm@0: 		partials.partialFreqMean[parIndex]				+= freq;	// for frequency mean
andrewm@0: 		// set deltas of previous frame [real or missing]
andrewm@0: 		partials.setFreqDelta(parIndex, frame-1, deltaFreq);
andrewm@0: 		partials.setAmpDelta(parIndex, frame-1, deltaAmp);
andrewm@0: 		// move to next frame [missing or real]
andrewm@0: 		sample += hopSize;
andrewm@0: 		frame++;
andrewm@0: 	}
andrewm@0: 
andrewm@0: 	// update global values
andrewm@0: 	*frameIndex	= frame;
andrewm@0: 	*prevFreq	= freq;
andrewm@0: 	*prevAmp	= amp;
andrewm@0: 
andrewm@0: 	return sample;	// return the frame sample of the next real frame
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: 
andrewm@0: // for each frame, statically calculate:
andrewm@0: // - which partial is active [and the total num of active partials]
andrewm@0: // - at which local frame each partial is
andrewm@0: void Spear_parser::staticCalculations()
andrewm@0: {
andrewm@0: 	partials.maxActiveParNum = 0;				// init to find maximum
andrewm@0: 
andrewm@0: 	unsigned short *indices	= new unsigned short[partials.parNum];	// temp array to store up to the maximum num of active partial indices
andrewm@0: 	unsigned int activeCnt	= 0;						// counts the num of active partials in each frame
andrewm@0: 
andrewm@0: 	unsigned int frameSample = 0;						// current frame in samples
andrewm@0: 
andrewm@0: 	char *partialStarted = new char [partials.parNum];	// index of the last local frame found per each partial
andrewm@0: 	fill(partialStarted, partialStarted+partials.parNum, 0);
andrewm@0: 
andrewm@0: 	for(unsigned int i=0; i<partials.hopNum+1; i++)		// for each frame [not hops, this explains the +1]
andrewm@0: 	{
andrewm@0: 		//partials.localPartialFrames[i] = new int[partials.parNum];	// init all local frames to -1
andrewm@0: 		//fill(partials.localPartialFrames[i], partials.localPartialFrames[i]+partials.parNum, -1);
andrewm@0: 
andrewm@0: 		frameSample = i*hopSize;	// current frame, expressed in samples
andrewm@0: 		activeCnt	  = 0;			// reset a each frame
andrewm@0: 
andrewm@0: 		for(unsigned int j=0; j<partials.parNum; j++)	// for each partial
andrewm@0: 		{
andrewm@0: 			// check if inside active time region [expressed in samples]
andrewm@0: 			if( (frameSample>=partials.partialStartSample[j]) && (frameSample<partials.partialEndSample[j]) )	// frame sample not equal to end sample, this filters out last frames and partials with one frame only
andrewm@0: 			{
andrewm@0: 				// activity
andrewm@0: 				indices[activeCnt] = j;	// save active index
andrewm@0: 				activeCnt++;			// increase counter
andrewm@0: 
andrewm@0: 				// partial local frames
andrewm@0: 				if(partialStarted[j]==0)	// this partial has just started, so current local frame is first frame
andrewm@0: 				{
andrewm@0: 					partialStarted[j] 		 		= 1;
andrewm@0: 					partials.partialStartFrame[j]	= i;	// here is the number of the first frame
andrewm@0: 				}
andrewm@0: 			}
andrewm@0: 		}
andrewm@0: 
andrewm@0: 		// activity
andrewm@0: 		partials.activePartialNum[i] = activeCnt;							// save number of active partials for this frame
andrewm@0: 		partials.activePartials[i]	 = new unsigned int[activeCnt];					// set correct size to save all indices
andrewm@0: 
andrewm@0: 		// look for maximum number of active partials at the same time
andrewm@0: 		if(activeCnt > partials.maxActiveParNum)
andrewm@0: 			partials.maxActiveParNum = activeCnt;
andrewm@0: 
andrewm@0: 		// copy indices
andrewm@0: 		for(unsigned int k=0; k<activeCnt; k++)
andrewm@0: 			partials.activePartials[i][k] = indices[k];
andrewm@0: 	}
andrewm@0: 
andrewm@0: 	delete[] indices;
andrewm@0: 	delete[] partialStarted;
andrewm@0: 
andrewm@0: 	delete[] partials.partialStartSample;
andrewm@0: 	delete[] partials.partialEndSample;
andrewm@0: }
andrewm@0: 
andrewm@0: 
andrewm@0: