annotate hs.h @ 13:de3961f74f30 tip

Add Linux/gcc Makefile; build fix
author Chris Cannam
date Mon, 05 Sep 2011 15:22:35 +0100
parents 977f541d6683
children
rev   line source
xue@11 1 /*
xue@11 2 Harmonic sinusoidal modelling and tools
xue@11 3
xue@11 4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
xue@11 5 Centre for Digital Music, Queen Mary, University of London.
xue@11 6 This file copyright 2011 Wen Xue.
xue@11 7
xue@11 8 This program is free software; you can redistribute it and/or
xue@11 9 modify it under the terms of the GNU General Public License as
xue@11 10 published by the Free Software Foundation; either version 2 of the
xue@11 11 License, or (at your option) any later version.
xue@11 12 */
xue@1 13 #ifndef hsH
xue@1 14 #define hsH
xue@1 15
Chris@5 16 /**
Chris@5 17 \file hs.h - harmonic sinusoid model
xue@1 18
xue@1 19 Further reading: Wen X. and M. Sandler, "Sinusoid modeling in a harmonic context," in Proc. DAFx'07, Bordeaux, 2007.
xue@1 20 */
xue@1 21
xue@1 22 //---------------------------------------------------------------------------
Chris@2 23 #include <string.h>
xue@1 24 #include "arrayalloc.h"
xue@1 25 #include "align8.h"
xue@1 26 #include "fft.h"
Chris@2 27 #include "quickspec.h"
xue@11 28
xue@11 29 #ifndef __BORLANDC__
Chris@2 30 #include "tstream.h"
xue@11 31 #else
xue@11 32 #include <Classes.hpp>
xue@11 33 #endif
xue@1 34
xue@1 35 #define ATOM_LOCALANCHOR 1
xue@1 36 #define HS_CONSTF 1
xue@1 37 #define MAX_CAND 64
xue@1 38 #define STIFF_B_MAX 0.01
xue@1 39
xue@1 40 enum atomtype //type flags of an HS atom
xue@1 41 {
xue@1 42 atAnchor, //"anchor" is an atom whose validity is taken for granted, e.g. user input
xue@1 43 atPeak, //an atom whose frequency is an actual spectral peak
xue@1 44 atInfered, //an atom which has no spectral peak and whose frequency is inferred from other atoms
xue@1 45 atMuted, //an atom which is being muted
xue@1 46 atBuried //an atom which is buried in background noise
xue@1 47 };
xue@1 48
xue@1 49 struct atom //an atom of a harmonic sinusoid
xue@1 50 {
xue@1 51 double t; //time
xue@1 52 double s; //scale
xue@1 53 double f; //digital frequency
xue@1 54 double a; //amplitude
xue@1 55 double p; //phase angle
xue@1 56 int pin; //partial index
xue@1 57 atomtype type; //atom type
xue@1 58 int tags; //additional info on atom type
xue@1 59 float r1;
xue@1 60 };
xue@1 61
xue@1 62 struct candid //candidate atom
xue@1 63 {
xue@1 64 int p; //partial index
xue@1 65 double f; //frequency
xue@1 66 double df; //delta freqdel folk
xue@1 67 double s; //score in partial-sum
xue@1 68 int prev; //index of last partial f-df
xue@1 69 int type; //0: f0, 1: local maximum, 2: not a maxixum
xue@1 70 double ms;
xue@1 71 };
xue@1 72
xue@1 73 struct dsparams1 //argument structure for calling ds1()
xue@1 74 {
xue@1 75 double s; //score
xue@1 76 double lastene; //energy of last frame
xue@1 77 double currentacce; //energy of this frame, currently accumulated
xue@1 78 int p; //partial index
xue@1 79 int lastP; //number of efficient partials in last frame
xue@1 80 double* lastvfp; //amplitude estimates of partials at last frame
xue@1 81 };
xue@1 82
xue@1 83 struct NMResults //note match output structure
xue@1 84 {
xue@1 85 double* fp; //frequencies, in bins
xue@1 86 double* vfp; //amplitudes
xue@1 87 double* pfp; //phase angles
xue@1 88 atomtype* ptype; //atom types
xue@1 89 };
xue@1 90
xue@1 91 struct NMSettings //note match algorithm settings
xue@1 92 {
xue@1 93 double c[4]; //cosine-family window specifiers
xue@1 94 int M; //ditto
xue@1 95 double iH2; //ditto
xue@1 96 double hB; //spectral truncation half width
xue@1 97 int maxp; //maximal number of partials
xue@1 98 double maxB; //stiffness coefficient upper bound
xue@1 99 double epf; //frequency estimation error tolerance for LSE estimation
xue@1 100 double epf0; //input frequency error bound for harmonic grouping
xue@1 101 double delm; //frequency error bound for harmonic grouping
xue@1 102 double delp; //pitch jump upper bound
xue@1 103 double minf0; //minimal fundamental frequency
xue@1 104 double maxf0; //maximal fundamental frequency
xue@1 105 int pin0; //input partial index
xue@1 106 bool forcepin0; //force the peak nearest to input frequency as an atom
xue@1 107 bool pin0asanchor; //mark atom found near the input frequency as anchor
xue@1 108 int pcount; //number of "pinned" (anchor) partials
xue@1 109 int* pin; //partial indices of pinned partials
xue@1 110 double* pinf; //frequencies of pinned partials
xue@1 111 int* pinfr; //frame indices of pinned partials, used in multi-frame constant-pitch note match
xue@1 112 };
xue@1 113
xue@1 114
Chris@5 115 /**
xue@1 116 stiffcandid is the harmonic atom class used internally by harmonic grouping and tracking routines. Literally
xue@1 117 it means "candidate harmonic atoms on a stiff string model". The stiff string is the main harmonic model used
xue@1 118 by me for describing frequency relations between partials of a harmonic sound.
xue@1 119
xue@1 120 stiffcandid is superceded by TTempAtom class.
xue@1 121 */
xue@1 122
xue@1 123 class stiffcandid
xue@1 124 {
xue@1 125 public:
xue@1 126 int P; //number of partial estimates located
xue@1 127 int* p; //partial indices of located partials, sizeof(int)*P
xue@1 128 double* f; //frequencies of located partials, sizeof(double)*P
xue@1 129 double s; //score in partial-sum
xue@1 130 //{N; F, G}: the feasible polygonal area of (F, G) given the P partials, where F=F0*F0, G=F0*B
xue@1 131 int N;
xue@1 132 double* F; //sizeof(double)*N
xue@1 133 double* G; //sizeof(double)*N
xue@1 134
xue@1 135 stiffcandid(int Wid); //create empty with minimal info
xue@1 136 stiffcandid(int Wid, int ap, double af, double errf); //create empty with pitch range
xue@1 137 stiffcandid(int Wid, int ap, double af, double errf, double ds); //create with 1 atom
xue@1 138 stiffcandid(stiffcandid* prev, int ap, double af, double errf, double ds); //create by updating with new atom
xue@1 139 ~stiffcandid();
xue@1 140 };
xue@1 141
xue@1 142
Chris@5 143 /**
xue@1 144 THS is the data structure hosting a harmonic sinusoid representation. Its key members include the number
xue@1 145 of partials, number of frames, and all its atoms (sinusoid parameters of all partials at measurement points).
xue@1 146 */
xue@1 147 class THS
xue@1 148 {
xue@1 149 public:
xue@1 150 int Channel; //channel id: THS describes a harmonic sinusoid in single channel
xue@1 151 int M; //number of partials
xue@1 152 int Fr; //number of frames
xue@1 153 atom** Partials; //atoms, [M][Fr]
xue@1 154
xue@1 155 int* BufM[128]; //a buffer for algorithmic use
xue@1 156
xue@1 157 int isconstf; //constant frequencies flag
xue@1 158
xue@1 159 double** startamp;//onset amplifiers, optional
xue@1 160 int st_start; //position of the first onset amplifying point
xue@1 161 int st_offst; //interval of onset amplifying points
xue@1 162 int st_count; //number of onset amplifying points
xue@1 163
xue@1 164 //constructors and destructor
xue@1 165 THS();
xue@1 166 THS(int aM, int aFr);
xue@1 167 THS(THS* HS);
xue@1 168 THS(THS* HS, double start, double end);
xue@1 169 ~THS();
xue@1 170
xue@1 171 int StartPos(); //start position
xue@1 172 int EndPos(); //end position
xue@1 173 int EndPosEx(); //extended end position
xue@1 174 int StdOffst(); //hop size
xue@1 175
xue@1 176 void ClearBufM(); //free buffers registered in BufM[]
xue@1 177 void Resize(int aM, int aFr, bool copydata=false, bool forcealloc=false); //change size (M or Fr)
xue@1 178
xue@1 179 //I/O routines
xue@1 180 int WriteHdrToStream(TStream* Stream);
xue@1 181 int ReadHdrFromStream(TStream* Stream);
xue@1 182 int WriteAtomToStream(TStream* Stream, atom* atm);
xue@1 183 int ReadAtomFromStream(TStream* Stream, atom* atm);
xue@1 184 int WriteToStream(TStream* Stream);
xue@1 185 int ReadFromStream(TStream* Stream);
xue@1 186 };
xue@1 187
xue@1 188
Chris@5 189 /**
xue@1 190 TPolygon is a polygon class. This class itself does not enforce convexness. However, when used for solving
xue@1 191 the stiff string model, all polygons are convex, as they are the results of current a first convex polygon
xue@1 192 by straight lines.
xue@1 193
xue@1 194 For the convenience of computation, the sequence of vertices are arranged so that they come in clockwise
xue@1 195 order starting from the leftmost (smallest x coordinate) vertex; in case two vertices are both leftmost
xue@1 196 the upper (larger y coordinate) one is placed at the start and the lower one is placed at the end.
xue@1 197 */
xue@1 198
xue@1 199 class TPolygon
xue@1 200 {
xue@1 201 public:
xue@1 202 int N; //number of vertices (equals number of edges)
xue@1 203 double* X; //x-coordinates of vertices
xue@1 204 double* Y; //y-coordinates of vertices
xue@1 205 TPolygon(int cap);
xue@1 206 TPolygon(int cap, TPolygon* R);
xue@1 207 ~TPolygon();
xue@1 208 };
xue@1 209
xue@1 210
Chris@5 211 /**
xue@1 212 TTempAtom is an atom class within the stiff-stirng harmonic atom context used internally by harmonic
xue@1 213 grouping and tracking routines. Literally it means "a temporary atom", and truly it hosts most info
xue@1 214 one expects of a potential atom. TTempAtom replaces stiffcandid class in harmonic sinusoid group and
xue@1 215 tracking algorithms, due to the advanges that it carries atom information (frequency, amplitude, etc.)
xue@1 216 as well as harmonic atom information (link to other atom, the F-G polygon), and is therefore both an
xue@1 217 individual atom and a harmonic atom containing all atoms tracked down through the linked list Prev.
xue@1 218 */
xue@1 219
xue@1 220 class TTempAtom
xue@1 221 {
xue@1 222 public:
xue@1 223 int pind; //partial index
xue@1 224 double f; //frequency
xue@1 225 double a; //amplitude
xue@1 226 double s; //scale
xue@1 227 double rsr; //residue-sinusoid ratio
xue@1 228 TTempAtom* Prev; //previous atom
xue@1 229 TPolygon *R; //F-G polygon for harmonic group
xue@1 230 union {double acce; int tag[2];};
xue@1 231
xue@1 232 TTempAtom(double af, double ef, double maxB); //create empty with frequency range
xue@1 233 TTempAtom(int apin, double af, double ef, double maxB); //create empty with frequency range
xue@1 234 TTempAtom(TPolygon* AR, double delf1, double delf2, double minf); //create empty with extended R
xue@1 235 TTempAtom(int apind, double af, double ef, double aa, double as, double maxB); //create with one partial
xue@1 236 TTempAtom(TTempAtom* APrev, bool DupR); //create duplicate
xue@1 237 TTempAtom(TTempAtom* APrev, int apind, double af, double ef, double aa, double as, bool updateR=true); //duplicate and add one partial
xue@1 238 ~TTempAtom();
xue@1 239 };
xue@1 240
xue@1 241 //--internal function--------------------------------------------------------
xue@1 242 double ds0(double, void*); //a score function, internal use only
xue@1 243
xue@1 244 //--general polygon routines-------------------------------------------------
xue@1 245 void areaandcentroid(double& A, double& cx, double& cy, int N, double* x, double* y); //compute area and centroid
xue@1 246 void cutcvpoly(int& N, double* x, double* y, double A, double B, double C, bool protect=false); //sever polygon by line
xue@1 247 double maximalminimum(double& x, double& y, int N, double* sx, double* sy); //maximum inscribed circle
xue@1 248
xue@1 249 //--F-G polygon routines-----------------------------------------------------
xue@1 250 void CutR(TPolygon* R, int apind, double af, double ef, bool protect=false);
xue@1 251 void ExBStiff(double& Bmin, double& Bmax, int N, double* F, double* G);
xue@1 252 void ExFmStiff(double& Fmin, double& Fmax, int m, int N, double* F, double* G);
xue@1 253 void ExtendR(TPolygon* R, double delf1, double delf2, double minf);
xue@1 254 void InitializeR(TPolygon* R, double af, double ef, double maxB);
xue@1 255 void InitializeR(TPolygon* R, int apind, double af, double ef, double maxB);
xue@1 256
xue@1 257 //--internal structure conversion routines-----------------------------------
xue@11 258 void AtomsToPartials(int k, atom* part, int& M, int& Fr, atom**& partials, int offst);
xue@1 259 int NMResultToAtoms(int M, atom* HP, int t, int wid, NMResults results);
xue@1 260 int NMResultToPartials(int M, int fr, atom** Partials, int t, int wid, NMResults results);
xue@1 261
xue@1 262 //--batch sinusoid estimation routines---------------------------------------
xue@1 263 double PeakShapeC(double f, int Fr, int N, cdouble** x, int B, int M, double* c, double iH2);
xue@1 264 double PeakShapeC(double f, int Fr, int N, cfloat** x, int B, int M, double* c, double iH2);
xue@1 265 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);
xue@1 266 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);
xue@1 267
xue@1 268 //--harmonic atom detection (harmonic grouping) routines---------------------
xue@1 269 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
xue@1 270 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
xue@1 271 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
xue@1 272 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
xue@1 273
xue@1 274 //--harmonic sinusoid tracking routines--------------------------------------
xue@1 275 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)
xue@1 276 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
xue@1 277 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
xue@1 278 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
xue@1 279 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()
xue@1 280
xue@1 281 //--harmonic sinusoid synthesis routines-------------------------------------
xue@1 282 double* SynthesisHS(int pm, int pfr, atom** partials, int& dst, int& den, bool* terminatetag=0);
xue@11 283 double* SynthesisHS(THS* HS, int& dst, int& den, bool* terminatetag=0);
xue@1 284 double* SynthesisHS2(int M, int Fr, atom** partials, int& dst, int& den, bool* terminatetag=0);
xue@1 285 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);
xue@1 286 double* SynthesisHSp(THS* HS, int& dst, int& den);
xue@1 287
xue@1 288 //--other functions----------------------------------------------------------
xue@1 289 void ReEstHS1(THS* HS, __int16* Data16); //reestimation of HS
xue@1 290
xue@1 291 #endif