diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hs.h	Tue Oct 05 10:45:57 2010 +0100
@@ -0,0 +1,273 @@
+#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