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 SinEstH
|
xue@1
|
14 #define SinEstH
|
xue@1
|
15
|
Chris@5
|
16 /**
|
Chris@5
|
17 \file sinest.h - sinusoid estimation algorithms
|
xue@1
|
18 */
|
xue@1
|
19
|
xue@1
|
20
|
Chris@2
|
21 #include <string.h>
|
xue@1
|
22 #include "xcomplex.h"
|
xue@1
|
23 #include "arrayalloc.h"
|
xue@1
|
24 #include "matrix.h"
|
xue@1
|
25 #ifdef I
|
xue@1
|
26 #undef I
|
xue@1
|
27 #endif
|
xue@1
|
28
|
xue@1
|
29 //--since function derivative------------------------------------------------
|
xue@1
|
30 double ddsincd_unn(double x, int N);
|
xue@1
|
31 double dsincd_unn(double x, int N);
|
xue@1
|
32
|
xue@1
|
33 //--window spectrum and derivatives------------------------------------------
|
xue@1
|
34 cdouble* Window(cdouble* x, double f, int N, int M, double* c, int K1, int K2);
|
xue@1
|
35 void dWindow(cdouble* dx, cdouble* x, double f, int N, int M, double* c, int K1, int K2);
|
xue@1
|
36 void ddWindow(cdouble* ddx, cdouble* dx, cdouble* x, double f, int N, int M, double* c, int K1, int K2);
|
xue@1
|
37
|
xue@1
|
38 //--spectral projection routines---------------------------------------------
|
xue@1
|
39 cdouble IPWindowC(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2);
|
xue@1
|
40
|
xue@1
|
41 double IPWindow(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2, bool returnamplitude);
|
xue@1
|
42 double IPWindow(double f, void* params);
|
xue@1
|
43 double ddIPWindow(double f, void* params);
|
xue@1
|
44 double ddIPWindow(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2, double& dipwindow, double& ipwindow);
|
xue@1
|
45
|
xue@1
|
46 double sIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, cdouble* ej2ph=0);
|
xue@1
|
47 double sIPWindow(double f, void* params);
|
xue@1
|
48 double dsIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& sip);
|
xue@1
|
49 double dsIPWindow(double f, void* params);
|
xue@1
|
50 double ddsIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& dsip, double& sip);
|
xue@1
|
51 double ddsIPWindow(double f, void* params);
|
xue@1
|
52 double ddsIPWindow_unn(double f, cdouble* x, int N, int M, double* c, int K1, int K2, double& dsipwindow, double& sipwindow, cdouble* w_unn=0);
|
xue@1
|
53
|
xue@1
|
54 double sIPWindowC(double f, int L, double offst_rel, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, cdouble* ej2ph=0);
|
xue@1
|
55 double sIPWindowC(double f, void* params);
|
xue@1
|
56 double dsIPWindowC(double f, int L, double offst_rel, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& sip);
|
xue@1
|
57 double dsIPWindowC(double f, void* params);
|
xue@1
|
58 double ddsIPWindowC(double f, int L, double offst_rel, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& dsip, double& sip);
|
xue@1
|
59 double ddsIPWindowC(double f, void* params);
|
xue@1
|
60
|
xue@1
|
61 //--least-square sinusoid estimation routines--------------------------------
|
xue@1
|
62 double LSESinusoid(cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf=1e-6);
|
xue@1
|
63 void LSESinusoid(double& f, cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf=1e-6);
|
xue@1
|
64 double LSESinusoid(int f1, int f2, cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf);
|
xue@1
|
65 int LSESinusoid(double& f, double f1, double f2, cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf);
|
xue@1
|
66 double LSESinusoidMP(double& f, double f1, double f2, cdouble** x, int Fr, int N, double B, int M, double* c, double iH2, double* a, double* ph, double epf);
|
xue@1
|
67
|
xue@1
|
68 //--multi-sinusoid spectral projection routines------------------------------
|
xue@1
|
69 void IPMulti(int I, double* f, cdouble* lmd, cdouble* x, int Wid, int K1, int K2, int M, double* c, double eps=0);
|
xue@1
|
70 void IPMulti(int I, double* f, cdouble* lmd, cfloat* x, int Wid, int K1, int K2, int M, double* c, double eps=0, double* sens=0, double* r1=0);
|
xue@1
|
71 void IPMultiSens(int I, double* f, int Wid, int K1, int K2, int M, double* c, double* sens, double eps=0);
|
xue@1
|
72 double IPMulti(int I, double* f, cdouble* lmd, cdouble* x, int Wid, int M, double* c, double iH2, int B);
|
xue@1
|
73 double IPMulti_Direct(int I, double* f, double* ph, double* a, cdouble* x, int Wid, int M, double* c, double iH2, int B);
|
xue@1
|
74 double IPMulti_GS(int I, double* f, double* ph, double* a, cdouble* x, int Wid, int M, double* c, double iH2, int B, double** L=0, double** Q=0);
|
xue@1
|
75 cdouble* IPMulti(int I, int J, double* f, double* ph, double* a, cdouble* x, int Wid, int M, double* c, cdouble** wt=0, cdouble** Q=0, double** L=0, MList* RetList=0);
|
xue@1
|
76
|
xue@1
|
77 //--dual-sinusoid spectral projection routines-------------------------------
|
xue@1
|
78 double WindowDuo(double df, int N, double* d, int M, cdouble* w);
|
xue@1
|
79 double ddWindowDuo(double df, int N, double* d, int M, double& dwindow, double& window, cdouble* w);
|
xue@1
|
80 double sIPWindowDuo(double f1, double f2, cdouble* x, int N, double* c, double* d, int M, double iH2, int K1, int K2, cdouble& lmd1, cdouble& lmd2);
|
xue@1
|
81 double sIPWindowDuo(double f2, void* params);
|
xue@1
|
82 void ddsIPWindowDuo(double* ddsip2, double f1, double f2, cdouble* x, int N, double* c, double* d, int M, double iH2, int K1, int K2, cdouble& lmd1, cdouble& lmd2);
|
xue@1
|
83 double ddsIPWindowDuo(double f2, void* params);
|
xue@1
|
84 int LSEDuo(double& f2, double fmin, double fmax, double f1, cdouble* x, int N, double B, double* c, double* d, int M, double iH2, cdouble& r1, cdouble &r2, double epf);
|
xue@1
|
85
|
xue@1
|
86 //--time-frequency reassignment----------------------------------------------
|
xue@1
|
87 void TFReas(double& f, double& t, double& fslope, int Wid, cdouble* data, double* win, double* dwin, double* ddwin, double* plogaslope=0);
|
xue@1
|
88 void TFReas(double& f, double t, double& a, double& ph, double& fslope, int Wid, cdouble* data, double* w, double* dw, double* ddw, double* win=0);
|
xue@1
|
89
|
xue@1
|
90 //--additive and multiplicative reestimation routines------------------------
|
xue@1
|
91 typedef double (*TBasicAnalyzer)(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, __int16* ref, int reserved, bool LogA);
|
xue@1
|
92 void AdditiveUpdate(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA=false);
|
xue@1
|
93 void AdditiveAnalyzer(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, __int16* ref, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA=false);
|
xue@1
|
94 void MultiplicativeUpdate(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA=false);
|
xue@1
|
95 void MultiplicativeAnalyzer(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, __int16* ref, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA=false);
|
xue@1
|
96 void MultiplicativeUpdateF(double* fs, double* as, double* phs, __int16* x, int Fr, int frst, int fren, int Wid, int Offst);
|
xue@1
|
97
|
xue@1
|
98 void ReEstFreq(int FrCount, int Wid, int Offst, double* x, double* fbuf, double* abuf, double* pbuf, double* win, int M, double* c, double iH2, cdouble* w, cdouble* xc, cdouble* xs, double* ps, double* fa, double* fb, double* fc, double* fd, double* ns, int* Wids=0);
|
xue@1
|
99 void ReEstFreq_2(int FrCount, int Wid, int Offst, double* x, double* fbuf, double* abuf, double* pbuf, double* win, int M, double* c, double iH2, cdouble* w, cdouble* xc, cdouble* xs, double* f3, double* f2, double* f1, double* f0, double* ns);
|
xue@1
|
100 void ReEstFreqAmp(int FrCount, int Wid, int Offst, double* x, double* fbuf, double* abuf, double* pbuf, double* win, int M, double* c, double iH2, cdouble* w, cdouble* xc, cdouble* xs, double* ps, double* as, double* fa, double* fb, double* fc, double* fd, double* aa, double* ab, double* ac, double* ad, double* ns, int* Wids=0);
|
xue@1
|
101 int Reestimate2(int FrCount, int Wid, int Offst, double* win, int M, double* c, double iH2, double* x, double* ae, double* fe, double* pe, double* aret, double* fret, double *pret, int maxiter, int* Wids=0);
|
xue@1
|
102
|
xue@1
|
103 //--local derivative algorithms - DAFx09-------------------------------------
|
xue@1
|
104 void Derivative(int M, double (**h)(double t, void*), double (**dh)(double t, void*), cdouble* r, int p0s, int* p0, int q0s, int* q0, int Wid, double* s, double** win, double omg, void* harg);
|
xue@1
|
105 void DerivativeLS(int K, int M, double (**h)(double t, void* harg), double (**dh)(double t, void* harg), cdouble* r, int p0s, int* p0, int q0s, int* q0, int Wid, double* s, double** win, double omg, void* harg, bool r0=false);
|
xue@1
|
106 void DerivativeLS(int Fr, int K, int M, double (**h)(double t, void* harg), double (**dh)(double t, void* harg), cdouble* r, int p0s, int* p0, int q0s, int* q0, int Wid, double* s, double** win, double omg, void* harg, bool r0=false);
|
xue@1
|
107
|
xue@1
|
108 //--the Abe-Smith estimator--------------------------------------------------
|
xue@1
|
109 void TFAS05(double& f, double& t, double& a, double& ph, double& aesp, double& fslope, int Wid, double* data, double* w, double res=1);
|
xue@1
|
110 void TFAS05_enh(double& f, double& t, double& a, double& ph, double& aesp, double& fslope, int Wid, double* data, double* w, double res=1);
|
xue@1
|
111 void TFAS05_enh(double& f, double& t, double& a, double& ph, int Wid, double* data, double* w, double res=1);
|
xue@1
|
112
|
xue@1
|
113 //--piecewise derivative algorithms and tools--------------------------------
|
xue@1
|
114 void DerivativePiecewise(int N, cdouble* aita, int L, double* f, int T, cdouble* s, double*** A, int M, double** h, int I, cdouble** u, cdouble** du, int endmode=0, cdouble* ds=0);
|
xue@1
|
115 void DerivativePiecewise2(int Np, double* p, int Nq, double* q, int L, double* f, int T, cdouble* s, double*** A, double*** B, int M, double** h, int I, cdouble** u, cdouble** du, int endmode=0, cdouble* ds=0);
|
xue@1
|
116 void DerivativePiecewise3(int Np, double* p, int Nq, double* q, int L, double* f, int T, cdouble* s, double*** DA, double*** B, int M, double** h, int I, cdouble** u, cdouble** du, int endmode=0, cdouble* ds=0, double** dh=0);
|
xue@1
|
117 void seth(int M, int T, double**& h, MList* mlist);
|
xue@1
|
118 void setdh(int M, int T, double**& dh, MList* mlist);
|
xue@1
|
119 void setdih(int M, int T, double**& dih, MList* mlist);
|
xue@1
|
120 void setu(int I, int Wid, cdouble**& u, cdouble**& du, int WinOrder=2, MList* mlist=0);
|
xue@1
|
121 void ssALinearSpline(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
122 void ssACubicHermite(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
123 void ssACubicSpline(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
124 void ssLinearSpline(int L, int T, int M, int &N, double** &h, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
125 void ssCubicHermite(int L, int T, int M, int& N, double** &h, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
126 void ssCubicSpline(int L, int T, int M, int& N, double** &h, double*** &A, MList* mlist, int mode=0);
|
xue@1
|
127 void DerivativePiecewiseI(cdouble* aita, int L, double* f, int T, cdouble* s, int M, void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssmode=0, int WinOrder=2, int I=2, int endmode=0, cdouble* ds=0);
|
xue@1
|
128 void DerivativePiecewiseII(double* p, double* q, int L, double* f, int T, cdouble* s, int M, void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssAmode, void (*SpecifyB)(int L, int T, int M, int &N, double*** &B, MList* mlist, int mode), int ssBmode, int WinOrder=2, int I=2, int endmode=0, cdouble* ds=0);
|
xue@1
|
129 void DerivativePiecewiseIII(double* p, double* q, int L, double* f, int T, cdouble* s, int M, void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssAmode, void (*SpecifyB)(int L, int T, int M, int &N, double*** &B, MList* mlist, int mode), int ssBmode, int WinOrder=2, int I=2, int endmode=0, cdouble* ds=0);
|
xue@1
|
130 double AmpPhCorrectionExpA(cdouble* s2, int N, cdouble* aita, int L, int T, cdouble* sre, int M, double** h, double** dih, double*** A, void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int WinOrder);
|
xue@1
|
131
|
xue@1
|
132 //--local derivative algorithms - general------------------------------------
|
Chris@5
|
133 /**
|
xue@1
|
134 template DerivativeLSv: local derivative algorithm for estimating time-varying sinusoids, "v" version,
|
xue@1
|
135 i.e. using tuned test functions.
|
xue@1
|
136
|
xue@1
|
137 In: s[Wid]: waveform data
|
xue@1
|
138 v[I][Wid], dv[I][Wid]: test functions and their derivatives
|
xue@1
|
139 h[M+1][Wid]: basis functions
|
xue@1
|
140 p0[p0s], q0[q0s]: zero-constraints, i.e. Re(lmd[p0[*]]) and Im(lmd[q0[*]]) are constrained zero.
|
xue@1
|
141 Out: lmd[1:M]: coefficients of h[1:M].
|
xue@1
|
142
|
xue@1
|
143 Returns inner product of s and v[0].
|
xue@1
|
144 */
|
xue@1
|
145 template<class Ts>cdouble DerivativeLSv(int Wid, Ts* s, int I, cdouble** v, cdouble** dv, int M, double **h, cdouble* lmd, int p0s, int* p0, int q0s, int* q0)
|
xue@1
|
146 {
|
xue@1
|
147 int Kr=M*2-p0s-q0s; //number of real unknowns apart from p0 and q0
|
xue@1
|
148 if (I<ceil(Kr/2.0)) throw("insufficient test functions"); //Kr/2 complex equations are needed to solve the unknowns
|
xue@1
|
149
|
xue@1
|
150 //ind maps the real unknowns to their positions in physical buffer
|
xue@1
|
151 //uind maps them back
|
xue@1
|
152 int *uind=new int[Kr], *ind=new int[2*M];
|
xue@1
|
153 memset(ind, 0, sizeof(int)*2*M);
|
xue@1
|
154 for (int p=0; p<p0s; p++) ind[2*(p0[p]-1)]=-1;
|
xue@1
|
155 for (int q=0; q<q0s; q++) ind[2*(q0[q]-1)+1]=-1;
|
xue@1
|
156
|
xue@1
|
157 {
|
xue@1
|
158 int p=0, up=0; while (p<2*M){if (ind[p]>=0){uind[up]=p; ind[p]=up; up++;} p++;}
|
xue@1
|
159 if (up!=Kr) throw("");
|
xue@1
|
160 }
|
xue@1
|
161
|
xue@1
|
162 cdouble* sv1=new cdouble[I];
|
xue@1
|
163 for (int i=0; i<I; i++) sv1[i]=-Inner(Wid, s, dv[i]);
|
xue@1
|
164
|
xue@1
|
165 double** Allocate2(double, 2*I, Kr, A);
|
xue@1
|
166 for (int m=1; m<=M; m++)
|
xue@1
|
167 for (int i=0; i<I; i++)
|
xue@1
|
168 {
|
xue@1
|
169 int lind;
|
xue@1
|
170 cdouble shv=Inner(Wid, s, h[m], v[i]);
|
xue@1
|
171 if ((lind=ind[2*(m-1)])>=0)
|
xue@1
|
172 {
|
xue@1
|
173 A[2*i][lind]=shv.x;
|
xue@1
|
174 A[2*i+1][lind]=shv.y;
|
xue@1
|
175 }
|
xue@1
|
176 if ((lind=ind[2*m-1])>=0)
|
xue@1
|
177 {
|
xue@1
|
178 A[2*i][lind]=-shv.y;
|
xue@1
|
179 A[2*i+1][lind]=shv.x;
|
xue@1
|
180 }
|
xue@1
|
181 }
|
xue@1
|
182
|
xue@1
|
183 double* pq=new double[Kr];
|
xue@1
|
184 if (2*I==Kr) GECP(Kr, pq, A, (double*)sv1);
|
xue@1
|
185 else LSLinear(2*I, Kr, pq, A, (double*)sv1);
|
xue@1
|
186
|
xue@1
|
187 memset(lmd, 0, sizeof(double)*(M+1)*2);
|
xue@1
|
188 for (int k=0; k<Kr; k++) ((double*)(&lmd[1]))[uind[k]]=pq[k];
|
xue@1
|
189
|
xue@1
|
190 cdouble result=Inner(Wid, s, v[0]);
|
xue@1
|
191 delete[] pq;
|
xue@1
|
192 delete[] sv1;
|
xue@1
|
193 delete[] uind;
|
xue@1
|
194 delete[] ind;
|
xue@1
|
195 DeAlloc2(A);
|
xue@1
|
196 return result;
|
xue@1
|
197 }//DerivativeLSv
|
xue@1
|
198
|
Chris@5
|
199 /**
|
xue@1
|
200 template DerivativeLS: local derivative algorithm for estimating time-varying sinusoids, "u" version,
|
xue@1
|
201 i.e. using base-band test functions.
|
xue@1
|
202
|
xue@1
|
203 In: s[Wid]: waveform data
|
xue@1
|
204 u[I][Wid], du[I][Wid]: base-band test functions and their derivatives
|
xue@1
|
205 omg: angular frequency onto which u[I] and du[I] are modulated to give the test functions
|
xue@1
|
206 h[M+1][Wid]: basis functions
|
xue@1
|
207 p0[p0s], q0[q0s]: zero-constraints, i.e. Re(lmd[p0[*]]) and Im(lmd[q0[*]]) are constrained zero.
|
xue@1
|
208 Out: lmd[1:M]: coefficients of h[1:M].
|
xue@1
|
209
|
xue@1
|
210 Returns inner product of s and v[0].
|
xue@1
|
211 */
|
xue@1
|
212 template<class Ts, class Tu>cdouble DerivativeLS(int Wid, Ts* s, int I, double omg, Tu** u, Tu** du, int M, double **h, cdouble* lmd, int p0s, int* p0, int q0s, int* q0)
|
xue@1
|
213 {
|
xue@1
|
214 cdouble** Allocate2(cdouble, I, Wid, v);
|
xue@1
|
215 cdouble** Allocate2(cdouble, I, Wid, dv);
|
xue@1
|
216 cdouble jomg=cdouble(0, omg); int hWid=Wid/2;
|
xue@1
|
217 for (int c=0; c<Wid; c++)
|
xue@1
|
218 {
|
xue@1
|
219 double t=c-hWid;
|
xue@1
|
220 cdouble rot=cdouble(1).rotate(omg*t);
|
xue@1
|
221 for (int i=0; i<I; i++) v[i][c]=u[i][c]*rot;
|
xue@1
|
222 for (int i=0; i<I; i++) dv[i][c]=du[i][c]*rot+jomg*v[i][c];
|
xue@1
|
223 }
|
xue@1
|
224 cdouble result=DerivativeLSv(Wid, s, I, v, dv, M, h, lmd, p0s, p0, q0s, q0);
|
xue@1
|
225 DeAlloc2(v); DeAlloc2(dv);
|
xue@1
|
226 return result;
|
xue@1
|
227 }//DerivativeLS
|
xue@1
|
228
|
Chris@5
|
229 /**
|
xue@1
|
230 template DerivativeLS_AmpPh: amplitude and phase estimation in the local derivative algorithm, "u"
|
xue@1
|
231 version
|
xue@1
|
232
|
xue@1
|
233 In: sv0: inner product of signal s[Wid] and test function v0
|
xue@1
|
234 u0[Wid], omg: base-band test function and carrier frequency used for computing v0[]
|
xue@1
|
235 integr_h[M+1][Wid]: integrals of basis functions
|
xue@1
|
236
|
xue@1
|
237 Returns coefficient to integr_h[0]=1.
|
xue@1
|
238 */
|
xue@1
|
239 template<class Tu>cdouble DerivativeLS_AmpPh(int Wid, int M, double** integr_h, cdouble* lmd, double omg, Tu* u0, cdouble sv0)
|
xue@1
|
240 {
|
xue@1
|
241 cdouble e0=0; double hWid=Wid/2.0;
|
xue@1
|
242 for (int n=0; n<Wid; n++)
|
xue@1
|
243 {
|
xue@1
|
244 cdouble expo=0;
|
xue@1
|
245 for (int m=1; m<=M; m++) expo+=lmd[m]*integr_h[m][n];
|
xue@1
|
246 if (expo.x>300) expo.x=300;
|
xue@1
|
247 else if (expo.x<-300) expo.x=-300;
|
xue@1
|
248 e0+=exp(expo)**(cdouble(u0[n]).rotate(omg*(n-hWid)));
|
xue@1
|
249 }
|
xue@1
|
250 return log(sv0/e0);
|
xue@1
|
251 }//DerivativeLS_AmpPh
|
xue@1
|
252
|
Chris@5
|
253 /**
|
xue@1
|
254 template DerivativeLS_AmpPh: amplitude and phase estimation in the local derivative algorithm, "u"
|
xue@1
|
255 version.
|
xue@1
|
256
|
xue@1
|
257 In: s[Wid]: waveform data
|
xue@1
|
258 u0[Wid], omg: base-band test function and carrier frequency used for computing v0[]
|
xue@1
|
259 integr_h[M+1][Wid]: integrals of basis functions
|
xue@1
|
260
|
xue@1
|
261 Returns coefficient to integr_h[0]=1.
|
xue@1
|
262 */
|
xue@1
|
263 template<class Tu, class Ts>cdouble DerivativeLS_AmpPh(int Wid, int M, double** integr_h, cdouble* lmd, double omg, Tu* u0, Ts* s)
|
xue@1
|
264 {
|
xue@1
|
265 cdouble ss0=0, e0=0; double hWid=Wid/2.0;
|
xue@1
|
266 for (int n=0; n<Wid; n++)
|
xue@1
|
267 {
|
xue@1
|
268 cdouble expo=0;
|
xue@1
|
269 for (int m=1; m<=M; m++) expo+=lmd[m]*integr_h[m][n];
|
xue@1
|
270 if (expo.x>300) expo.x=300;
|
xue@1
|
271 else if (expo.x<-300) expo.x=-300;
|
xue@1
|
272 e0+=~exp(expo)*abs(u0[n]);
|
xue@1
|
273 ss0+=s[n]**exp(expo)*abs(u0[n]);
|
xue@1
|
274 }
|
xue@1
|
275 return log(ss0/e0);
|
xue@1
|
276 }//DerivativeLS_AmpPh
|
xue@1
|
277
|
xue@1
|
278 cdouble DerivativeLSv_AmpPh(int, int, double**, cdouble*, cdouble*, cdouble); //the "v" version is implemented as a normal function in SinEst.cpp.
|
xue@1
|
279
|
Chris@5
|
280 /**
|
xue@1
|
281 template DerivativeLSv: local derivative algorithm for estimating time-varying sinusoids, "v" version.
|
xue@1
|
282
|
xue@1
|
283 In: s[Wid]: waveform data
|
xue@1
|
284 v[I][Wid], dv[I][Wid]: test functions and their derivatives
|
xue@1
|
285 h[M+1][Wid], integr_h[M+1][Wid]: basis functions and their integrals
|
xue@1
|
286 p0[p0s], q0[q0s]: zero-constraints, i.e. Re(lmd[p0[*]]) and Im(lmd[q0[*]]) are constrained zero.
|
xue@1
|
287 Out: lmd[M+1]: coefficients of h[M+1], including lmd[0].
|
xue@1
|
288
|
xue@1
|
289 No return value.
|
xue@1
|
290 */
|
xue@1
|
291 template<class Ts> void DerivativeLSv(int Wid, Ts* s, int I, cdouble** v, cdouble** dv, int M, double **h, double **integr_h, cdouble* lmd, int p0s, int* p0, int q0s, int* q0)
|
xue@1
|
292 {
|
xue@1
|
293 cdouble sv0=DerivativeLSv(Wid, s, I, v, dv, M, h, lmd, p0s, p0, q0s, q0);
|
xue@1
|
294 lmd[0]=DerivativeLSv_AmpPh(Wid, M, integr_h, lmd, v[0], sv0);
|
xue@1
|
295 }//DerivativeLSv_AmpPh
|
xue@1
|
296
|
Chris@5
|
297 /**
|
Chris@5
|
298 template DerivativeLSv: local derivative algorithm for estimating time-varying sinusoids, "u" version.
|
xue@1
|
299
|
xue@1
|
300 In: s[Wid]: waveform data
|
xue@1
|
301 u[I][Wid], du[I][Wid]: base-band test functions and their derivatives
|
xue@1
|
302 omg: angular frequency onto which u[I] and du[I] are modulated to give the test functions
|
xue@1
|
303 h[M+1][Wid], integr_h[M+1][Wid]: basis functions and their integrals
|
xue@1
|
304 p0[p0s], q0[q0s]: zero-constraints, i.e. Re(lmd[p0[*]]) and Im(lmd[q0[*]]) are constrained zero.
|
xue@1
|
305 Out: lmd[M+1]: coefficients of h[M+1], including lmd[0].
|
xue@1
|
306
|
xue@1
|
307 No return value.
|
xue@1
|
308 */
|
xue@1
|
309 template<class Ts, class Tu>void DerivativeLS(int Wid, Ts* s, int I, double omg, Tu** u, Tu** du, int M, double **h, double **integr_h, cdouble* lmd, int p0s, int* p0, int q0s, int* q0)
|
xue@1
|
310 {
|
xue@1
|
311 cdouble sv0=DerivativeLS(Wid, s, I, omg, u, du, M, h, lmd, p0s, p0, q0s, q0);
|
xue@1
|
312 lmd[0]=DerivativeLS_AmpPh(Wid, M, integr_h, lmd, omg, u[0], s); //sv0);
|
xue@1
|
313 }//DerivativeLSv
|
xue@1
|
314
|
Chris@5
|
315 /**
|
xue@1
|
316 template CosineWindows: generates the Hann^(K/2) window and its L-1 derivatives as Result[L][Wid+1]
|
xue@1
|
317
|
xue@1
|
318 In: K, L, Wid
|
xue@1
|
319 Out: w[L][Wid+1]: Hann^(K/2) window function and its derivatives up to order L-1
|
xue@1
|
320
|
xue@1
|
321 Returns pointer to w. w is created anew if w=0 is specified on start.
|
xue@1
|
322 */
|
xue@1
|
323 template<class T>T** CosineWindows(int K, int Wid, T **w, int L=0)
|
xue@1
|
324 {
|
xue@1
|
325 if (L<=0) L=K;
|
xue@1
|
326 if (!w) {Allocate2(T, L, Wid+1, w);}
|
xue@1
|
327 memset(w[0], 0, sizeof(T)*L*(Wid+1));
|
xue@1
|
328 int hWid=Wid/2, dWid=Wid*2;
|
xue@1
|
329 double *s=new double[dWid+hWid], *c=&s[hWid]; //s[n]=sin(pi*n/N), n=0, ..., 2N-1
|
xue@1
|
330 double *C=new double[K+2], *lK=&C[K/2+1], piC=M_PI/Wid;
|
xue@1
|
331 //C[i]=C(K, i)(-1)^i*2^(-K+1), the combination number, i=0, ..., K/2
|
xue@1
|
332 //ik[i]=(K-2i)^k*(M_PI/Wid)^k, i=0, ..., K/2
|
xue@1
|
333 //calculate C(K,i)(-1)^i*2^(-K+1)
|
xue@1
|
334 C[0]=1.0/(1<<(K-1)); double lC=C[0]; for (int i=1; i+i<=K; i++){lC=lC*(K-i+1)/i; C[i]=(i%2)?(-lC):lC;}
|
xue@1
|
335 //calculate sin/cos functions
|
xue@1
|
336 for (int n=0; n<dWid; n++) s[n]=sin(n*piC); memcpy(&s[dWid], s, sizeof(double)*hWid);
|
xue@1
|
337 for (int k=0; k<L; k++)
|
xue@1
|
338 {
|
xue@1
|
339 if (k==0) for (int i=0; i+i<K; i++) lK[i]=C[i];
|
xue@1
|
340 else for (int i=0; i+i<K; i++) lK[i]*=(K-2*i)*piC;
|
xue@1
|
341
|
xue@1
|
342 if ((K-k)%2) //K-k is odd
|
xue@1
|
343 {
|
xue@1
|
344 for (int i=0; i+i<K; i++) for (int n=0; n<=Wid; n++) w[k][n]+=lK[i]*s[(K-2*i)*n%dWid];
|
xue@1
|
345 if ((K-k-1)/2%2) for (int n=0; n<=Wid; n++) w[k][n]=-w[k][n];
|
xue@1
|
346 }
|
xue@1
|
347 else
|
xue@1
|
348 {
|
xue@1
|
349 for (int i=0; i+i<K; i++) for (int n=0; n<=Wid; n++) w[k][n]+=lK[i]*c[(K-2*i)*n%dWid];
|
xue@1
|
350 if ((K-k)/2%2) for (int n=0; n<=Wid; n++) w[k][n]=-w[k][n];
|
xue@1
|
351 }
|
xue@1
|
352 }
|
xue@1
|
353 if (K%2==0){double tmp=C[K/2]*0.5; if (K/2%2) tmp=-tmp; for (int n=0; n<=Wid; n++) w[0][n]+=tmp;}
|
xue@1
|
354 delete[] s; delete[] C;
|
xue@1
|
355 return w;
|
xue@1
|
356 }//CosineWindows
|
xue@1
|
357
|
xue@1
|
358
|
xue@1
|
359 #endif
|