andrewm@0: /*
andrewm@0:  * spear_parser.h v1.2
andrewm@0:  *
andrewm@0:  *  Created on: May 6, 2014
andrewm@0:  *      Author: Victor Zappi
andrewm@0:  */
andrewm@0: 
andrewm@0: #ifndef SPEAR_PARSER_H_
andrewm@0: #define SPEAR_PARSER_H_
andrewm@0: 
andrewm@0: #include <iostream>
andrewm@0: #include <fstream>
andrewm@0: #include <cstring>
andrewm@0: #include <string>
andrewm@0: #include <stdlib.h>		// atoi, atof
andrewm@0: #include <math.h>
andrewm@0: #include <algorithm>	// std::fill
andrewm@0: 
andrewm@0: #include <sys/time.h>
andrewm@0: 
andrewm@0: using namespace std;
andrewm@0: 
andrewm@0: 
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: // partials
andrewm@0: //------------------------------------------------------------------------------------------------
andrewm@0: 
andrewm@0: class Spear_parser; // for class friendship
andrewm@0: 
andrewm@0: class Partials
andrewm@0: {
andrewm@0: 	friend class Spear_parser;
andrewm@0: 	friend class Dbox_parser;
andrewm@0: 
andrewm@0: public:
andrewm@0: 	int **partialSamples;				// sample at which each frame is
andrewm@0: 	float **partialFrequencies;			// frequencies at each frame
andrewm@0: 	float **partialAmplitudes;			// amplitudes at each frame
andrewm@0: 	unsigned int *partialNumFrames;		// Length of each partial in frames
andrewm@0: 	unsigned int *partialStartFrame;	// frame at which each partial begins
andrewm@0: 	float **partialFreqDelta;			// constant frequency slope for each partial in each frame interval
andrewm@0: 	float **partialAmpDelta;			// constant amplitude slope for each partial in each frame interval
andrewm@0: 	float *partialFreqMean;				// frequency mean for each partial, over all its frames
andrewm@0: 
andrewm@0: 	unsigned short *activePartialNum;	// num of each active partial at each frame
andrewm@0: 	unsigned int **activePartials;		// indices of all active partials at each frame
andrewm@0: 
andrewm@0: 
andrewm@0: 	int getPartialNum();
andrewm@0: 	int getHopNum();
andrewm@0: 	int getMaxActivePartialNum();
andrewm@0: 
andrewm@0: private:
andrewm@0: 	Partials();
andrewm@0: 	~Partials();
andrewm@0: 
andrewm@0: 	unsigned int *partialStartSample;	// sample at which each partial begins
andrewm@0: 	unsigned int *partialEndSample;		// sample at which each partial ends [sample gap between 2 consecutive frames can be an integer multiple of hopSize]
andrewm@0: 	unsigned int parNum;
andrewm@0: 	unsigned int currentSample;
andrewm@0: 	unsigned int hopSize;
andrewm@0: 	unsigned int hopNum;
andrewm@0: 	unsigned int maxActiveParNum;
andrewm@0: 
andrewm@0: 	void init(int parNum, int hopSize, bool isDBX=false);
andrewm@0: 	void update(int parIndex, int frameNum);
andrewm@0: 	void setFreqDelta(int parIndex, int frameNum, double delta);
andrewm@0: 	void setAmpDelta(int parIndex, int frameNum, double delta);
andrewm@0: 	void setHopNum(int hopNum);
andrewm@0: };
andrewm@0: 
andrewm@0: inline int Partials::getPartialNum()
andrewm@0: {
andrewm@0: 	return parNum;
andrewm@0: }
andrewm@0: 
andrewm@0: inline void Partials::setHopNum(int hopN)
andrewm@0: {
andrewm@0: 	hopNum = hopN;
andrewm@0: 
andrewm@0: 	// prepare data structures
andrewm@0: 	activePartialNum 	= new unsigned short[hopNum+1];	// +1 cos total num of frames = num of hops+1
andrewm@0: 	activePartials	 	= new unsigned int *[hopNum+1];
andrewm@0: }
andrewm@0: 
andrewm@0: // useful to increase current sample using a modulo on the total number of samples [easy to be deduced from the total num or hops]
andrewm@0: inline int Partials::getHopNum()
andrewm@0: {
andrewm@0: 	return hopNum;
andrewm@0: }
andrewm@0: 
andrewm@0: inline void Partials::setFreqDelta(int parIndex, int frameNum, double delta)
andrewm@0: {
andrewm@0: 	partialFreqDelta[parIndex][frameNum] = delta;
andrewm@0: }
andrewm@0: 
andrewm@0: inline void Partials::setAmpDelta(int parIndex, int frameNum, double delta)
andrewm@0: {
andrewm@0: 	partialAmpDelta[parIndex][frameNum] = delta;
andrewm@0: }
andrewm@0: 
andrewm@0: inline int Partials::getMaxActivePartialNum()
andrewm@0: {
andrewm@0: 	return maxActiveParNum;
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: 
andrewm@0: class Spear_parser
andrewm@0: {
andrewm@0: public:
andrewm@0: 	Spear_parser();
andrewm@0: 	~Spear_parser();
andrewm@0: 
andrewm@0: 	Partials partials;
andrewm@0: 
andrewm@0: 	bool parseFile(string filename, int hopsize=-1, int samplerate = 44100);
andrewm@0: 	bool parseFile(char *filename, int hopsize=-1, int samplerate = 44100);
andrewm@0: 	int getHopSize();
andrewm@0: 	int getFileSampleRate();
andrewm@0: 	double getDeltaTime();
andrewm@0: 
andrewm@0: private:
andrewm@0: 
andrewm@0: 	int hopSize;
andrewm@0: 	int fileSampleRate;
andrewm@0: 	double deltaTime;	// min time gap between consecutive frames
andrewm@0: 
andrewm@0: 	timeval start, stop;
andrewm@0: 	unsigned long hopSizeT, parserT, staticT;
andrewm@0: 
andrewm@0: 	void calculateDeltaTime();
andrewm@0: 	void calculateHopSize(char *filename);
andrewm@0: 	bool parser(char *filename, int hopsize=-1, int samplerate=44100);
andrewm@0: 	bool DBXparser(char *filename, int samplerate=44100);
andrewm@0: 	bool TXTparser(char *filename, int hopsize=-1, int samplerate=44100);
andrewm@0: 	int fromTimeToSamples(float time);
andrewm@0: 	int interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample,
andrewm@0: 							double nextFreq, double nextAmp, double *prevFreq, double *prevAmp);
andrewm@0: 	void staticCalculations();
andrewm@0: 
andrewm@0: };
andrewm@0: 
andrewm@0: inline bool Spear_parser::parseFile(string filename, int hopsize, int samplerate)
andrewm@0: {
andrewm@0: 	return parser((char *)filename.c_str(), hopsize, samplerate);
andrewm@0: }
andrewm@0: 
andrewm@0: inline bool Spear_parser::parseFile(char *filename, int hopsize, int samplerate)
andrewm@0: {
andrewm@0: 	return parser(filename, hopsize, samplerate);
andrewm@0: }
andrewm@0: 
andrewm@0: inline void Spear_parser::calculateDeltaTime()
andrewm@0: {
andrewm@0: 	deltaTime = (double)hopSize/ (double)fileSampleRate;
andrewm@0: }
andrewm@0: 
andrewm@0: // each time value in the file is rounded, and 2 consecutive frames can differ of a time gap = i*deltaTime, where i is a positive integer
andrewm@0: inline int Spear_parser::fromTimeToSamples(float time)
andrewm@0: {
andrewm@0: 	return round(time/deltaTime)*hopSize;	// round is necessary since in the file log time values are rounded, so they do not apparently look like integer multiples of deltaTime
andrewm@0: }
andrewm@0: 
andrewm@0: inline int Spear_parser::getHopSize()
andrewm@0: {
andrewm@0: 	return hopSize;
andrewm@0: }
andrewm@0: 
andrewm@0: inline int Spear_parser::getFileSampleRate()
andrewm@0: {
andrewm@0: 	return fileSampleRate;
andrewm@0: }
andrewm@0: 
andrewm@0: inline double Spear_parser::getDeltaTime()
andrewm@0: {
andrewm@0: 	return deltaTime;
andrewm@0: }
andrewm@0: 
andrewm@0: #endif /* SPEAR_PARSER_H_ */