Mercurial > hg > x
view hs.h @ 1:6422640a802f
first upload
author | Wen X <xue.wen@elec.qmul.ac.uk> |
---|---|
date | Tue, 05 Oct 2010 10:45:57 +0100 |
parents | |
children | fc19d45615d1 |
line wrap: on
line source
#ifndef hsH #define hsH /* hs.cpp - harmonic sinusoid model Further reading: Wen X. and M. Sandler, "Sinusoid modeling in a harmonic context," in Proc. DAFx'07, Bordeaux, 2007. */ //--------------------------------------------------------------------------- #include <mem.h> #include "arrayalloc.h" #include "align8.h" #include "fft.h" #include "QuickSpec.h" #include "TStream.h" #define ATOM_LOCALANCHOR 1 #define HS_CONSTF 1 #define MAX_CAND 64 #define STIFF_B_MAX 0.01 enum atomtype //type flags of an HS atom { atAnchor, //"anchor" is an atom whose validity is taken for granted, e.g. user input atPeak, //an atom whose frequency is an actual spectral peak atInfered, //an atom which has no spectral peak and whose frequency is inferred from other atoms atMuted, //an atom which is being muted atBuried //an atom which is buried in background noise }; struct atom //an atom of a harmonic sinusoid { double t; //time double s; //scale double f; //digital frequency double a; //amplitude double p; //phase angle int pin; //partial index atomtype type; //atom type int tags; //additional info on atom type float r1; }; struct candid //candidate atom { int p; //partial index double f; //frequency double df; //delta freqdel folk double s; //score in partial-sum int prev; //index of last partial f-df int type; //0: f0, 1: local maximum, 2: not a maxixum double ms; }; struct dsparams1 //argument structure for calling ds1() { double s; //score double lastene; //energy of last frame double currentacce; //energy of this frame, currently accumulated int p; //partial index int lastP; //number of efficient partials in last frame double* lastvfp; //amplitude estimates of partials at last frame }; struct NMResults //note match output structure { double* fp; //frequencies, in bins double* vfp; //amplitudes double* pfp; //phase angles atomtype* ptype; //atom types }; struct NMSettings //note match algorithm settings { double c[4]; //cosine-family window specifiers int M; //ditto double iH2; //ditto double hB; //spectral truncation half width int maxp; //maximal number of partials double maxB; //stiffness coefficient upper bound double epf; //frequency estimation error tolerance for LSE estimation double epf0; //input frequency error bound for harmonic grouping double delm; //frequency error bound for harmonic grouping double delp; //pitch jump upper bound double minf0; //minimal fundamental frequency double maxf0; //maximal fundamental frequency int pin0; //input partial index bool forcepin0; //force the peak nearest to input frequency as an atom bool pin0asanchor; //mark atom found near the input frequency as anchor int pcount; //number of "pinned" (anchor) partials int* pin; //partial indices of pinned partials double* pinf; //frequencies of pinned partials int* pinfr; //frame indices of pinned partials, used in multi-frame constant-pitch note match }; /* stiffcandid is the harmonic atom class used internally by harmonic grouping and tracking routines. Literally it means "candidate harmonic atoms on a stiff string model". The stiff string is the main harmonic model used by me for describing frequency relations between partials of a harmonic sound. stiffcandid is superceded by TTempAtom class. */ class stiffcandid { public: int P; //number of partial estimates located int* p; //partial indices of located partials, sizeof(int)*P double* f; //frequencies of located partials, sizeof(double)*P double s; //score in partial-sum //{N; F, G}: the feasible polygonal area of (F, G) given the P partials, where F=F0*F0, G=F0*B int N; double* F; //sizeof(double)*N double* G; //sizeof(double)*N stiffcandid(int Wid); //create empty with minimal info stiffcandid(int Wid, int ap, double af, double errf); //create empty with pitch range stiffcandid(int Wid, int ap, double af, double errf, double ds); //create with 1 atom stiffcandid(stiffcandid* prev, int ap, double af, double errf, double ds); //create by updating with new atom ~stiffcandid(); }; /* THS is the data structure hosting a harmonic sinusoid representation. Its key members include the number of partials, number of frames, and all its atoms (sinusoid parameters of all partials at measurement points). */ class THS { public: int Channel; //channel id: THS describes a harmonic sinusoid in single channel int M; //number of partials int Fr; //number of frames atom** Partials; //atoms, [M][Fr] int* BufM[128]; //a buffer for algorithmic use int isconstf; //constant frequencies flag double** startamp;//onset amplifiers, optional int st_start; //position of the first onset amplifying point int st_offst; //interval of onset amplifying points int st_count; //number of onset amplifying points //constructors and destructor THS(); THS(int aM, int aFr); THS(THS* HS); THS(THS* HS, double start, double end); ~THS(); int StartPos(); //start position int EndPos(); //end position int EndPosEx(); //extended end position int StdOffst(); //hop size void ClearBufM(); //free buffers registered in BufM[] void Resize(int aM, int aFr, bool copydata=false, bool forcealloc=false); //change size (M or Fr) //I/O routines int WriteHdrToStream(TStream* Stream); int ReadHdrFromStream(TStream* Stream); int WriteAtomToStream(TStream* Stream, atom* atm); int ReadAtomFromStream(TStream* Stream, atom* atm); int WriteToStream(TStream* Stream); int ReadFromStream(TStream* Stream); }; /* TPolygon is a polygon class. This class itself does not enforce convexness. However, when used for solving the stiff string model, all polygons are convex, as they are the results of current a first convex polygon by straight lines. For the convenience of computation, the sequence of vertices are arranged so that they come in clockwise order starting from the leftmost (smallest x coordinate) vertex; in case two vertices are both leftmost the upper (larger y coordinate) one is placed at the start and the lower one is placed at the end. */ class TPolygon { public: int N; //number of vertices (equals number of edges) double* X; //x-coordinates of vertices double* Y; //y-coordinates of vertices TPolygon(int cap); TPolygon(int cap, TPolygon* R); ~TPolygon(); }; /* TTempAtom is an atom class within the stiff-stirng harmonic atom context used internally by harmonic grouping and tracking routines. Literally it means "a temporary atom", and truly it hosts most info one expects of a potential atom. TTempAtom replaces stiffcandid class in harmonic sinusoid group and tracking algorithms, due to the advanges that it carries atom information (frequency, amplitude, etc.) as well as harmonic atom information (link to other atom, the F-G polygon), and is therefore both an individual atom and a harmonic atom containing all atoms tracked down through the linked list Prev. */ class TTempAtom { public: int pind; //partial index double f; //frequency double a; //amplitude double s; //scale double rsr; //residue-sinusoid ratio TTempAtom* Prev; //previous atom TPolygon *R; //F-G polygon for harmonic group union {double acce; int tag[2];}; TTempAtom(double af, double ef, double maxB); //create empty with frequency range TTempAtom(int apin, double af, double ef, double maxB); //create empty with frequency range TTempAtom(TPolygon* AR, double delf1, double delf2, double minf); //create empty with extended R TTempAtom(int apind, double af, double ef, double aa, double as, double maxB); //create with one partial TTempAtom(TTempAtom* APrev, bool DupR); //create duplicate TTempAtom(TTempAtom* APrev, int apind, double af, double ef, double aa, double as, bool updateR=true); //duplicate and add one partial ~TTempAtom(); }; //--internal function-------------------------------------------------------- double ds0(double, void*); //a score function, internal use only //--general polygon routines------------------------------------------------- void areaandcentroid(double& A, double& cx, double& cy, int N, double* x, double* y); //compute area and centroid void cutcvpoly(int& N, double* x, double* y, double A, double B, double C, bool protect=false); //sever polygon by line double maximalminimum(double& x, double& y, int N, double* sx, double* sy); //maximum inscribed circle //--F-G polygon routines----------------------------------------------------- void CutR(TPolygon* R, int apind, double af, double ef, bool protect=false); void ExBStiff(double& Bmin, double& Bmax, int N, double* F, double* G); void ExFmStiff(double& Fmin, double& Fmax, int m, int N, double* F, double* G); void ExtendR(TPolygon* R, double delf1, double delf2, double minf); void InitializeR(TPolygon* R, double af, double ef, double maxB); void InitializeR(TPolygon* R, int apind, double af, double ef, double maxB); //--internal structure conversion routines----------------------------------- int NMResultToAtoms(int M, atom* HP, int t, int wid, NMResults results); int NMResultToPartials(int M, int fr, atom** Partials, int t, int wid, NMResults results); //--batch sinusoid estimation routines--------------------------------------- double PeakShapeC(double f, int Fr, int N, cdouble** x, int B, int M, double* c, double iH2); double PeakShapeC(double f, int Fr, int N, cfloat** x, int B, int M, double* c, double iH2); int QuickPeaks(double* f, double* a, int N, cdouble* x, int M, double* c, double iH2, double mina, int binst=-1, int binen=-1, int B=5, double* rsr=0); int QuickPeaks(double* f, double* a, int Fr, int N, cdouble** x, int fr0, int r0, int M, double* c, double iH2, double mina, int binst=-1, int binen=-1, int B=5, double* rsr=0); //--harmonic atom detection (harmonic grouping) routines--------------------- double NoteMatchStiff3(TPolygon* R, double &f0, double& B, int pc, double* fps, double* vps, int Fr, cdouble** x, int N, int offst, NMSettings* settings, NMResults* results, int lastp, double* lastvfp, double (*computes)(double a, void* params)=ds0, int forceinputlocalfr=-1); //basic grouping without rsr double NoteMatchStiff3(TPolygon* R, double &f0, double& B, int pc, double* fps, double* vps, double* rsr, int Fr, cdouble** x, int N, int offst, NMSettings* settings, NMResults* results, int lastp, double* lastvfp, double (*computes)(double a, void* params)=ds0, int forceinputlocalfr=-1); //basic grouping with rsr double NoteMatchStiff3(TPolygon* R, double &f0, double& B, int Fr, cdouble** x, int N, int offst, NMSettings* settings, NMResults* results, int lastp, double* lastvfp, double (*deltas)(double a, void* params)=ds0, bool forceinputlocalfr=false, int startfr=-1, int validfrrange=0); //basic grouping with rsr - wrapper double NoteMatchStiff3(TPolygon* R, int peak0, int pin0, cdouble* x, int pc, double* fps, double* vps, int N, NMSettings* settings, double* vfp, int** pitchind, int newpc); //grouping with given pitch, single-frame //--harmonic sinusoid tracking routines-------------------------------------- int FindNote(int _t, double _f, int& M, int& Fr, atom**& partials, int frst, int fren, int wid, int offst, TQuickSpectrogram* Spec, NMSettings settings); //harmonic sinusoid tracking (forward and backward tracking) int FindNoteConst(int _t, double _f, int& M, int& Fr, atom**& partials, int frst, int fren, int wid, int offst, TQuickSpectrogram* Spec, NMSettings settings, double brake); //constant-pitch harmonic sinusoid tracking int FindNoteF(atom* part, double& starts, TPolygon* R, int startp, double* startvfp, int frst, int fren, int wid, int offst, TQuickSpectrogram* Spec, NMSettings settings, double brake); //forward harmonic sinusoid tracking int FindNoteFB(int frst, TPolygon* Rst, double* vfpst, int fren, TPolygon* Ren, double* vfpen, int M, atom** partials, int wid, int offst, TQuickSpectrogram* Spec, NMSettings settings); //forward-backward harmonic sinusoid tracking void NoteMatchStiff3FB(int& pitchcount, TPolygon**& R, double**& vfp, double*& sc, int* newpitches, int* prev, int pc, double* fps, double* vps, cdouble* x, int wid, int maxpitch, NMSettings* settings); //single DP step of FindNoteFB() //--harmonic sinusoid synthesis routines------------------------------------- double* SynthesisHS(int pm, int pfr, atom** partials, int& dst, int& den, bool* terminatetag=0); double* SynthesisHS2(int M, int Fr, atom** partials, int& dst, int& den, bool* terminatetag=0); double* SynthesisHSp(int pm, int pfr, atom** partials, int& dst, int& den, double** startamp=0, int st_start=0, int st_offst=0, int st_count=0); double* SynthesisHSp(THS* HS, int& dst, int& den); //--other functions---------------------------------------------------------- void ReEstHS1(THS* HS, __int16* Data16); //reestimation of HS #endif