comparison SinEst.cpp @ 1:6422640a802f

first upload
author Wen X <xue.wen@elec.qmul.ac.uk>
date Tue, 05 Oct 2010 10:45:57 +0100
parents
children
comparison
equal deleted inserted replaced
0:9b9f21935f24 1:6422640a802f
1 //---------------------------------------------------------------------------
2
3 #include <stddef.h>
4 #include "SinEst.h"
5 #include "fft.h"
6 #include "opt.h"
7 #include "SinSyn.h"
8 #include "splines.h"
9 #include "WindowFunctions.h"
10
11 //---------------------------------------------------------------------------
12 /*
13 function dsincd_unn: derivative of unnormalized discrete sinc function
14
15 In: x, scale N
16
17 Returns the derivative of sincd_unn(x, N)
18 */
19 double dsincd_unn(double x, int N)
20 {
21 double r=0;
22 double omg=M_PI*x;
23 double domg=omg/N;
24 if (fabs(x)>1e-6)
25 {
26 r=M_PI*(cos(omg)-sin(omg)*cos(domg)/sin(domg)/N)/sin(domg);
27 }
28 else
29 {
30 if (domg!=0)
31 {
32 double sindomg=sin(domg);
33 r=-omg*omg*omg*(1-1.0/(1.0*N*N))/3*M_PI/N/sindomg/sindomg;
34 }
35 else
36 r=0;
37 }
38 return r;
39 }//dsincd_unn
40
41 /*
42 function ddsincd_unn: 2nd-order derivative of unnormalized discrete sinc function
43
44 In: x, scale (equivalently, window size) N
45
46 Returns the 2nd-order derivative of sincd_unn(x, N)
47 */
48 double ddsincd_unn(double x, int N)
49 {
50 double r=0;
51 double omg=M_PI*x;
52 double domg=omg/N;
53 double PI2=M_PI*M_PI;
54 double NN=1.0/N/N-1;
55 if (domg==0)
56 {
57 r=PI2*N*NN/3;
58 }
59 else
60 {
61 if (fabs(x)>1e-5)
62 {
63 r=sin(domg)*cos(omg)-sin(omg)*cos(domg)/N;
64 }
65 else
66 {
67 r=omg*omg*omg/N*NN/3;
68 }
69 double ss=sin(omg)*NN;
70 r=-2.0/N*cos(domg)*r/sin(domg)/sin(domg)+ss;
71 r=r*PI2/sin(domg);
72 }
73 return r;
74 }//ddsincd_unn
75
76 //---------------------------------------------------------------------------
77 /*
78 function Window: calculates the cosine-family-windowed spectrum of a complex sinusoid on [0:N-1] at
79 frequency f bins with zero central phase.
80
81 In: f: frequency, in bins
82 N: window size
83 M, c[]: cosine-family window decomposition coefficients
84 Out: x[0...K2-K1] containing the spectrum at bins K1, ..., K2.
85
86 Returns pointer to x. x is created anew if x=0 is specified on start.
87 */
88 cdouble* Window(cdouble* x, double f, int N, int M, double* c, int K1, int K2)
89 {
90 if (K1<0) K1=0;
91 if (K2>N/2-1) K2=N/2-1;
92
93 if (!x) x=new cdouble[K2-K1+1];
94 memset(x, 0, sizeof(cdouble)*(K2-K1+1));
95
96 for (int l=K1-M; l<=K2+M; l++)
97 {
98 double ang=(f-l)*M_PI;
99 double omg=ang/N;
100 long double si, co, sinn=sin(ang);
101 si=sin(omg), co=cos(omg);
102 double sa=(ang==0)?N:(sinn/si);
103 double saco=sa*co;
104
105 int k1=l-M, k2=l+M;
106 if (k1<K1) k1=K1;
107 if (k2>K2) k2=K2;
108
109 for (int k=k1; k<=k2; k++)
110 {
111 int m=k-l, kt=k-K1;
112 if (m<0) m=-m;
113 if (k%2)
114 {
115 x[kt].x-=c[m]*saco;
116 x[kt].y+=c[m]*sinn;
117 }
118 else
119 {
120 x[kt].x+=c[m]*saco;
121 x[kt].y-=c[m]*sinn;
122 }
123 }
124 }
125 return x;
126 }//Window
127
128 /*
129 function dWindow: calculates the cosine-family-windowed spectrum and its derivative of a complex
130 sinusoid on [0:N-1] at frequency f bins with zero central phase.
131
132 In: f: frequency, in bins
133 N: window size
134 M, c[]: cosine-family window decomposition coefficients
135 Out: x[0...K2-K1] containing the spectrum at bins K1, ..., K2,
136 dx[0...K2-K1] containing the derivative spectrum at bins K1, ..., K2
137
138 No return value.
139 */
140 void dWindow(cdouble* dx, cdouble* x, double f, int N, int M, double* c, int K1, int K2)
141 {
142 if (K1<0) K1=0;
143 if (K2>N/2-1) K2=N/2-1;
144 memset(x, 0, sizeof(cdouble)*(K2-K1+1));
145 memset(dx, 0, sizeof(cdouble)*(K2-K1+1));
146
147 for (int l=K1-M; l<=K2+M; l++)
148 {
149 double ang=(f-l), Omg=ang*M_PI, omg=Omg/N;
150 long double si, co, sinn=sin(Omg), cosn=cos(Omg);
151 si=sin(omg), co=cos(omg);
152 double sa=(ang==0)?N:(sinn/si), dsa=dsincd_unn(ang, N);
153 double saco=sa*co, dsaco=dsa*co, sinnpi_n=sinn*M_PI/N, cosnpi=cosn*M_PI;
154
155 int k1=l-M, k2=l+M;
156 if (k1<K1) k1=K1;
157 if (k2>K2) k2=K2;
158
159 for (int k=k1; k<=k2; k++)
160 {
161 int m=k-l, kt=k-K1;
162 if (m<0) m=-m;
163 if (k%2)
164 {
165 x[kt].x-=c[m]*saco;
166 x[kt].y+=c[m]*sinn;
167 dx[kt].x-=c[m]*(-sinnpi_n+dsaco);
168 dx[kt].y+=c[m]*cosnpi;
169 }
170 else
171 {
172 x[kt].x+=c[m]*saco;
173 x[kt].y-=c[m]*sinn;
174 dx[kt].x+=c[m]*(-sinnpi_n+dsaco);
175 dx[kt].y-=c[m]*cosnpi;
176 }
177 }
178 }
179 }//dWindow
180
181 /*
182 function ddWindow: calculates the cosine-family-windowed spectrum and its 1st and 2nd derivatives of
183 a complex sinusoid on [0:N-1] at frequency f bins with zero central phase.
184
185 In: f: frequency, in bins
186 N: window size
187 M, c[]: cosine-family window decomposition coefficients
188 Out: x[0...K2-K1] containing the spectrum at bins K1, ..., K2,
189 dx[0...K2-K1] containing the derivative spectrum at bins K1, ..., K2
190 ddx[0...K2-K1] containing the 2nd-order derivative spectrum at bins K1, ..., K2
191
192 No return value.
193 */
194 void ddWindow(cdouble* ddx, cdouble* dx, cdouble* x, double f, int N, int M, double* c, int K1, int K2)
195 {
196 if (K1<0) K1=0;
197 if (K2>N/2-1) K2=N/2-1;
198 memset(x, 0, sizeof(cdouble)*(K2-K1+1));
199 memset(dx, 0, sizeof(cdouble)*(K2-K1+1));
200 memset(ddx, 0, sizeof(cdouble)*(K2-K1+1));
201
202 for (int l=K1-M; l<=K2+M; l++)
203 {
204 double ang=(f-l), Omg=ang*M_PI, omg=Omg/N;
205 long double si, co, sinn=sin(Omg), cosn=cos(Omg);
206 si=sin(omg), co=cos(omg);
207 double sa=(ang==0)?N:(sinn/si), dsa=dsincd_unn(ang, N), ddsa=ddsincd_unn(ang, N);
208 double saco=sa*co, dsaco=dsa*co, sinnpi_n=sinn*M_PI/N, sinnpipi=sinn*M_PI*M_PI, cosnpi=cosn*M_PI,
209 cosnpipi_n=cosnpi*M_PI/N, sipi_n=si*M_PI/N;
210
211 int k1=l-M, k2=l+M;
212 if (k1<K1) k1=K1;
213 if (k2>K2) k2=K2;
214
215 for (int k=k1; k<=k2; k++)
216 {
217 int m=k-l, kt=k-K1;
218 if (m<0) m=-m;
219 if (k%2)
220 {
221 x[kt].x-=c[m]*saco;
222 x[kt].y+=c[m]*sinn;
223 dx[kt].x-=c[m]*(-sinnpi_n+dsaco);
224 dx[kt].y+=c[m]*cosnpi;
225 ddx[kt].x-=c[m]*(-cosnpipi_n+ddsa*co-dsa*sipi_n);
226 ddx[kt].y-=c[m]*sinnpipi;
227 }
228 else
229 {
230 x[kt].x+=c[m]*saco;
231 x[kt].y-=c[m]*sinn;
232 dx[kt].x+=c[m]*(-sinnpi_n+dsaco);
233 dx[kt].y-=c[m]*cosnpi;
234 ddx[kt].x+=c[m]*(-cosnpipi_n+ddsa*co-dsa*sipi_n);
235 ddx[kt].y+=c[m]*sinnpipi;
236 }
237 }
238 }
239 }//ddWindow
240
241 //---------------------------------------------------------------------------
242 /*
243 function IPWindow: computes the truncated inner product of a windowed spectrum with that of a sinusoid
244 at reference frequency f.
245
246 In: x[0:N-1]: input spectrum
247 f: reference frequency, in bins
248 M, c[], iH2: cosine-family window specification parameters
249 K1, K2: spectrum truncation bounds, in bins, inclusive
250 returnamplitude: specifies return value, true for amplitude, false for angle
251
252 Returns the amplitude or phase of the inner product, as specified by $returnamplitude. The return
253 value is interpreted as the actual amplitude/phase of a sinusoid being estimated at f.
254 */
255 double IPWindow(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2, bool returnamplitude)
256 {
257 cdouble r=IPWindowC(f, x, N, M, c, iH2, K1, K2);
258 double result;
259 if (returnamplitude) result=sqrt(r.x*r.x+r.y*r.y);
260 else result=arg(r);
261 return result;
262 }//IPWindow
263 //wrapper function
264 double IPWindow(double f, void* params)
265 {
266 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dipwindow; double ipwindow;} *p=(l_ip *)params;
267 return IPWindow(f, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, true);
268 }//IPWindow
269
270 /*
271 function ddIPWindow: computes the norm of the truncated inner product of a windowed spectrum with
272 that of a sinusoid at reference frequency f, as well as its 1st and 2nd derivatives.
273
274 In: x[0:N-1]: input spectrum
275 f: reference frequency, in bins
276 M, c[], iH2: cosine-family window specification parameters
277 K1, K2: spectrum truncation bounds, in bins, inclusive
278 Out: ipwindow and dipwindow: the truncated inner product norm and its derivative
279
280 Returns the 2nd derivative of the norm of the truncated inner product.
281 */
282 double ddIPWindow(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2, double& dipwindow, double& ipwindow)
283 {
284 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
285 int K=K2-K1+1;
286 cdouble *w=new cdouble[K*3], *dw=&w[K], *ddw=&w[K*2], *lx=&x[K1];
287 ddWindow(ddw, dw, w, f, N, M, c, K1, K2);
288 cdouble r=Inner(K, lx, w), dr=Inner(K, lx, dw), ddr=Inner(K, lx, ddw);
289 delete[] w;
290
291 double R2=~r,
292 R=sqrt(R2),
293 dR2=2*(r.x*dr.x+r.y*dr.y),
294 dR=dR2/(2*R),
295 ddR2=2*(r.x*ddr.x+r.y*ddr.y+~dr),
296 ddR=(R*ddR2-dR2*dR)/(2*R2);
297 ipwindow=R*iH2;
298 dipwindow=dR*iH2;
299 return ddR*iH2;
300 }//ddIPWindow
301 //wrapper function
302 double ddIPWindow(double f, void* params)
303 {
304 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dipwindow; double ipwindow;} *p=(l_ip *)params;
305 return ddIPWindow(f, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->dipwindow, p->ipwindow);
306 }//ddIPWindow
307
308 //---------------------------------------------------------------------------
309 /*
310 function IPWindowC: computes the truncated inner product of a windowed spectrum with that of a
311 sinusoid at reference frequency f.
312
313 In: x[0:N-1]: input spectrum
314 f: reference frequency, in bins
315 M, c[], iH2: cosine-family window specification parameters
316 K1, K2: spectrum truncation bounds, in bins, inclusive
317
318 Returns the inner product. The return value is interpreted as the actual amplitude-phase factor of a
319 sinusoid being estimated at f.
320 */
321 cdouble IPWindowC(double f, cdouble* x, int N, int M, double* c, double iH2, int K1, int K2)
322 {
323 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
324 int K=K2-K1+1;
325 cdouble *w=new cdouble[K];
326 cdouble *lx=&x[K1], result=0;
327 Window(w, f, N, M, c, K1, K2);
328 for (int k=0; k<K; k++) result+=lx[k]^w[k];
329 delete[] w;
330 result*=iH2;
331 return result;
332 }//IPWindowC
333
334 //---------------------------------------------------------------------------
335 /*
336 function sIPWindow: computes the total energy of truncated inner products between multiple windowed
337 spectra and that of a sinusoid at a reference frequency f. This does not consider phase alignment
338 between the spectra, supposedly measured at a sequence of known instants.
339
340 In: x[L][N]: input spectra
341 f: reference frequency, in bins
342 M, c[], iH2: cosine-family window specification parameters
343 K1, K2: spectrum truncation bounds, in bins, inclusive
344 Out: lmd[L]: the actual individual inner products representing actual ampltiude-phase factors (optional)
345
346 Returns the energy of the vector of inner products.
347 */
348 double sIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, cdouble* lmd)
349 {
350 double sip=0;
351 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
352 int K=K2-K1+1;
353 cdouble *w=new cdouble[K];
354 Window(w, f, N, M, c, K1, K2);
355 for (int l=0; l<L; l++)
356 {
357 cdouble *lx=&x[l][K1];
358 cdouble r=Inner(K, lx, w);
359 if (lmd) lmd[l]=r*iH2;
360 sip+=~r;
361 }
362 sip*=iH2;
363 delete[] w;
364 return sip;
365 }//sIPWindow
366 //wrapper function
367 double sIPWindow(double f, void* params)
368 {
369 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; int Fr; cdouble** x; double dipwindow; double ipwindow; cdouble* lmd;} *p=(l_ip *)params;
370 return sIPWindow(f, p->Fr, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->lmd);
371 }//sIPWindow
372
373 /*
374 function dsIPWindow: computes the total energy of truncated inner products between multiple windowed
375 spectra and that of a sinusoid at a reference frequency f, as well as its derivative. This does not
376 consider phase synchronization between the spectra, supposedly measured at a sequence of known
377 instants.
378
379 In: x[L][N]: input spectra
380 f: reference frequency, in bins
381 M, c[], iH2: cosine-family window specification parameters
382 K1, K2: spectrum truncation bounds, in bins, inclusive
383 Out: sip, the energy of the vector of inner products.
384
385 Returns the derivative of the energy of the vector of inner products.
386 */
387 double dsIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& sip)
388 {
389 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
390 int K=K2-K1+1;
391 cdouble *w=new cdouble[K*2], *dw=&w[K];
392 dWindow(dw, w, f, N, M, c, K1, K2);
393 double dsip; sip=0;
394 for (int l=0; l<L; l++)
395 {
396 cdouble* lx=&x[l][K1];
397 cdouble r=Inner(K, lx, w), dr=Inner(K, lx, dw);
398 double R2=~r, dR2=2*(r.x*dr.x+r.y*dr.y);
399 sip+=R2, dsip+=dR2;
400 }
401 sip*=iH2, dsip*=iH2;
402 delete[] w;
403 return dsip;
404 }//dsIPWindow
405 //wrapper function
406 double dsIPWindow(double f, void* params)
407 {
408 struct l_ip1 {int N; int k1; int k2; int M; double* c; double iH2; int Fr; cdouble** x; double sip;} *p=(l_ip1 *)params;
409 return dsIPWindow(f, p->Fr, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->sip);
410 }//dsIPWindow
411
412 /*
413 function dsdIPWindow_unn: computes the energy of unnormalized truncated inner products between a given
414 windowed spectrum and that of a sinusoid at a reference frequency f, as well as its 1st and 2nd
415 derivatives. "Unnormalized" indicates that the inner product cannot be taken as the actual amplitude-
416 phase factor of a sinusoid, but deviate from that by an unspecified factor.
417
418 In: x[N]: input spectrum
419 f: reference frequency, in bins
420 M, c[], iH2: cosine-family window specification parameters
421 K1, K2: spectrum truncation bounds, in bins, inclusive
422 Out: sipwindow and dsipwindow, the energy and its derivative of the unnormalized inner product.
423
424 Returns the 2nd derivative of the inner product.
425 */
426 double ddsIPWindow_unn(double f, cdouble* x, int N, int M, double* c, int K1, int K2, double& dsipwindow, double& sipwindow, cdouble* w_unn)
427 {
428 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
429 int K=K2-K1+1;
430
431 cdouble *w=new cdouble[K*3], *dw=&w[K], *ddw=&w[K*2];
432
433 ddWindow(ddw, dw, w, f, N, M, c, K1, K2);
434
435 double rr=0, ri=0, drr=0, dri=0, ddrr=0, ddri=0;
436 cdouble *lx=&x[K1];
437 for (int k=0; k<K; k++)
438 {
439 rr+=lx[k].x*w[k].x+lx[k].y*w[k].y;
440 ri+=lx[k].y*w[k].x-lx[k].x*w[k].y;
441 drr+=lx[k].x*dw[k].x+lx[k].y*dw[k].y;
442 dri+=lx[k].y*dw[k].x-lx[k].x*dw[k].y;
443 ddrr+=lx[k].x*ddw[k].x+lx[k].y*ddw[k].y;
444 ddri+=lx[k].y*ddw[k].x-lx[k].x*ddw[k].y;
445 }
446 delete[] w;
447
448 double R2=rr*rr+ri*ri,
449 dR2=2*(rr*drr+ri*dri),
450 ddR2=2*(rr*ddrr+ri*ddri+drr*drr+dri*dri);
451 sipwindow=R2;
452 dsipwindow=dR2;
453 if (w_unn) w_unn->x=rr, w_unn->y=ri;
454 return ddR2;
455 }//ddsIPWindow_unn
456
457 /*
458 function ddsIPWindow: computes the total energy of truncated inner products between multiple windowed
459 spectra and that of a sinusoid at a reference frequency f, as well as its 1st and 2nd derivatives.
460 This does not consider phase synchronization between the spectra, supposedly measured at a sequence
461 of known instants.
462
463 In: x[L][N]: input spectra
464 f: reference frequency, in bins
465 M, c[], iH2: cosine-family window specification parameters
466 K1, K2: spectrum truncation bounds, in bins, inclusive
467 Out: sip and dsip, the energy of the vector of inner products and its derivative.
468
469 Returns the 2nd derivative of the energy of the vector of inner products.
470 */
471 double ddsIPWindow(double f, int L, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& dsip, double& sip)
472 {
473 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
474 int K=K2-K1+1;
475 cdouble *w=new cdouble[K*3], *dw=&w[K], *ddw=&w[K*2];
476 ddWindow(ddw, dw, w, f, N, M, c, K1, K2);
477 double ddsip=0; dsip=sip=0;
478 for (int l=0; l<L; l++)
479 {
480 cdouble* lx=&x[l][K1];
481 cdouble r=Inner(K, lx, w), dr=Inner(K, lx, dw), ddr=Inner(K, lx, ddw);
482 double R2=~r, dR2=2*(r.x*dr.x+r.y*dr.y), ddR2=2*(r.x*ddr.x+r.y*ddr.y+~dr);
483 sip+=R2, dsip+=dR2, ddsip+=ddR2;
484 }
485 sip*=iH2, dsip*=iH2, ddsip*=iH2;
486 delete[] w;
487 return ddsip;
488 }//ddsIPWindow
489 //wrapper function
490 double ddsIPWindow(double f, void* params)
491 {
492 struct l_ip1 {int N; int k1; int k2; int M; double* c; double iH2; int Fr; cdouble** x; double dsip; double sip;} *p=(l_ip1 *)params;
493 return ddsIPWindow(f, p->Fr, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->dsip, p->sip);
494 }//ddsIPWindow
495
496 //---------------------------------------------------------------------------
497 /*
498 function sIPWindowC: computes the total energy of truncated inner products between multiple frames of
499 a spectrogram and multiple frames of a spectrogram of a sinusoid at a reference frequency f.
500
501 In: x[L][N]: the spectrogram
502 offst_rel: frame offset, relative to frame size
503 f: reference frequency, in bins
504 M, c[], iH2: cosine-family window specification parameters
505 K1, K2: spectrum truncation bounds, in bins, inclusive
506 Out: lmd[L]: the actual individual inner products representing actual ampltiude-phase factors (optional)
507
508 Returns the energy of the vector of inner products.
509 */
510 double sIPWindowC(double f, int L, double offst_rel, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, cdouble* lmd)
511 {
512 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
513 int K=K2-K1+1;
514 cdouble *w=new cdouble[K];
515 double Cr=0;
516 cdouble Cc=0;
517 Window(w, f, N, M, c, K1, K2);
518 for (int l=0; l<L; l++)
519 {
520 cdouble *lx=&x[l][K1];
521 cdouble r=Inner(K, lx, w);
522 Cr+=~r;
523 double ph=-4*M_PI*f*offst_rel*l;
524 cdouble r2=r*r;
525 Cc+=r2.rotate(ph);
526 if (lmd) lmd[l]=r;
527 }
528 delete[] w;
529 double result=0.5*iH2*(Cr+abs(Cc));
530 if (lmd)
531 {
532 double absCc=abs(Cc), hiH2=0.5*iH2;
533 cdouble ej2ph=Cc/absCc;
534 for (int l=0; l<L; l++)
535 {
536 double ph=4*M_PI*f*offst_rel*l;
537 lmd[l]=hiH2*(lmd[l]+(ej2ph**lmd[l]).rotate(ph));
538 }
539 }
540 return result;
541 }//sIPWindowC
542 //wrapper function
543 double sIPWindowC(double f, void* params)
544 {
545 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; int L; double offst_rel; cdouble** x; double dipwindow; double ipwindow;} *p=(l_ip *)params;
546 return sIPWindowC(f, p->L, p->offst_rel, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2);
547 }//sIPWindowC
548
549 /*
550 function dsIPWindowC: computes the total energy of truncated inner products between multiple frames of
551 a spectrogram and multiple frames of a spectrogram of a sinusoid at a reference frequency f, together
552 with its derivative.
553
554 In: x[L][N]: the spectrogram
555 offst_rel: frame offset, relative to frame size
556 f: reference frequency, in bins
557 M, c[], iH2: cosine-family window specification parameters
558 K1, K2: spectrum truncation bounds, in bins, inclusive
559 Out: sip: energy of the vector of the inner products
560
561 Returns the 1st derivative of the energy of the vector of inner products.
562 */
563 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)
564 {
565 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
566 int K=K2-K1+1;
567
568 cdouble *w=new cdouble[K*2], *dw=&w[K];
569 dWindow(dw, w, f, N, M, c, K1, K2);
570 double Cr=0, dCr=0;
571 cdouble Cc=0, dCc=0;
572 for (int l=0; l<L; l++)
573 {
574 cdouble *lx=&x[l][K1];
575 cdouble r=Inner(K, lx, w), dr=Inner(K, lx, dw);
576 Cr+=~r; dCr+=2*(r.x*dr.x+r.y*dr.y);
577 int two=2;
578 cdouble r2=r*r, dr2=r*dr*two;
579 double lag=-4*M_PI*offst_rel*l, ph=lag*f;
580 Cc=Cc+cdouble(r2).rotate(ph), dCc=dCc+(dr2+cdouble(0,lag)*r2).rotate(ph);
581 }
582 double Cc2=~Cc, dCc2=2*(Cc.x*dCc.x+Cc.y*dCc.y);
583 double Cc1=sqrt(Cc2), dCc1=dCc2/(2*Cc1);
584 sip=0.5*iH2*(Cr+Cc1);
585 double dsip=0.5*iH2*(dCr+dCc1);
586 delete[] w;
587 return dsip;
588 }//dsIPWindowC
589 //wrapper function
590 double dsIPWindowC(double f, void* params)
591 {
592 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; int L; double offst_rel; cdouble** x; double sip;} *p=(l_ip *)params;
593 return dsIPWindowC(f, p->L, p->offst_rel, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->sip);
594 }//dsIPWindowC
595
596 /*
597 function ddsIPWindowC: computes the total energy of truncated inner products between multiple frames
598 of a spectrogram and multiple frames of a spectrogram of a sinusoid at a reference frequency f,
599 together with its 1st and 2nd derivatives.
600
601 In: x[L][N]: the spectrogram
602 offst_rel: frame offset, relative to frame size
603 f: reference frequency, in bins
604 M, c[], iH2: cosine-family window specification parameters
605 K1, K2: spectrum truncation bounds, in bins, inclusive
606 Out: sipwindow, dsipwindow: energy of the vector of the inner products and its derivative
607
608 Returns the 2nd derivative of the energy of the vector of inner products.
609 */
610 double ddsIPWindowC(double f, int L, double offst_rel, cdouble** x, int N, int M, double* c, double iH2, int K1, int K2, double& dsipwindow, double& sipwindow)
611 {
612 if (K1<0) K1=0; if (K2>=N/2) K2=N/2-1;
613 int K=K2-K1+1;
614
615 cdouble *w=new cdouble[K*3], *dw=&w[K], *ddw=&w[K*2];
616 ddWindow(ddw, dw, w, f, N, M, c, K1, K2);
617 double Cr=0, dCr=0, ddCr=0;
618 cdouble Cc=0, dCc=0, ddCc=0;
619 for (int l=0; l<L; l++)
620 {
621 cdouble *lx=&x[l][K1];
622 cdouble r=Inner(K, lx, w), dr=Inner(K, lx, dw), ddr=Inner(K, lx, ddw);
623 Cr+=~r; dCr+=2*(r.x*dr.x+r.y*dr.y); ddCr+=2*(r.x*ddr.x+r.y*ddr.y+~dr);
624 int two=2;
625 cdouble r2=r*r, dr2=r*dr*two, ddr2=(dr*dr+r*ddr)*two;
626 double lag=-4*M_PI*offst_rel*l, ph=lag*f;
627 Cc=Cc+cdouble(r2).rotate(ph), dCc=dCc+(dr2+cdouble(0,lag)*r2).rotate(ph), ddCc=ddCc+(ddr2+cdouble(0,2*lag)*dr2-r2*lag*lag).rotate(ph);
628 }
629 double Cc2=~Cc, dCc2=2*(Cc.x*dCc.x+Cc.y*dCc.y), ddCc2=2*(Cc.x*ddCc.x+Cc.y*ddCc.y+~dCc);
630 double Cc1=sqrt(Cc2), dCc1=dCc2/(2*Cc1), ddCc1=(Cc1*ddCc2-dCc2*dCc1)/(2*Cc2);
631 sipwindow=0.5*iH2*(Cr+Cc1);
632 dsipwindow=0.5*iH2*(dCr+dCc1);
633 double ddsipwindow=0.5*iH2*(ddCr+ddCc1);
634 delete[] w;
635 return ddsipwindow;
636 }//ddsIPWindowC
637 //wrapper function
638 double ddsIPWindowC(double f, void* params)
639 {
640 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; int L; double offst_rel; cdouble** x; double dipwindow; double ipwindow;} *p=(l_ip *)params;
641 return ddsIPWindowC(f, p->L, p->offst_rel, p->x, p->N, p->M, p->c, p->iH2, p->k1, p->k2, p->dipwindow, p->ipwindow);
642 }//ddsIPWindowC
643
644 //--------------------------------------------------------------------------
645 /*
646 Least-square-error sinusoid detection function
647
648 version1: picking the highest peak and take measurement of a single sinusoid
649 version2: given a rough peak location and take measurement of a single sinusoid
650
651 Complex spectrum x is calculated using N data points windowed by a window function that is specified
652 by the parameter set (M, c, iH2). c[0:M] is provided according to Table 3 in the transfer report, on
653 pp.11. iH2 is simply 1/H2, where H2 can be calculated using formula (2.17) on pp.12.
654
655 f & epf are given/returned in bins.
656
657 Further reading: "Least-square-error estimation of sinusoids.pdf"
658 */
659
660 /*
661 function LSESinusoid: LSE estimation of the predominant stationary sinusoid.
662
663 In: x[N]: windowed spectrum
664 B: spectral truncation half width, in bins.
665 M, c[], iH2: cosine-family window specification parameters
666 epf: frequency error tolerance, in bins
667 Out: a and pp: amplitude and phase estimates
668
669 Returns the frequency estimate, in bins.
670 */
671 double LSESinusoid(cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf)
672 {
673 struct l_hx {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dhxpeak; double hxpeak;} p={N, 0, 0, M, c, iH2, x, 0, 0}; //(l_hx *)&params;
674 int dfshift=int(&((l_hx*)0)->dhxpeak);
675
676 int inp;
677 double minp=0;
678 for (int i=0; i<N; i++)
679 {
680 double lf=i, tmp;
681 p.k1=ceil(lf-B); if (p.k1<0) p.k1=0;
682 p.k2=floor(lf+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
683 tmp=IPWindow(lf, &p);
684 if (minp<tmp) inp=i, minp=tmp;
685 }
686
687 double f=inp;
688 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
689 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
690 double tmp=Newton(f, ddIPWindow, &p, dfshift, epf);
691 if (tmp==-1)
692 {
693 Search1Dmax(f, &p, IPWindow, inp-1, inp+1, &a, epf);
694 }
695 else
696 a=p.hxpeak;
697 pp=IPWindow(f, x, N, M, c, iH2, p.k1, p.k2, false);
698 return f;
699 }//LSESinusoid
700
701 /*function LSESinusoid: LSE estimation of stationary sinusoid near a given initial frequency.
702
703 In: x[N]: windowed spectrum
704 f: initial frequency, in bins
705 B: spectral truncation half width, in bins.
706 M, c[], iH2: cosine-family window specification parameters
707 epf: frequency error tolerance, in bins
708 Out: f, a and pp: frequency, amplitude and phase estimates
709
710 No return value.
711 */
712 void LSESinusoid(double& f, cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf)
713 {
714 struct l_hx {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dhxpeak; double hxpeak;} p={N, 0, 0, M, c, iH2, x, 0, 0};
715 int dfshift=int(&((l_hx*)0)->dhxpeak);
716
717 double inp=f;
718 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
719 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
720 double tmp=Newton(f, ddIPWindow, &p, dfshift, epf);
721 if (tmp==-1)
722 {
723 Search1Dmax(f, &p, IPWindow, inp-1, inp+1, &a, epf);
724 }
725 else
726 a=p.hxpeak;
727 pp=IPWindow(f, x, N, M, c, iH2, p.k1, p.k2, false);
728 }//LSESinusoid
729
730 /*
731 function LSESinusoid: LSE estimation of stationary sinusoid predominant within [f1, f2].
732
733 In: x[N]: windowed spectrum
734 [f1, f2]: frequency range
735 B: spectral truncation half width, in bins.
736 M, c[], iH2: cosine-family window specification parameters
737 epf: frequency error tolerance, in bins
738 Out: a and pp: amplitude and phase estimates
739
740 Returns the frequency estimate, in bins.
741 */
742 double LSESinusoid(int f1, int f2, cdouble* x, int N, double B, int M, double* c, double iH2, double& a, double& pp, double epf)
743 {
744 struct l_hx {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dhxpeak; double hxpeak;} p={N, 0, 0, M, c, iH2, x, 0, 0};
745 int dfshift=int(&((l_hx*)0)->dhxpeak);
746
747 int inp;
748 double minp=0;
749 for (int i=f1; i<f2; i++)
750 {
751 double lf=i, tmp;
752 p.k1=ceil(lf-B); if (p.k1<0) p.k1=0;
753 p.k2=floor(lf+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
754 tmp=IPWindow(lf, &p);
755 if (minp<tmp) inp=i, minp=tmp;
756 }
757
758 double f=inp;
759 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
760 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
761 double tmp=Newton(f, ddIPWindow, &p, dfshift, epf);
762 if (tmp==-1)
763 {
764 Search1Dmax(f, &p, IPWindow, inp-1, inp+1, &a, epf);
765 }
766 else
767 a=p.hxpeak;
768 pp=IPWindow(f, x, N, M, c, iH2, p.k1, p.k2, false);
769 return f;
770 }//LSESinusoid
771
772 /*
773 function LSESinusoid: LSE estimation of stationary sinusoid near a given initial frequency within [f1,
774 f2].
775
776 In: x[N]: windowed spectrum
777 f: initial frequency, in bins
778 [f1, f2]: frequency range
779 B: spectral truncation half width, in bins.
780 M, c[], iH2: cosine-family window specification parameters
781 epf: frequency error tolerance, in bins
782 Out: f, a and pp: frequency, amplitude and phase estimates
783
784 Returns 1 if managed to find a sinusoid, 0 if not, upon which $a and $pp are estimated at the initial
785 f.
786 */
787 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)
788 {
789 struct l_hx {int N; int k1; int k2; int M; double* c; double iH2; cdouble* x; double dhxpeak; double hxpeak;} p={N, 0, 0, M, c, iH2, x, 0, 0};//(l_hx *)&params;
790 int dfshift=int(&((l_hx*)0)->dhxpeak);
791
792 int result=0;
793 double inp=f;
794 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
795 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
796 double tmp=Newton(f, ddIPWindow, &p, dfshift, epf, 100, 1e-256, f1, f2);
797 if (tmp!=-1 && f>f1 && f<f2)
798 {
799 result=1;
800 a=p.hxpeak;
801 pp=IPWindow(f, x, N, M, c, iH2, p.k1, p.k2, false);
802 }
803 else
804 {
805 Search1DmaxEx(f, &p, IPWindow, f1, f2, &a, epf);
806 if (f<=f1 || f>=f2)
807 {
808 f=inp;
809 cdouble r=IPWindowC(f, x, N, M, c, iH2, p.k1, p.k2);
810 a=abs(r);
811 pp=arg(r);
812 }
813 else
814 {
815 result=1;
816 pp=IPWindow(f, x, N, M, c, iH2, p.k1, p.k2, false);
817 }
818 }
819 return result;
820 }//LSESinusoid
821
822 /*
823 function LSESinusoidMP: LSE estimation of a stationary sinusoid from multi-frames spectrogram without
824 considering phase-frequency consistency across frames.
825
826 In: x[Fr][N]: spectrogram
827 f: initial frequency, in bins
828 [f1, f2]: frequency range
829 B: spectral truncation half width, in bins.
830 M, c[], iH2: cosine-family window specification parameters
831 epf: frequency error tolerance, in bins
832 Out: f, a[Fr] and ph[Fr]: frequency, amplitudes and phase angles estimates
833
834 Returns an error bound of the frequency estimate.
835 */
836 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)
837 {
838 struct l_ip1 {int N; int k1; int k2; int M; double* c; double iH2; int L; cdouble** x; double dsip; double sip; cdouble* lmd;} p={N, 0, 0, M, c,iH2, Fr, x, 0, 0, 0};
839 int dfshift=int(&((l_ip1*)0)->dsip), fshift=int(&((l_ip1*)0)->sip);
840
841 double inp=f;
842 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
843 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
844 double errf=Newton1dmax(f, f1, f2, ddsIPWindow, &p, dfshift, fshift, dsIPWindow, dfshift, epf);
845 if (errf<0) errf=Search1Dmax(f, &p, sIPWindow, f1, f2, a, epf);
846 if (a || ph)
847 {
848 for (int fr=0; fr<Fr; fr++)
849 {
850 cdouble r=IPWindowC(f, x[fr], N, M, c, iH2, p.k1, p.k2);
851 if (a) a[fr]=abs(r);
852 if (ph) ph[fr]=arg(r);
853 }
854 }
855 return errf;
856 }//LSESinusoidMP
857
858 /*
859 function LSESinusoidMP: LSE estimation of a stationary sinusoid from multi-frames spectrogram without
860 considering phase-frequency consistency across frames.
861
862 In: x[Fr][N]: spectrogram
863 f: initial frequency, in bins
864 [f1, f2]: frequency range
865 B: spectral truncation half width, in bins.
866 M, c[], iH2: cosine-family window specification parameters
867 epf: frequency error tolerance, in bins
868 Out: f, a[Fr] and ph[Fr]: frequency, amplitudes and phase angles estimates
869
870 Returns an error bound of the frequency estimate. Although the frequencies are estimated assuming
871 cross-frame frequency-phase consistency, the final output phase angles are reestimated independently
872 for each frame using the frequency estimate.
873 */
874 double LSESinusoidMPC(double& f, double f1, double f2, cdouble** x, int Fr, int N, int Offst, double B, int M, double* c, double iH2, double* a, double* ph, double epf)
875 {
876 struct l_ip {int N; int k1; int k2; int M; double* c; double iH2; int L; double offst_rel; cdouble** x; double sdip; double sip;}
877 p={N, 0, 0, M, c,iH2, Fr, Offst*1.0/N, x, 0, 0};
878 int dfshift=int(&((l_ip*)0)->sdip), fshift=int(&((l_ip*)0)->sip);
879
880 double inp=f;
881 p.k1=ceil(inp-B); if (p.k1<0) p.k1=0;
882 p.k2=floor(inp+B); if (p.k2>=p.N/2) p.k2=p.N/2-1;
883 double errf=Newton1dmax(f, f1, f2, ddsIPWindowC, &p, dfshift, fshift, dsIPWindowC, dfshift, epf);
884 if (errf<0) errf=Search1Dmax(f, &p, sIPWindowC, f1, f2, a, epf);
885 if (a || ph)
886 {
887 cdouble* lmd=new cdouble[Fr];
888 sIPWindowC(f, Fr, Offst*1.0/N, x, N, M, c, iH2, p.k1, p.k2, lmd);
889 for (int fr=0; fr<Fr; fr++)
890 {
891 lmd[fr]=IPWindowC(f, x[fr], N, M, c, iH2, p.k1, p.k2);
892
893 if (a) a[fr]=abs(lmd[fr]);
894 if (ph) ph[fr]=arg(lmd[fr]);
895 }
896 delete[] lmd;
897 }
898 return errf;
899 }//LSESinusoidMPC
900
901 //---------------------------------------------------------------------------
902 /*
903 function IPMulti: least square estimation of multiple sinusoids, given their frequencies and an energy
904 suppression index of eps, i.e. the least square error is minimized with an additional eps*||lmd||^2
905 term.
906
907 In: x[Wid]: spectrum
908 f[I]: frequencies
909 M, c[]: cosine-family window specification parameters
910 K1, K2: spectral truncation range, i.e. bins outside [K1, K2] are ignored
911 eps: energy suppression factor
912 Out: lmd[I]: amplitude-phase factors
913
914 No return value.
915 */
916 void IPMulti(int I, double* f, cdouble* lmd, cdouble* x, int Wid, int K1, int K2, int M, double* c, double eps)
917 {
918 if (K1<0) K1=0; if (K2>=Wid/2) K2=Wid/2-1; int K=K2-K1+1;
919 MList* List=new MList;
920 cdouble** Allocate2L(cdouble, I, K, wt, List);
921 for (int i=0; i<I; i++) Window(wt[i], f[i], Wid, M, c, K1, K2);
922 cdouble** whw=MultiplyXcXt(I, K, wt, List);
923 cdouble* whx=MultiplyXcy(I, K, wt, &x[K1], List);
924 for (int i=0; i<I; i++) whw[i][i]+=eps;
925 GECP(I, lmd, whw, whx);
926 delete List;
927 }//IPMulti
928
929 /*
930 function IPMulti: least square estimation of multiple sinusoids, given their frequencies and an energy
931 suppression index of eps, and optionally returns residue and sensitivity indicators for each sinusoid.
932
933 In: x[Wid]: spectrum
934 f[I]: frequencies
935 M, c[]: cosine-family window specification parameters
936 K1, K2: spectral truncation range, i.e. bins outside [K1, K2] are ignored
937 eps: energy suppression factor
938 Out: lmd[I]: amplitude-phase factors
939 sens[I]: sensitivity indicators
940 r1[I]: residue indicators, measured by correlating residue with sinusoid spectra, optional
941
942 No return value. Sensibitily is computed BEFORE applying eps.
943 */
944 void IPMulti(int I, double* f, cdouble* lmd, cfloat* x, int Wid, int K1, int K2, int M, double* c, double eps, double* sens, double* r1)
945 {
946 if (K1<0) K1=0; if (K2>=Wid/2) K2=Wid/2-1; int K=K2-K1+1;
947 MList* List=new MList;
948 cdouble** Allocate2L(cdouble, I, K, wt, List);
949 for (int i=0; i<I; i++) Window(wt[i], f[i], Wid, M, c, K1, K2);
950 cdouble** whw=MultiplyXcXt(I, K, wt, List);
951
952 //*computes sensitivity if required
953 if (sens)
954 {
955 cdouble** iwhw=Copy(I, whw, List);
956 GICP(I, iwhw);
957 cdouble** u=MultiplyXYc(I, I, K, iwhw, wt, List);
958 for (int i=0; i<I; i++)
959 {
960 sens[i]=0; for (int k=0; k<K; k++) sens[i]+=~u[i][k]; sens[i]=sqrt(sens[i]);
961 }
962 } //*/
963 cdouble* whx=MultiplyXcy(I, K, wt, &x[K1], List);
964 for (int i=0; i<I; i++) whw[i][i]+=eps;
965 GECP(I, lmd, whw, whx);
966 //compute residue if required
967 if (r1)
968 {
969 cdouble* wlmd=MultiplyXty(K, I, wt, lmd, List); //reconstruct
970 for (int k=0; k<K; k++) wlmd[k]=wlmd[k]-x[K1+k]; //-residue
971 for (int i=0; i<I; i++) //r1[i]=Inner(K, wlmd, wt[i]).abs(); //-residue weighted by window
972 {
973 r1[i]=0;
974 for (int k=0; k<K; k++) r1[i]+=abs(wlmd[k])*abs(wt[i][k]);
975 }
976 }
977 delete List;
978 }//IPMulti
979
980 /*
981 function IPMultiSens: computes the sensitivity of the least square estimation of multiple sinusoids given
982 their frequencies .
983
984 In: f[I]: frequencies
985 M, c[]: cosine-family window specification parameters
986 K1, K2: spectral truncation range, i.e. bins outside [K1, K2] are ignored
987 eps: energy suppression factor
988 Out: sens[I]: sensitivity indicators
989
990 No return value. Sensibility is computed AFTER applying eps
991 */
992 void IPMultiSens(int I, double* f, int Wid, int K1, int K2, int M, double* c, double* sens, double eps)
993 {
994 if (K1<0) K1=0; if (K2>=Wid/2) K2=Wid/2-1; int K=K2-K1+1;
995 MList* List=new MList;
996 cdouble** Allocate2L(cdouble, I, K, wt, List);
997 for (int i=0; i<I; i++) Window(wt[i], f[i], Wid, M, c, K1, K2);
998
999 cdouble** whw=MultiplyXcXt(I, K, wt, List);
1000 for (int i=0; i<I; i++) whw[i][i]+=eps;
1001
1002 cdouble** iwhw=Copy(I, whw, List);
1003 GICP(I, iwhw);
1004 cdouble** u=MultiplyXYc(I, I, K, iwhw, wt, List);
1005 for (int i=0; i<I; i++)
1006 {
1007 sens[i]=0; for (int k=0; k<K; k++) sens[i]+=~u[i][k]; sens[i]=sqrt(sens[i]);
1008 }
1009 delete List;
1010 }//IPMultiSens
1011
1012 /*
1013 function IPMulti: least square estimation of multi-sinusoids with GIVEN frequencies. This version
1014 operates in groups at least B bins from each other, rather than LSE all frequencies together.
1015
1016 In: x[Wid]: spectrum
1017 f[I]: frequencies, must be ordered low to high.
1018 B: number of bins beyond which sinusoids are treated as non-interfering
1019 M, c[], iH2: cosine-family window specification parameters
1020 Out: lmd[I]: amplitude-phase factors
1021
1022 Returns 0.
1023 */
1024 double IPMulti(int I, double* f, cdouble* lmd, cdouble* x, int Wid, int M, double* c, double iH2, int B)
1025 {
1026 int i=0, ist=0;
1027 double Bw=B;
1028 while (i<I)
1029 {
1030 if ((i>0 && f[i]-f[i-1]>Bw) || i==I-1)
1031 {
1032 if (i==I-1) i++;
1033 //process frequencies from ist to i-1
1034 if (i-1==ist) //one sinusoid
1035 {
1036 double fb=f[ist]; int K1=floor(fb-B+0.5), K2=floor(fb+B+0.5);
1037 lmd[ist]=IPWindowC(fb, x, Wid, M, c, iH2, K1, K2);
1038 }
1039 else
1040 {
1041 MList* List=new MList;
1042 int N=i-ist, K1=floor(f[ist]-B+0.5), K2=floor(f[i-1]+B+0.5), K=K2-K1+1;
1043 cdouble** Allocate2L(cdouble, N, K, wt, List);
1044 for (int n=0; n<N; n++) Window(wt[n], f[ist+n], Wid, M, c, K1, K2);
1045 cdouble* whx=MultiplyXcy(N, K, wt, &x[K1], List); //w*'x=(wt*)x
1046 cdouble** whw=MultiplyXcXt(N, K, wt, List);
1047 /*debug cdouble** C=SubMatrix(0, whw, 1, 4, 1, 4, List); cdouble** C2=SubMatrix(0, whw, 1, 4, 1, 4, List); cdouble** Bh=SubMatrix(0, whw, 1, 4, 0, 1, List); cdouble* Y2=SubVector(0, whx, 1, 4);
1048 cdouble x2[4]; cdouble x1=lmd[ist], Bhx1[4], dx2[4]; for (int j=0; j<4; j++) Bhx1[j]=x1^Bh[j][0]; GECP(4, x2, C, Y2); GECP(4, dx2, C2, Bhx1);*/
1049 GECP(N, &lmd[ist], whw, whx); //solving complex linear system (w*'w)a=w*'x
1050 delete List;
1051 }
1052 ist=i;
1053 }
1054 i++;
1055 }
1056 return 0;
1057 }//IPMulti
1058
1059 /*
1060 function IPMulti_Direct: LSE estimation of multiple sinusoids given frequencies AND PHASES (direct
1061 method)
1062
1063 In: x[Wid]: spectrum
1064 f[I], ph[I]: frequencies and phase angles.
1065 B: spectral truncation half width, in bins; sinusoids over 3B bins apart are regarded non-interfering
1066 M, c[], iH2: cosine-family window specification parameters
1067 Out: a[I]: amplitudes
1068
1069 Returns square norm of the residue.
1070 */
1071 double IPMulti_Direct(int I, double* f, double* ph, double* a, cdouble* x, int Wid, int M, double* c, double iH2, int B)
1072 {
1073 MList* List=new MList;
1074 int i=0, ist=0, hWid=Wid/2;
1075 cdouble* r=Copy(hWid, x, List); //to store the residue
1076
1077 double Bw=3.0*B;
1078 while (i<I)
1079 {
1080 if ((i>0 && f[i]-f[i-1]>Bw) || i==I-1)
1081 {
1082 if (i==I-1) i++;
1083
1084 //process frequencies from ist to i-1
1085 if (i-1==ist) //one sinusoid
1086 {
1087 double fb=f[ist];
1088 cdouble* w=Window(0, fb, Wid, M, c, 0, hWid-1);
1089 for (int k=0; k<hWid; k++) w[k].rotate(ph[ist]);
1090 double ip=Inner(2*hWid, (double*)x, (double*)w);
1091 a[ist]=ip*iH2;
1092 MultiAdd(hWid, r, r, w, -a[ist]);
1093 delete[] w;
1094 }
1095 else
1096 {
1097 int N=i-ist;
1098 cdouble** Allocate2L(cdouble, N, hWid, wt, List);
1099 for (int n=0; n<N; n++)
1100 {
1101 Window(wt[n], f[ist+n], Wid, M, c, 0, hWid-1);
1102 for (int k=0; k<hWid; k++) wt[n][k].rotate(ph[ist+n]);
1103 }
1104 double* whxr=MultiplyXy(N, hWid*2, (double**)wt, (double*)x, List); //w*'x=(wt*)x
1105 double** whwr=MultiplyXXt(N, hWid*2, (double**)wt, List);
1106 GECP(N, &a[ist], whwr, whxr); //solving complex linear system (w*'w)a=w*'x
1107 for (int n=0; n<N; n++) MultiAdd(hWid, r, r, wt[n], -a[ist+n]);
1108 }
1109 ist=i;
1110 }
1111 i++;
1112 }
1113 double result=Inner(hWid, r, r).x;
1114 delete List;
1115 return result;
1116 }//IPMulti_Direct
1117
1118 /*
1119 function IPMulti_GS: LSE estimation of multiple sinusoids given frequencies AND PHASES (Gram-Schmidt method)
1120
1121 In: x[Wid]: spectrum
1122 f[I], ph[I]: frequencies and phase angles.
1123 B: spectral truncation, in bins; sinusoids over 3B bins apart are regarded non-interfering
1124 M, c[], iH2: cosine-family window specification parameters
1125 Out: a[I]: amplitudes
1126
1127 Returns square norm of the residue.
1128 */
1129 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, double** Q)
1130 {
1131 MList* List=new MList;
1132 int i=0, ist=0, hWid=Wid/2;
1133 cdouble* r=Copy(hWid, x, List); //to store the residue
1134 double Bw=3.0*B;
1135 while (i<I)
1136 {
1137 if ((i>0 && f[i]-f[i-1]>Bw) || i==I-1)
1138 {
1139 if (i==I-1) i++;
1140
1141 //process frequencies from ist to i-1
1142 if (i-1==ist) //one sinusoid
1143 {
1144 double fb=f[ist];
1145 cdouble* w=Window(0, fb, Wid, M, c, 0, hWid-1);
1146 for (int k=0; k<hWid; k++) w[k].rotate(ph[ist]);
1147 double ip=Inner(2*hWid, (double*)x, (double*)w);
1148 a[ist]=ip*iH2;
1149 MultiAdd(hWid, r, r, w, -a[ist]);
1150 delete[] w;
1151 }
1152 else
1153 {
1154 int N=i-ist;
1155 cdouble** Allocate2L(cdouble, N, hWid, wt, List);
1156 Alloc2L(N, N, L, List); Alloc2L(N, hWid*2, Q, List);
1157 for (int n=0; n<N; n++)
1158 {
1159 Window(wt[n], f[ist+n], Wid, M, c, 0, hWid-1);
1160 for (int k=0; k<hWid; k++) wt[n][k].rotate(ph[ist+n]);
1161 }
1162 LQ_GS(N, hWid*2, (double**)wt, L, Q);
1163 double* atl=MultiplyxYt(N, hWid*2, (double*)x, Q, List);
1164 GExL(N, &a[ist], L, atl);
1165 for (int n=0; n<N; n++) MultiAdd(hWid, r, r, wt[n], -a[ist+n]);
1166 }
1167 ist=i;
1168 }
1169 i++;
1170 }
1171 double result=Inner(hWid, r, r).x;
1172 delete List;
1173 return result;
1174 }//IPMulti_GS
1175
1176 /*
1177 function IPMulti: LSE estimation of I sinusoids given frequency and phase and J sinusoids given
1178 frequency only
1179
1180 In: x[Wid]: spectrum
1181 f[I+J], ph[I]: frequencies and phase angles
1182 M, c[], iH2: cosine-family window specification parameters
1183 Out: a[I+J]: amplitudes
1184 ph[I:I+J-1]: phase angles not given on start
1185 wt[I+2J][hWid], Q[I+2J][hWid], L[I+2J][I+2J]: internal w matrix and its LQ factorization, optional
1186
1187 Returns the residue vector, newly created and registered to RetList, if specified. On start a[] should
1188 have valid storage no less than I+2J.
1189 */
1190 cdouble* IPMulti(int I, int J, double* f, double* ph, double* a, cdouble* x, int Wid, int M, double* c, cdouble** wt, cdouble** Q, double** L, MList* RetList)
1191 {
1192 MList* List=new MList;
1193 int hWid=Wid/2;
1194 cdouble* r=Copy(hWid, x, RetList); //to store the residue
1195 if (!wt){Allocate2L(cdouble, I+J*2, hWid, wt, List);}
1196 if (!Q){Allocate2L(cdouble, I+J*2, hWid, Q, List);}
1197 if (!L){Allocate2L(double, I+J*2, I+J*2, L, List);}
1198 memset(wt[0], 0, sizeof(cdouble)*(I+J*2)*hWid);
1199 memset(Q[0], 0, sizeof(cdouble)*(I+J*2)*hWid);
1200 memset(L[0], 0, sizeof(double)*(I+J*2)*(I+J*2));
1201
1202 //*The direct form
1203 for (int i=0; i<I; i++)
1204 {
1205 Window(wt[i], f[i], Wid, M, c, 0, hWid-1);
1206 for (int k=0; k<hWid; k++) wt[i][k].rotate(ph[i]);
1207 }
1208 for (int j=0; j<J; j++)
1209 {
1210 cdouble *w1=wt[I+j*2], *w2=wt[I+j*2+1];
1211 Window(w1, f[I+j], Wid, M, c, 0, hWid-1);
1212 for (int k=0; k<hWid; k++) w2[k].y=w1[k].x, w2[k].x=-w1[k].y;
1213 }
1214
1215 LQ_GS(I+J*2, hWid*2, (double**)wt, L, (double**)Q);
1216 double *atl=MultiplyxYt(I+J*2, hWid*2, (double*)x, (double**)Q, List);
1217 GExL(I+J*2, a, L, atl);
1218
1219 for (int i=0; i<I+J*2; i++) MultiAdd(hWid, r, r, wt[i], -a[i]);
1220 for (int j=0; j<J; j++)
1221 {
1222 double xx=a[I+j*2], yy=a[I+j*2+1];
1223 a[I+j]=sqrt(xx*xx+yy*yy);
1224 ph[I+j]=atan2(yy, xx);
1225 }
1226 delete List;
1227 return r;
1228 }//IPMulti
1229
1230 //---------------------------------------------------------------------------
1231 /*
1232 Routines for estimation two sinusoids with 1 fixed and 1 flexible frequency
1233
1234 Further reading: "LSE estimation for 2 sinusoids with 1 at a fixed frequency.pdf"
1235 */
1236
1237 /*
1238 function WindowDuo: calcualtes the square norm of the inner product between windowed spectra of two
1239 sinusoids at frequencies f1 and f2, df=f1-f2.
1240
1241 In: df: frequency difference, in bins
1242 N: DFT size
1243 M, d[]: cosine-family window specification parameters (see "further reading").
1244 Out: w[0], the inner product, optional
1245
1246 Returns square norm of the inner product.
1247 */
1248 double WindowDuo(double df, int N, double* d, int M, cdouble* w)
1249 {
1250 double wr=0, wi=0;
1251 for (int m=-2*M; m<=2*M; m++)
1252 {
1253 double ang=df+m, Omg=ang*M_PI, omg=Omg/N;
1254 double si=sin(omg), co=cos(omg), sinn=sin(Omg);
1255 double sa=(ang==0)?N:(sinn/si);
1256 double dm; if (m<0) dm=d[-m]; else dm=d[m];
1257 wr+=dm*sa*co, wi+=-dm*sinn;
1258 }
1259 wr*=N, wi*=N;
1260 if (w) w->x=wr, w->y=wi;
1261 double result=wr*wr+wi*wi;
1262 return result;
1263 }//WindowDuo
1264
1265 /*
1266 function ddWindowDuo: calcualtes the square norm of the inner product between windowed spectra of two
1267 sinusoids at frequencies f1 and f2, df=f1-f2, with its 1st and 2nd derivatives
1268
1269 In: df: frequency difference, in bins
1270 N: DFT size
1271 M, d[]: cosine-family window specification parameters (see "further reading" for d[]).
1272 Out: w[0], the inner product, optional
1273 window, dwindow: square norm and its derivative, of the inner product
1274
1275 Returns 2nd derivative of the square norm of the inner product.
1276 */
1277 double ddWindowDuo(double df, int N, double* d, int M, double& dwindow, double& window, cdouble* w)
1278 {
1279 double wr=0, wi=0, dwr=0, dwi=0, ddwr=0, ddwi=0, PI_N=M_PI/N, PIPI_N=PI_N*M_PI, PIPI=M_PI*M_PI;
1280 for (int m=-2*M; m<=2*M; m++)
1281 {
1282 double ang=df+m, Omg=ang*M_PI, omg=Omg/N;
1283 double si=sin(omg), co=cos(omg), sinn=sin(Omg), cosn=cos(Omg);
1284 double sa=(ang==0)?N:(sinn/si), dsa=dsincd_unn(ang, N), ddsa=ddsincd_unn(ang, N);
1285 double dm; if (m<0) dm=d[-m]; else dm=d[m];
1286 wr+=dm*sa*co, wi+=-dm*sinn;
1287 dwr+=dm*(dsa*co-PI_N*sinn), dwi+=-dm*M_PI*cosn;
1288 ddwr+=dm*(ddsa*co-PI_N*dsa*si-PIPI_N*cosn), ddwi+=dm*PIPI*sinn;
1289 }
1290 wr*=N, wi*=N, dwr*=N, dwi*=N, ddwr*=N, ddwi*=N;
1291 window=wr*wr+wi*wi;
1292 dwindow=2*(wr*dwr+wi*dwi);
1293 if (w) w->x=wr, w->y=wi;
1294 double ddwindow=2*(wr*ddwr+dwr*dwr+wi*ddwi+dwi*dwi);
1295 return ddwindow;
1296 }//ddWindowDuo
1297
1298 /*
1299 function sIPWindowDuo: calculates the square norm of the orthogonal projection of a windowed spectrum
1300 onto the linear span of the windowed spectra of two sinusoids at reference frequencies f1 and f2.
1301
1302 In: x[N]: spectrum
1303 f1, f2: reference frequencies.
1304 M, c[], d[], iH2: cosine-family window specification parameters.
1305 K1, K2: spectrum truncation range, i.e. bins outside [K1, K2] are ignored.
1306 Out: lmd1, lmd2: projection coefficients, interpreted as actual amplitude-phase factors
1307
1308 Returns the square norm of the orthogonal projection.
1309 */
1310 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)
1311 {
1312 int K=K2-K1+1;
1313 cdouble xw1=0, *lx=&x[K1], *w1=new cdouble[K*2], *r1=&w1[K];
1314 Window(w1, f1, N, M, c, K1, K2);
1315 double w1w1=0;
1316 for (int k=0; k<K; k++) xw1+=(lx[k]^w1[k]), w1w1+=~w1[k]; cdouble mu1=xw1/w1w1;
1317 for (int k=0; k<K; k++) r1[k]=lx[k]-mu1*w1[k];
1318 Window(w1, f2, N, M, c, K1, K2);
1319 cdouble r1w2=0, w12; for (int k=0; k<K; k++) r1w2+=(r1[k]^w1[k]);
1320 double w=WindowDuo(f1-f2, N, d, M, &w12);
1321 double v=1.0/iH2-w*iH2;
1322 double result=~xw1/w1w1+~r1w2/v;
1323 cdouble mu2=r1w2/v;
1324 lmd2=mu2; lmd1=mu1-(mu2^w12)*iH2;
1325 delete[] w1;
1326 return result;
1327 }//sIPWindowDuo
1328 //wrapper function
1329 double sIPWindowDuo(double f2, void* params)
1330 {
1331 struct l_ip {int N; int k1; int k2; double* c; double* d; int M; double iH2; cdouble* x; double f1; double dipwindow; double ipwindow;} *p=(l_ip *)params;
1332 cdouble r1, r2;
1333 return sIPWindowDuo(p->f1, f2, p->x, p->N, p->c, p->d, p->M, p->iH2, p->k1, p->k2, r1, r2);
1334 }//sIPWindowDuo
1335
1336 /*
1337 function ddsIPWindowDuo: calculates the square norm, and its 1st and 2nd derivatives against f2,, of
1338 the orthogonal projection of a windowed spectrum onto the linear span of the windowed spectra of two
1339 sinusoids at reference frequencies f1 and f2.
1340
1341 In: x[N]: spectrum
1342 f1, f2: reference frequencies.
1343 M, c[], d[], iH2: cosine-family window specification parameters.
1344 K1, K2: spectrum truncation range, i.e. bins outside [K1, K2] are ignored.
1345
1346 Out: lmd1, lmd2: projection coefficients, interpreted as actual amplitude-phase factors
1347 ddsip[3]: the 2nd, 1st and 0th derivatives (against f2) of the square norm.
1348
1349 No return value.
1350 */
1351 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)
1352 {
1353 int K=K2-K1+1;
1354 cdouble xw1=0, *lx=&x[K1], *w1=new cdouble[K*2], *r1=&w1[K];
1355 Window(w1, f1, N, M, c, K1, K2);
1356 double w1w1=0;
1357 for (int k=0; k<K; k++) xw1+=(lx[k]^w1[k]), w1w1+=~w1[k]; cdouble mu1=xw1/w1w1;
1358 for (int k=0; k<K; k++) r1[k]=lx[k]-mu1*w1[k];
1359
1360 cdouble r1w2, w12;
1361 double u, du, ddu=ddsIPWindow_unn(f2, &r1[-K1], N, M, c, K1, K2, du, u, &r1w2);
1362 double w, dw, ddw=ddWindowDuo(f1-f2, N, d, M, dw, w, &w12); dw=-dw;
1363 double v=1.0/iH2-w*iH2, dv=-iH2*dw, ddv=-iH2*ddw;
1364 double iv=1.0/v;//, div=-dv*iv*iv, ddiv=(2*dv*dv-v*ddv)*iv*iv*iv;
1365
1366 ddsip2[2]=~xw1/w1w1+u*iv;
1367 ddsip2[1]=iv*(du-iv*u*dv);
1368 ddsip2[0]=iv*(ddu-iv*(u*ddv+2*du*dv-2*iv*u*dv*dv));
1369
1370 cdouble mu2=r1w2*iv;
1371 lmd2=mu2; lmd1=mu1-(mu2^w12)*iH2;
1372
1373 delete[] w1;
1374 }//ddsIPWindowDuo
1375 //wrapper function
1376 double ddsIPWindowDuo(double f2, void* params)
1377 {
1378 struct l_ip {int N; int k1; int k2; double* c; double* d; int M; double iH2; cdouble* x; double f1; double dipwindow; double ipwindow;} *p=(l_ip *)params;
1379 double ddsip2[3]; cdouble r1, r2;
1380 ddsIPWindowDuo(ddsip2, p->f1, f2, p->x, p->N, p->c, p->d, p->M, p->iH2, p->k1, p->k2, r1, r2);
1381 p->dipwindow=ddsip2[1], p->ipwindow=ddsip2[2];
1382 return ddsip2[0];
1383 }//ddsIPWindowDuo
1384
1385 /*
1386 function LSEDuo: least-square estimation of two sinusoids of which one has a fixed frequency
1387
1388 In: x[N]: the windowed spectrum
1389 f1: the fixed frequency
1390 f2: initial value of the flexible frequency
1391 fmin, fmax: search range for f2, the flexible frequency
1392 B: spectral truncation half width
1393 M, c[], d[], iH2:
1394 epf: frequency error tolerance
1395 Out: f2: frequency estimate
1396 lmd1, lmd2: amplitude-phase factor estimates
1397 Returns 1 if managed to find a good f2, 0 if not, upon which the initial f2 is used for estimating
1398
1399 amplitudes and phase angles.
1400 */
1401 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)
1402 {
1403 int result=0;
1404 double inp=f2;
1405 int k1=ceil(inp-B); if (k1<0) k1=0;
1406 int k2=floor(inp+B); if (k2>=N/2) k2=N/2-1;
1407 struct l_hx {int N; int k1; int k2; double* c; double* d; int M; double iH2; cdouble* x; double f1; double dipwindow; double ipwindow;} p={N, k1, k2, c, d, M, iH2, x, f1, 0, 0};
1408 int dfshift=int(&((l_hx*)0)->dipwindow);// fshift=int(&((l_hx*)0)->ipwindow);
1409
1410 double tmp=Newton(f2, ddsIPWindowDuo, &p, dfshift, epf, 100, 1e-256, fmin, fmax);
1411 if (tmp!=-1 && f2>fmin && f2<fmax) result=1;
1412 else
1413 {
1414 Search1DmaxEx(f2, &p, sIPWindowDuo, fmin, fmax, NULL, epf);
1415 if (f2<=fmin || f2>=fmax) f2=inp;
1416 else result=1;
1417 }
1418 sIPWindowDuo(f1, f2, x, N, c, d, M, iH2, k1, k2, r1, r2);
1419 return result;
1420 }//LSEDuo
1421
1422 //---------------------------------------------------------------------------
1423 /*
1424 Time-frequency reassignment sinusoid estimation routines.
1425
1426 Further reading: A. R?bel, ¡°Estimating partial frequency and frequency slope using reassignment
1427 operators,¡± in Proc. ICMC¡¯02. G?teborg. 2002.
1428 */
1429
1430 /*
1431 function CDFTW: single-frequency windowed DTFT, centre-aligned
1432
1433 In: data[Wid]: waveform data x
1434 win[Wid+1]: window function
1435 k: frequency, in bins, where bin=1/Wid
1436 Out: X: DTFT of xw at frequency k bins
1437
1438 No return value.
1439 */
1440 void CDFTW(cdouble& X, double k, int Wid, cdouble* data, double* win)
1441 {
1442 X=0;
1443 int hWid=Wid/2;
1444 for (int i=0; i<Wid; i++)
1445 {
1446 cdouble tmp=data[i]*win[Wid-i];
1447 double ph=-2*M_PI*(i-hWid)*k/Wid;
1448 tmp.rotate(ph);
1449 X+=tmp;
1450 }
1451 }//CDFTW
1452
1453 /*
1454 function CuDFTW: single-frequency windowed DTFT of t*data[t], centre-aligned
1455
1456 In: data[Wid]: waveform data x
1457 wid[Wid+1]: window function
1458 k: frequency, in bins
1459 Out: X: DTFT of txw at frequency k bins
1460
1461 No return value.
1462 */
1463 void CuDFTW(cdouble& X, int k, int Wid, cdouble* data, double* win)
1464 {
1465 X=0;
1466 int hWid=Wid/2;
1467 for (int i=0; i<Wid; i++)
1468 {
1469 double tw=((i-hWid)*win[Wid-i]);
1470 cdouble tmp=data[i]*tw;
1471 double ph=-2*M_PI*(i-hWid)*k/Wid;
1472 tmp.rotate(ph);
1473 X+=tmp;
1474 }
1475 }//CuDFTW
1476
1477 /*
1478 function TFReas: time-frequency reassignment
1479
1480 In: data[Wid]: waveform data
1481 win[Wid+1], dwin[Wid+1], ddwin[Wid+1]: window function and its derivatives
1482 f, t: initial digital frequency and time
1483 Out: f, t: reassigned digital frequency and time
1484 fslope: estimate of frequency derivative
1485 plogaslope[0]: estimate of the derivative of logarithmic amplitude, optional
1486
1487 No return value.
1488 */
1489 void TFReas(double& f, double& t, double& fslope, int Wid, cdouble* data, double* win, double* dwin, double* ddwin, double* plogaslope)
1490 {
1491 int fi=floor(f*Wid+0.5);
1492
1493 cdouble x, xt, xw;
1494 CDFTW(x, fi, Wid, data, win);
1495 CuDFTW(xw, fi, Wid, data, win); xt.x=xw.y; xw.y=-xw.x; xw.x=xt.x;
1496 CDFTW(xt, fi, Wid, data, dwin);
1497 double px=~x;
1498 t=t-(xw.y*x.x-xw.x*x.y)/px;
1499 f=1.0*fi/Wid+(xt.y*x.x-xt.x*x.y)/px/(2*M_PI);
1500 if (plogaslope) plogaslope[0]=-(xt.x*x.x+xt.y*x.y)/px;
1501 cdouble xtt, xtw;
1502 CuDFTW(xtw, fi, Wid, data, dwin); xtt.x=xtw.y; xtw.y=-xtw.x; xtw.x=xtt.x;
1503 CDFTW(xtt, fi, Wid, data, ddwin);
1504 double dtdt=-(xtw.y*x.x-xtw.x*x.y)/px+((xt.y*x.x-xt.x*x.y)*(xw.x*x.x+xw.y*x.y)+(xt.x*x.x+xt.y*x.y)*(xw.y*x.x-xw.x*x.y))/px/px,
1505 dwdt=(xtt.y*x.x-xtt.x*x.y)/px-2*(xt.x*x.x+xt.y*x.y)*(xt.y*x.x-xt.x*x.y)/px/px;
1506 if (dtdt!=0) fslope=dwdt/dtdt/(2*M_PI);
1507 else fslope=0;
1508 } //TFReas*/
1509
1510 /*
1511 function TFReas: sinusoid estimation using reassignment method
1512
1513 In: data[Wid]: waveform data
1514 w[Wid+1], dw[Wid+1], ddw[Wid+1]: window function and its derivatives
1515 win[Wid]: window function used for estimating amplitude and phase by projection onto a chirp
1516 t: time for which the parameters are estimated
1517 f: initial frequency at t
1518 Out: f, a, ph: digital frequency, amplitude and phase angle estimated at t
1519 fslope: frequency derivative estimate
1520
1521 No return value.
1522 */
1523 void TFReas(double& f, double t, double& a, double& ph, double& fslope, int Wid, cdouble* data, double* w, double* dw, double* ddw, double* win)
1524 {
1525 double localt=t, logaslope;
1526 TFReas(f, localt, fslope, Wid, data, w, dw, ddw, &logaslope);
1527
1528 if (logaslope*Wid>6) logaslope=6.0/Wid;
1529 else if (logaslope*Wid<-6) logaslope=-6.0/Wid;
1530
1531 f=f+fslope*(t-localt); //obtain frequency estimate at t
1532
1533 cdouble x=0;
1534 if (win==0)
1535 {
1536 for (int n=0; n<Wid; n++)
1537 {
1538 double ni=n-t;
1539 cdouble tmp=data[n];
1540 double p=-2*M_PI*(f+0.5*fslope*ni)*ni;
1541 tmp.rotate(p);
1542 x+=tmp;
1543 }
1544 a=abs(x)/Wid;
1545 }
1546 else
1547 {
1548 double sumwin=0;
1549 for (int n=0; n<Wid; n++)
1550 {
1551 double ni=n-t;
1552 cdouble tmp=data[n]*win[n];
1553 double p=-2*M_PI*(f+0.5*fslope*ni)*ni;
1554 tmp.rotate(p);
1555 x+=tmp; sumwin+=win[n];
1556 }
1557 a=abs(x)/sumwin;
1558 }
1559 ph=arg(x);
1560 }//TFReas
1561
1562 //---------------------------------------------------------------------------
1563 /*
1564 Routines for additive and multiplicative reestimation of sinusoids.
1565
1566 Further reading: Wen X. and M. Sandler, "Additive and multiplicative reestimation schemes
1567 for the sinusoid modeling of audio," in Proc. EUSIPCO'09, Glasgow, 2009.
1568 */
1569
1570 /*
1571 function AdditiveUpdate: additive reestimation of time-varying sinusoid
1572
1573 In: x[Count]: waveform data
1574 Wid, Offst: frame size and hop
1575 fs[Count], as[Count], phs[Count]: initial estimate of sinusoid parameters
1576 das[Count]: initial estimate of amplitude derivative
1577 BasicAnalyzer: pointer to a sinusoid analyzer
1578 LogA: indicates if amplitudes are interpolated at cubic spline or exponential cubic spline
1579 Out: fs[Count], as[Count], phs[Count], das[Count]: estimates after additive update
1580
1581 No return value.
1582 */
1583 void AdditiveUpdate(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA)
1584 {
1585 int HWid=Wid/2, Fr=(Count-Wid)/Offst+1;
1586
1587 for (int fr=0; fr<Fr; fr++)
1588 {
1589 int i=HWid+Offst*fr;
1590 if (fs[i]<0 || fs[i]>0.5){}
1591 }
1592
1593 cdouble *y=new cdouble[Count];
1594 double *lf=new double[Count*4], *la=&lf[Count], *lp=&lf[Count*2], *lda=&lf[Count*3];
1595
1596 __int16* ref=new __int16[Count];
1597 for (int i=0; i<Count; i++) y[i]=x[i].x-as[i]*cos(phs[i]), ref[i]=floor(fs[i]*Wid+0.5);
1598 memcpy(lf, fs, sizeof(double)*Count);
1599 BasicAnalyzer(lf, la, lp, lda, y, Count, Wid, Offst, ref, reserved, LogA);
1600
1601 //merge and interpolate
1602 double *fa=new double[Fr*12], *fb=&fa[Fr], *fc=&fa[Fr*2], *fd=&fa[Fr*3],
1603 *aa=&fa[Fr*4], *ab=&aa[Fr], *ac=&aa[Fr*2], *ad=&aa[Fr*3],
1604 *xs=&fa[Fr*8], *ffr=&xs[Fr], *afr=&xs[Fr*2], *pfr=&xs[Fr*3];
1605 for (int fr=0; fr<Fr; fr++)
1606 {
1607 int i=HWid+Offst*fr;
1608 double a=as[i], b=la[i], fai=phs[i], thet=lp[i], f=fs[i], g=lf[i], delt=fai-thet, da=das[i], db=lda[i];
1609 xs[fr]=i;
1610 if (fabs(f-g)*Wid>1)
1611 {
1612 afr[fr]=a, pfr[fr]=fai, ffr[fr]=f;
1613 }
1614 else
1615 {
1616 double rr=a*cos(fai)+b*cos(thet);
1617 double ii=a*sin(fai)+b*sin(thet);
1618 ffr[fr]=(a*f*(a+b*cos(delt))+b*g*(b+a*cos(delt))+(da*b-a*db)*sin(delt)/(2*M_PI))/(a*a+b*b+2*a*b*cos(delt));
1619 afr[fr]=sqrt(rr*rr+ii*ii);
1620 pfr[fr]=atan2(ii, rr);
1621 }
1622 if (LogA) afr[fr]=log(afr[fr]);
1623 }
1624 CubicSpline(Fr-1, fa, fb, fc, fd, xs, ffr, 1, 1);
1625 CubicSpline(Fr-1, aa, ab, ac, ad, xs, afr, 1, 1);
1626 for (int fr=0; fr<Fr-1; fr++) Sinusoid(&fs[int(xs[fr])], &as[int(xs[fr])], &phs[int(xs[fr])], &das[int(xs[fr])], 0, Offst, aa[fr], ab[fr], ac[fr], ad[fr], fa[fr], fb[fr], fc[fr], fd[fr], pfr[fr], pfr[fr+1], LogA);
1627 Sinusoid(&fs[int(xs[0])], &as[int(xs[0])], &phs[int(xs[0])], &das[int(xs[0])], -HWid, 0, aa[0], ab[0], ac[0], ad[0], fa[0], fb[0], fc[0], fd[0], pfr[0], pfr[1], LogA);
1628 Sinusoid(&fs[int(xs[Fr-2])], &as[int(xs[Fr-2])], &phs[int(xs[Fr-2])], &das[int(xs[Fr-2])], Offst, Offst+HWid, aa[Fr-2], ab[Fr-2], ac[Fr-2], ad[Fr-2], fa[Fr-2], fb[Fr-2], fc[Fr-2], fd[Fr-2], pfr[Fr-2], pfr[Fr-1], LogA);
1629 delete[] fa; //*/
1630 /*
1631 for (int i=0; i<Count; i++)
1632 {
1633 double rr=as[i]*cos(phs[i])+la[i]*cos(lp[i]);
1634 double ii=as[i]*sin(phs[i])+la[i]*sin(lp[i]);
1635 as[i]=sqrt(rr*rr+ii*ii);
1636 phs[i]=atan2(ii, rr);
1637 } //*/
1638 for (int fr=0; fr<Fr; fr++)
1639 {
1640 int i=HWid+Offst*fr;
1641 if (fs[i]<0 || fs[i]>0.5){}
1642 }
1643 delete[] y; delete[] lf; delete[] ref;
1644 }//AdditiveUpdate
1645
1646 /*
1647 function AdditiveAnalyzer: sinusoid analyzer with one additive update
1648
1649 In: x[Count]: waveform data
1650 Wid, Offst: frame size and hop size
1651 BasicAnalyzer: pointer to a sinusoid analyzer
1652 ref[Count]: reference frequencies, in bins, used by BasicAnalyzer
1653 BasicAnalyzer: pointer to a sinusoid analyzer
1654 LogA: indicates if amplitudes are interpolated at cubic spline or exponential cubic spline
1655 Out: fs[Count], as[Count], phs[Count]: sinusoid parameter estimates
1656 das[Count]: estimate of amplitude derivative
1657
1658 No return value.
1659 */
1660 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)
1661 {
1662 BasicAnalyzer(fs, as, phs, das, x, Count, Wid, Offst, ref, reserved, LogA);
1663 AdditiveUpdate(fs, as, phs, das, x, Count, Wid, Offst, BasicAnalyzer, reserved, LogA);
1664 }//AdditiveAnalyzer
1665
1666 /*
1667 function MultiplicativeUpdate: multiplicative reestimation of time-varying sinusoid
1668
1669 In: x[Count]: waveform data
1670 Wid, Offst: frame size and hop
1671 fs[Count], as[Count], phs[Count]: initial estimate of sinusoid parameters
1672 das[Count]: initial estimate of amplitude derivative
1673 BasicAnalyzer: pointer to a sinusoid analyzer
1674 LogA: indicates if amplitudes are interpolated at cubic spline or exponential cubic spline
1675 Out: fs[Count], as[Count], phs[Count], das[Count]: estimates after additive update
1676
1677 No return value.
1678 */
1679 void MultiplicativeUpdate(double* fs, double* as, double* phs, double* das, cdouble* x, int Count, int Wid, int Offst, TBasicAnalyzer BasicAnalyzer, int reserved, bool LogA)
1680 {
1681 int HWid=Wid/2;
1682 cdouble *y=new cdouble[Count];
1683 double *lf=new double[Count*8], *la=&lf[Count], *lp=&lf[Count*2], *lda=&lf[Count*3],
1684 *lf2=&lf[Count*4], *la2=&lf2[Count], *lp2=&lf2[Count*2], *lda2=&lf2[Count*3];
1685 __int16 *lref=new __int16[Count];
1686
1687 for (int i=0; i<Count; i++) y[i]=x[i]*(cdouble(1.0).rotate(-phs[i]+i*0.15*2*M_PI)),
1688 lref[i]=0.15*Wid;
1689 BasicAnalyzer(lf, la, lp, lda, y, Count, Wid, Offst, lref, reserved, LogA);
1690 for (int i=0; i<Count; i++) y[i]=y[i]*(cdouble(1.0/la[i]).rotate(-lp[i]+i*0.15*2*M_PI)), lref[i]=0.15*Wid;
1691 BasicAnalyzer(lf2, la2, lp2, lda2, y, Count, Wid, Offst, lref, reserved, LogA);
1692
1693 /*
1694 for (int i=0; i<Count; i++)
1695 {
1696 as[i]=la[i]*la2[i];
1697 phs[i]=phs[i]+lp[i]+lp2[i]-0.3*2*M_PI*i;
1698 fs[i]=fs[i]+lf[i]+lf2[i]-0.3;
1699 } //*/
1700
1701 //merge
1702 int Fr=(Count-Wid)/Offst+1;
1703 double *fa=new double[Fr*12], *fb=&fa[Fr], *fc=&fa[Fr*2], *fd=&fa[Fr*3],
1704 *aa=&fa[Fr*4], *ab=&aa[Fr], *ac=&aa[Fr*2], *ad=&aa[Fr*3],
1705 *xs=&fa[Fr*8], *ffr=&xs[Fr], *afr=&xs[Fr*2], *pfr=&xs[Fr*3];
1706 for (int fr=0; fr<Fr; fr++)
1707 {
1708 int i=HWid+Offst*fr;
1709 xs[fr]=i;
1710 afr[fr]=la[i]*la2[i];
1711 if (LogA) afr[fr]=log(afr[fr]);
1712 ffr[fr]=fs[i]+lf[i]-0.15+lf2[i]-0.15;
1713 pfr[fr]=phs[i]+lp[i]+lp2[i]-0.3*i*2*M_PI;
1714 }
1715 CubicSpline(Fr-1, fa, fb, fc, fd, xs, ffr, 1, 1);
1716 CubicSpline(Fr-1, aa, ab, ac, ad, xs, afr, 1, 1);
1717 for (int fr=0; fr<Fr-1; fr++) Sinusoid(&fs[int(xs[fr])], &as[int(xs[fr])], &phs[int(xs[fr])], &das[int(xs[fr])], 0, Offst, aa[fr], ab[fr], ac[fr], ad[fr], fa[fr], fb[fr], fc[fr], fd[fr], pfr[fr], pfr[fr+1], LogA);
1718 Sinusoid(&fs[int(xs[0])], &as[int(xs[0])], &phs[int(xs[0])], &das[int(xs[0])], -HWid, 0, aa[0], ab[0], ac[0], ad[0], fa[0], fb[0], fc[0], fd[0], pfr[0], pfr[1], LogA);
1719 Sinusoid(&fs[int(xs[Fr-2])], &as[int(xs[Fr-2])], &phs[int(xs[Fr-2])], &das[int(xs[Fr-2])], Offst, Offst+HWid, aa[Fr-2], ab[Fr-2], ac[Fr-2], ad[Fr-2], fa[Fr-2], fb[Fr-2], fc[Fr-2], fd[Fr-2], pfr[Fr-2], pfr[Fr-1], LogA);
1720 delete[] fa; //*/
1721
1722 for (int fr=0; fr<Fr; fr++)
1723 {
1724 int i=HWid+Offst*fr;
1725 if (fs[i]<0 || fs[i]>0.5){}
1726 }
1727
1728 delete[] y; delete[] lf; delete[] lref;
1729 }//MultiplicativeUpdate
1730
1731 /*
1732 function MultiplicativeAnalyzer: sinusoid analyzer with one multiplicative update
1733
1734 In: x[Count]: waveform data
1735 Wid, Offst: frame size and hop size
1736 BasicAnalyzer: pointer to a sinusoid analyzer
1737 ref[Count]: reference frequencies, in bins, used by BasicAnalyzer
1738 BasicAnalyzer: pointer to a sinusoid analyzer
1739 LogA: indicates if amplitudes are interpolated at cubic spline or exponential cubic spline
1740 Out: fs[Count], as[Count], phs[Count]: sinusoid parameter estimates
1741 das[Count]: estimate of amplitude derivative
1742
1743 No return value.
1744 */
1745 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)
1746 {
1747 BasicAnalyzer(fs, as, phs, das, x, Count, Wid, Offst, ref, reserved, LogA);
1748 MultiplicativeUpdate(fs, as, phs, das, x, Count, Wid, Offst, BasicAnalyzer, reserved);
1749 }//MultiplicativeAnalyzer
1750
1751 /*
1752 This is an earlier version of the multiplicative method without using a user-provided BasicAnalyzer.
1753 This updates the sinusoid estimates at the selected consecutive FRAMES of x. Only frequency modulation
1754 is included in the multiplier. The first frame (0) is centred at x[Wid/2]. fs, as, and phs are based
1755 on frames rather than samples. Updates include frame frst, but not frame fren.
1756 */
1757 void MultiplicativeUpdateF(double* fs, double* as, double* phs, __int16* x, int Fr, int frst, int fren, int Wid, int Offst)
1758 {
1759 int HWid=Wid/2;
1760
1761 double *fa=new double[Fr*12], *fb=&fa[Fr], *fc=&fa[Fr*2], *fd=&fa[Fr*3],
1762 *xs=&fa[Fr*8];
1763 for (int fr=0; fr<Fr; fr++) xs[fr]=HWid+Offst*fr;
1764 CubicSpline(Fr-1, fa, fb, fc, fd, xs, fs, 1, 1);
1765
1766 int dst=Offst*frst, den=Offst*(fren-1)+Wid, dcount=den-dst;
1767 double *f=new double[dcount*2], *ph=&f[dcount];
1768 for (int fr=frst; fr<fren-1; fr++) Sinusoid(&f[int(xs[fr])-dst], &ph[int(xs[fr])-dst], 0, Offst, fa[fr], fb[fr], fc[fr], fd[fr], phs[fr], phs[fr+1]);
1769 if (frst==0) Sinusoid(&f[int(xs[0])-dst], &ph[int(xs[0])-dst], -HWid, 0, fa[0], fb[0], fc[0], fd[0], phs[0], phs[1]);
1770 else Sinusoid(&f[int(xs[frst-1])-dst], &ph[int(xs[frst-1])-dst], 0, Offst, fa[frst-1], fb[frst-1], fc[frst-1], fd[frst-1], phs[frst-1], phs[frst]);
1771 if (fren==Fr) Sinusoid(&f[int(xs[fren-2])-dst], &ph[int(xs[fren-2])-dst], Offst, Offst+HWid, fa[fren-2], fb[fren-2], fc[fren-2], fd[fren-2], phs[fren-2], phs[fren-1]);
1772 else Sinusoid(&f[int(xs[fren-1])-dst], &ph[int(xs[fren-1])-dst], 0, Offst, fa[fren-1], fb[fren-1], fc[fren-1], fd[fren-1], phs[fren-1], phs[fren]);
1773
1774 cdouble* y=new cdouble[Wid];
1775 AllocateFFTBuffer(Wid, Amp, W, X);
1776 double* win=NewWindow(wtHann, Wid);
1777 int M; double c[10], iH2; windowspec(wtHann, Wid, &M, c, &iH2);
1778 for (int fr=frst; fr<fren; fr++)
1779 {
1780 __int16* lx=&x[Offst*fr];
1781 double* lph=&ph[Offst*(fr-frst)];
1782 for (int i=0; i<Wid; i++) y[i]=cdouble(lx[i]).rotate(-lph[i]+i*0.15*2*M_PI);
1783 CFFTCW(y, win, Amp, 0, log2(Wid), W, X);
1784 int pf=0.15*Wid, mpf=pf;
1785 for (int k=pf-4; k<=pf+4; k++) if (Amp[k]>Amp[mpf]) mpf=k;
1786 if (mpf>pf-4 && mpf<pf+4) pf=mpf;
1787 double lfs=pf, lphs;
1788 LSESinusoid(lfs, pf-3, pf+3, X, Wid, 3, M, c, iH2, as[fr], lphs, 1e-3);
1789 fs[fr]=fs[fr]+lfs/Wid-0.15;
1790 phs[fr]+=lphs-0.15*Wid*M_PI;
1791 as[fr]*=2;
1792 }
1793
1794 delete[] y;
1795 delete[] f;
1796 delete[] win;
1797 delete[] fa;
1798 FreeFFTBuffer(Amp);
1799 }//MultiplicativeUpdateF
1800
1801 //---------------------------------------------------------------------------
1802 /*
1803 Earlier reestimation method routines.
1804
1805 Further reading: Wen X. and M. Sandler, "Evaluating parameters of time-varying
1806 sinusoids by demodulation," in Proc. DAFx'08, Espoo, 2008.
1807 */
1808
1809 /*
1810 function ReEstFreq: sinusoid reestimation by demodulating frequency.
1811
1812 In: x[Wid+Offst*(FrCount-1)]: waveform data
1813 FrCount, Wid, Offst: frame count, frame size and hop size
1814 fbuf[FrCount], ns[FrCount]: initial frequency estiamtes and their timing
1815 win[Wid]: window function for estimating demodulated sinusoid
1816 M, c[], iH2: cosine-family window specification parameters, must be consistent with win[]
1817 Wids[FrCount]: specifies frame sizes for estimating individual frames of demodulated sinusoid, optional
1818 w[Wid/2], ps[Wid], xs[Wid], xc[Wid], fa[FrCount-1], fb[FrCount-1], fc[FrCount-1], fd[FrCount-1]: buffers
1819 Out: fbuf[FrCount], abuf[FrCount], pbuf[FrCount]: reestimated frequencies, amplitudes and phase angles
1820
1821 No return value.
1822 */
1823 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)
1824 {
1825 int hWid=Wid/2;
1826 //reestimate using frequency track
1827 CubicSpline(FrCount-1, fa, fb, fc, fd, ns, fbuf, 0, 1);
1828 for (int fr=0; fr<FrCount; fr++)
1829 {
1830 //find ps
1831 if (fr==0)
1832 {
1833 double lfd=0, lfc=fc[0], lfb=fb[0], lfa=fa[0];
1834 for (int j=0; j<Wid; j++)
1835 {
1836 double lx=j-hWid;
1837 ps[j]=2*M_PI*lx*(lfd+lx*(lfc/2+lx*(lfb/3+lx*lfa/4)));
1838 }
1839 // memset(ps, 0, sizeof(double)*hWid);
1840 }
1841 else if (fr==FrCount-1)
1842 {
1843 int lfr=FrCount-2;
1844 double lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
1845 double lfd=-(hWid*(lfc+hWid*(lfb+hWid*lfa)));
1846 ps[0]=-2*M_PI*hWid*(lfd+hWid*(lfc/2+hWid*(lfb/3+hWid*lfa/4)));
1847 for (int j=1; j<Wid; j++)
1848 {
1849 ps[j]=ps[0]+2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
1850 }
1851 // memset(&ps[hWid], 0, sizeof(double)*hWid);
1852 }
1853 else
1854 {
1855 int lfr=fr-1;
1856 double lfd=fd[lfr]-fd[fr], lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
1857 ps[0]=-2*M_PI*hWid*(lfd+hWid*(lfc/2+hWid*(lfb/3+hWid*lfa/4)));
1858 for (int j=1; j<hWid+1; j++)
1859 {
1860 ps[j]=ps[0]+2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
1861 }
1862 lfr=fr;
1863 lfd=0, lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
1864 for (int j=1; j<hWid; j++)
1865 {
1866 ps[j+hWid]=2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
1867 }
1868 }
1869 double* ldata=&x[fr*Offst];
1870 for (int j=0; j<Wid; j++)
1871 {
1872 xs[j].x=ldata[j]*cos(-ps[j]);
1873 xs[j].y=ldata[j]*sin(-ps[j]);
1874 }
1875
1876 if (Wids)
1877 {
1878 int lWid=Wids[fr], lhWid=Wids[fr]/2, lM;
1879 SetTwiddleFactors(lWid, w);
1880 double *lwin=NewWindow(wtHann, lWid), lc[4], liH2;
1881 windowspec(wtHann, lWid, &lM, lc, &liH2);
1882 CFFTCW(&xs[hWid-lhWid], lwin, NULL, NULL, log2(lWid), w, xc);
1883 delete[] lwin;
1884 double lf=fbuf[fr]*lWid, la, lp;
1885 LSESinusoid(lf, lf-3, lf+3, xc, lWid, 3, lM, lc, liH2, la, lp, 1e-3);
1886 if (la*2>abuf[fr]) fbuf[fr]=lf/lWid, abuf[fr]=la*2, pbuf[fr]=lp;
1887 }
1888 else
1889 {
1890 CFFTCW(xs, win, NULL, NULL, log2(Wid), w, xc);
1891 double lf=fbuf[fr]*Wid, la, lp;
1892 LSESinusoid(lf, lf-3, lf+3, xc, Wid, 3, M, c, iH2, la, lp, 1e-3);
1893 if (la*2>abuf[fr])
1894 fbuf[fr]=lf/Wid, abuf[fr]=la*2, pbuf[fr]=lp;
1895 }
1896 }
1897 }//ReEstFreq
1898
1899 /*
1900 function ReEstFreq_2: sinusoid reestimation by demodulating frequency. This is that same as ReEstFreq(...)
1901 except that it calls Sinusoid(...) to synthesize the phase track used for demodulation and that it
1902 does not allow variable window sizes for estimating demodulated sinusoid.
1903
1904 In: x[Wid+Offst*(FrCount-1)]: waveform data
1905 FrCount, Wid, Offst: frame count, frame size and hop size
1906 fbuf[FrCount], ns[FrCount]: initial frequency estiamtes and their timing
1907 win[Wid]: window function for LSE sinusoid estimation
1908 M, c[], iH2: cosine-family window specification parameters, must be consistent with M, c, iH2
1909 w[Wid/2], xs[Wid], xc[Wid], f3[FrCount-1], f2[FrCount-1], f1[FrCount-1], f0[FrCount-1]: buffers
1910 Out: fbuf[FrCount], abuf[FrCount], pbuf[FrCount]: reestimated frequencies, amplitudes and phase angles
1911
1912 No return value.
1913 */
1914 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)
1915 {
1916 int hWid=Wid/2;
1917 //reestimate using frequency track
1918 CubicSpline(FrCount-1, f3, f2, f1, f0, ns, fbuf, 1, 1);
1919 double *refcos=(double*)malloc8(sizeof(double)*Wid), *refsin=&refcos[hWid], ph=0, centralph;
1920
1921 memset(f0, 0, sizeof(double)*FrCount);
1922
1923 int N=Wid+Offst*(FrCount-1);
1924 double* cosine=new double[N], *sine=new double[N];
1925 Sinusoid(&cosine[hWid], &sine[hWid], -hWid, 0, f3[0], f2[0], f1[0], f0[0], ph);
1926 for (int fr=0; fr<FrCount-1; fr++)
1927 {
1928 int ncentre=hWid+Offst*fr;
1929 if (fr==FrCount-2) Sinusoid(&cosine[ncentre], &sine[ncentre], 0, Wid, f3[fr], f2[fr], f1[fr], f0[fr], ph);
1930 else Sinusoid(&cosine[ncentre], &sine[ncentre], 0, hWid, f3[fr], f2[fr], f1[fr], f0[fr], ph);
1931 }
1932 double err=0;
1933 for (int n=0; n<N; n++) {double tmp=cosine[n]-x[n-hWid]; err+=tmp*tmp; tmp=cosine[n]*cosine[n]+sine[n]*sine[n]-1; err+=tmp*tmp;}
1934
1935 ph=0;
1936 for (int fr=0; fr<FrCount; fr++)
1937 {
1938 double* ldata=&x[fr*Offst-hWid];
1939
1940 //store first half of demodulated frame to xs[0:hWid-1]
1941 if (fr==0)
1942 {
1943 Sinusoid(&refcos[hWid], &refsin[hWid], -hWid, 0, f3[0], f2[0], f1[0], f0[0], ph);
1944 for (int i=0; i<hWid; i++) xs[i].x=ldata[i]*refcos[i], xs[i].y=-ldata[i]*refsin[i];
1945 }
1946 else
1947 {
1948 ph=0;
1949 Sinusoid(refcos, refsin, 0, hWid, f3[fr-1], f2[fr-1], f1[fr-1], f0[fr-1], ph);
1950 for (int i=0; i<hWid; i++) xs[i].x=ldata[i]*refcos[i], xs[i].y=-ldata[i]*refsin[i];
1951 }
1952
1953 //taking care of phase angles
1954 if (fr==FrCount-1) {double tmp=ph; ph=centralph; centralph=tmp;}
1955 else centralph=ph;
1956
1957 double *lrefcos=&refcos[-hWid], *lrefsin=&refsin[-hWid];
1958 //store second half of demodulated frame to xs[hWid:Wid-1]
1959 if (fr==FrCount-1)
1960 {
1961 Sinusoid(lrefcos, lrefsin, hWid, Wid, f3[FrCount-2], f2[FrCount-2], f1[FrCount-2], f0[FrCount-2], ph);
1962 for (int i=hWid; i<Wid; i++) xs[i].x=ldata[i]*lrefcos[i], xs[i].y=-ldata[i]*lrefsin[i];
1963 }
1964 else
1965 {
1966 Sinusoid(refcos, refsin, 0, hWid, f3[fr], f2[fr], f1[fr], f0[fr], ph);
1967 for (int i=hWid; i<Wid; i++) xs[i].x=ldata[i]*lrefcos[i], xs[i].y=-ldata[i]*lrefsin[i];
1968 }
1969
1970 CFFTCW(xs, win, NULL, NULL, log2(Wid), w, xc);
1971 double lf=fbuf[fr]*Wid, la, lp;
1972 LSESinusoid(lf, lf-3, lf+3, xc, Wid, 3, M, c, iH2, la, lp, 1e-3);
1973 if (la*2>abuf[fr])
1974 fbuf[fr]=lf/Wid, abuf[fr]=la*2, pbuf[fr]=lp+centralph;
1975 }
1976 }//ReEstFreq_2
1977
1978 /*
1979 function ReEstFreqAmp: sinusoid reestimation by demodulating frequency and amplitude.
1980
1981 In: x[Wid+Offst*(FrCount-1)]: waveform data
1982 FrCount, Wid, Offst: frame count, frame size and hop size
1983 fbuf[FrCount], abuf[FrCount], ns[FrCount]: initial frequency and amplitude estiamtes and their
1984 timing
1985 win[Wid]: window function for estimating demodulated sinusoid
1986 M, c[], iH2: cosine-family window specification parameters, must be consistent with win[]
1987 Wids[FrCount]: specifies frame sizes for estimating individual frames of demodulated sinusoid,
1988 optional
1989 w[Wid/2], ps[Wid], xs[Wid], xc[Wid]: buffers
1990 fa[FrCount-1], fb[FrCount-1], fc[FrCount-1], fd[FrCount-1]: buffers
1991 aa[FrCount-1], ab[FrCount-1], ac[FrCount-1], ad[FrCount-1]: buffers
1992 Out: fbuf[FrCount], abuf[FrCount], pbuf[FrCount]: reestimated frequencies, amplitudes and phase angles
1993
1994 No return value.
1995 */
1996 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)
1997 {
1998 int hWid=Wid/2;
1999 //reestimate using amplitude and frequency track
2000 CubicSpline(FrCount-1, fa, fb, fc, fd, ns, fbuf, 0, 1);
2001 CubicSpline(FrCount-1, aa, ab, ac, ad, ns, abuf, 0, 1);
2002 for (int fr=0; fr<FrCount; fr++)
2003 {
2004 if (fr==0)
2005 {
2006 double lfd=0, lfc=fc[0], lfb=fb[0], lfa=fa[0],
2007 lad=ad[0], lac=ac[0], lab=ab[0], laa=aa[0];
2008 for (int j=0; j<Wid; j++)
2009 {
2010 double lx=j-hWid;
2011 ps[j]=2*M_PI*lx*(lfd+lx*(lfc/2+lx*(lfb/3+lx*lfa/4)));
2012 }
2013 for (int j=0; j<Wid; j++)
2014 {
2015 double lx=j-hWid;
2016 as[j]=lad+lx*(lac+lx*(lab+lx*laa));
2017 }
2018 }
2019 else if (fr==FrCount-1)
2020 {
2021 int lfr=FrCount-2;
2022 double lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
2023 double lfd=-(hWid*(lfc+hWid*(lfb+hWid*lfa)));
2024 double lad=ad[lfr], lac=ac[lfr], lab=ab[lfr], laa=aa[lfr];
2025 ps[0]=-2*M_PI*hWid*(lfd+hWid*(lfc/2+hWid*(lfb/3+hWid*lfa/4)));
2026 for (int j=1; j<Wid; j++)
2027 {
2028 ps[j]=ps[0]+2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
2029 }
2030 as[0]=ad[lfr];
2031 for (int j=0; j<Wid; j++)
2032 {
2033 as[j]=lad+j*(lac+j*(lab+j*laa));
2034 }
2035 }
2036 else
2037 {
2038 int lfr=fr-1;
2039 double lfd=fd[lfr]-fd[fr], lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
2040 double lad=ad[lfr], lac=ac[lfr], lab=ab[lfr], laa=aa[lfr];
2041 ps[0]=-2*M_PI*hWid*(lfd+hWid*(lfc/2+hWid*(lfb/3+hWid*lfa/4)));
2042 for (int j=0; j<hWid+1; j++)
2043 {
2044 ps[j]=ps[0]+2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
2045 as[j]=lad+j*(lac+j*(lab+j*laa));
2046 }
2047 lfr=fr;
2048 lfd=0, lfc=fc[lfr], lfb=fb[lfr], lfa=fa[lfr];
2049 lad=ad[lfr], lac=ac[lfr], lab=ab[lfr], laa=aa[lfr];
2050 for (int j=1; j<hWid; j++)
2051 {
2052 ps[j+hWid]=2*M_PI*j*(lfd+j*(lfc/2+j*(lfb/3+j*lfa/4)));
2053 as[j+hWid]=lad+j*(lac+j*(lab+j*laa));
2054 }
2055 }
2056 double *ldata=&x[fr*Offst];
2057 for (int j=0; j<Wid; j++)
2058 {
2059 double tmp;
2060 if ((fr==0 && j<hWid) || (fr==FrCount-1 && j>=hWid)) tmp=1;
2061 else if (as[hWid]>100*as[j]) tmp=100;
2062 else tmp=as[hWid]/as[j];
2063 tmp=tmp*ldata[j];
2064 xs[j].x=tmp*cos(-ps[j]);
2065 xs[j].y=tmp*sin(-ps[j]);
2066 }
2067
2068 if (Wids)
2069 {
2070 int lWid=Wids[fr], lhWid=Wids[fr]/2, lM;
2071 SetTwiddleFactors(lWid, w);
2072 double *lwin=NewWindow(wtHann, lWid), lc[4], liH2;
2073 windowspec(wtHann, lWid, &lM, lc, &liH2);
2074 CFFTCW(&xs[hWid-lhWid], lwin, NULL, NULL, log2(lWid), w, xc);
2075 delete[] lwin;
2076 double lf=fbuf[fr]*lWid, la, lp;
2077 LSESinusoid(lf, lf-3, lf+3, xc, lWid, 3, lM, lc, liH2, la, lp, 1e-3);
2078 if (la*2>abuf[fr]) fbuf[fr]=lf/lWid, abuf[fr]=la*2, pbuf[fr]=lp;
2079 }
2080 else
2081 {
2082 CFFTCW(xs, win, NULL, NULL, log2(Wid), w, xc);
2083 double lf=fbuf[fr]*Wid, la, lp;
2084 LSESinusoid(lf, lf-3, lf+3, xc, Wid, 3, M, c, iH2, la, lp, 1e-3);
2085 if (la*2>abuf[fr]) fbuf[fr]=lf/Wid, abuf[fr]=la*2, pbuf[fr]=lp;
2086 }
2087 }
2088 }//ReEstFreqAmp
2089
2090 /*
2091 function Reestimate2: iterative demodulation method for sinusoid parameter reestimation.
2092
2093 In: x[(FrCount-1)*Offst+Wid]: waveform data
2094 FrCount, Wid, Offst: frame count, frame size and hop size
2095 win[Wid]: window function
2096 M, c[], iH2: cosine-family window specification parameters, must be consistent with win[]
2097 Wids[FrCount]: specifies frame sizes for estimating individual frames of demodulated sinusoid,
2098 optional
2099 maxiter: maximal number of iterates
2100 ae[FrCount], fe[FrCount], pe[FrCount]: initial amplitude, frequency and phase estimates
2101 Out: aret[FrCount], fret[FrCount], pret[FrCount]: reestimated amplitudes, frequencies and phase angles
2102
2103 Returns the number of unused iterates left of the total of maxiter.
2104 */
2105 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)
2106 {
2107 AllocateFFTBuffer(Wid, fft, w, xc);
2108 double convep=1e-4, dif=0, lastdif=0; //convep is the hard-coded threshold that stops the iteration
2109 int iter=1, hWid=Wid/2;
2110
2111 double *ns=new double[FrCount*12], *as=new double[Wid*5];
2112 double *fbuf=&ns[FrCount], *abuf=&ns[FrCount*2],
2113 *aa=&ns[FrCount*3], *ab=&ns[FrCount*4], *ac=&ns[FrCount*5], *ad=&ns[FrCount*6],
2114 *fa=&ns[FrCount*7], *fb=&ns[FrCount*8], *fc=&ns[FrCount*9], *fd=&ns[FrCount*10],
2115 *pbuf=&ns[FrCount*11];
2116 double *ps=&as[Wid];
2117 cdouble *xs=(cdouble*)&as[Wid*3];
2118
2119 memcpy(fbuf, fe, sizeof(double)*FrCount);
2120 memcpy(abuf, ae, sizeof(double)*FrCount);
2121 memcpy(pbuf, pe, sizeof(double)*FrCount);
2122 for (int i=0; i<FrCount; i++)
2123 {
2124 ns[i]=hWid+i*Offst;
2125 }
2126
2127 while (iter<=maxiter)
2128 {
2129 ReEstFreq(FrCount, Wid, Offst, x, fbuf, abuf, pbuf, win, M, c, iH2, w, xc, xs, ps, fa, fb, fc, fd, ns, Wids);
2130 ReEstFreq(FrCount, Wid, Offst, x, fbuf, abuf, pbuf, win, M, c, iH2, w, xc, xs, ps, fa, fb, fc, fd, ns, Wids);
2131 ReEstFreqAmp(FrCount, Wid, Offst, x, fbuf, abuf, pbuf, win, M, c, iH2, w, xc, xs, ps, as, fa, fb, fc, fd, aa, ab, ac, ad, ns, Wids);
2132
2133 if (iter>1) lastdif=dif;
2134 dif=0;
2135 if (iter==1)
2136 {
2137 for (int fr=0; fr<FrCount; fr++)
2138 {
2139 if (fabs(abuf[fr])>fabs(ae[fr]))
2140 dif+=fabs(fe[fr]-fbuf[fr])*Wid+fabs((ae[fr]-abuf[fr])/abuf[fr]);
2141 else
2142 dif+=fabs(fe[fr]-fbuf[fr])*Wid+fabs((ae[fr]-abuf[fr])/ae[fr]);
2143 }
2144 }
2145 else
2146 {
2147 for (int fr=0; fr<FrCount; fr++)
2148 {
2149 if (fabs(abuf[fr])>fabs(aret[fr]))
2150 dif+=fabs(fret[fr]-fbuf[fr])*Wid+fabs((aret[fr]-abuf[fr])/abuf[fr]);
2151 else
2152 dif+=fabs(fret[fr]-fbuf[fr])*Wid+fabs((aret[fr]-abuf[fr])/aret[fr]);
2153 }
2154 }
2155 memcpy(fret, fbuf, sizeof(double)*FrCount);
2156 memcpy(aret, abuf, sizeof(double)*FrCount);
2157 dif/=FrCount;
2158 if (fabs(dif)<convep || (iter>1 && fabs(dif-lastdif)<convep*lastdif)) break;
2159 iter++;
2160 }
2161
2162 memcpy(pret, pbuf, sizeof(double)*FrCount);
2163
2164 delete[] ns;
2165 delete[] as;
2166 delete[] fft;
2167
2168 return maxiter-iter;
2169 }//Reestimate2
2170
2171 //---------------------------------------------------------------------------
2172 /*
2173 Derivative method as proposed in DAFx09
2174
2175 Further reading: Wen X. and M. Sandler, "Notes on model-based non-stationary sinusoid estimation methods
2176 using derivatives," in Proc. DAFx'09, Como, 2009.
2177 */
2178
2179 /*
2180 function Derivative: derivative method for estimating amplitude derivative, frequency, and frequency derivative given
2181 signal and its derivatives.
2182
2183 In: x[Wid], dx[Wid], ddx[Wid]: waveform and its derivatives
2184 win[Wid]: window function
2185 f0: initial digital frequency estimate
2186 Out: f0: new estimate of digital frequency
2187 f1, a1: estimates of frequency and amplitude derivatives
2188
2189 No return value.
2190 */
2191 void Derivative(int Wid, double* win, cdouble* x, cdouble* dx, cdouble* ddx, double& f0, double* f1, double* a0, double* a1, double* ph)
2192 {
2193 AllocateFFTBuffer(Wid, fft, W, X);
2194 CFFTCW(x, win, fft, NULL, log2(Wid), W, X);
2195 int m=f0*Wid, m0=m-10, m1=m+10, hWid=Wid/2;
2196 if (m0<0) m0=0; if (m1>hWid) m1=hWid;
2197 for (int n=m0; n<=m1; n++) if (fft[n]>fft[m]) m=n;
2198 cdouble Sw=0, S1w=0, S2w=0;
2199 for (int n=0; n<Wid; n++)
2200 {
2201 cdouble tmp=x[n]*win[n];
2202 Sw+=tmp.rotate(-2*M_PI*m*(n-hWid)/Wid);
2203 tmp=dx[n]*win[n];
2204 S1w+=tmp.rotate(-2*M_PI*m*(n-hWid)/Wid);
2205 }
2206 double omg0=(S1w/Sw).y;
2207 Sw=0, S1w=0;
2208 for (int n=0; n<Wid; n++)
2209 {
2210 cdouble tmp=x[n]*win[n];
2211 Sw+=tmp.rotate(-omg0*(n-hWid)/Wid);
2212 tmp=dx[n]*win[n];
2213 S1w+=tmp.rotate(-omg0*(n-hWid)/Wid);
2214 tmp=ddx[n]*win[n];
2215 S2w+=tmp.rotate(-omg0*(n-hWid)/Wid);
2216 }
2217 omg0=(S1w/Sw).y;
2218 double miu0=(S1w/Sw).x;
2219 double psi0=(S2w/Sw).y-2*miu0*omg0;
2220
2221 f0=omg0/(2*M_PI);
2222 *f1=psi0/(2*M_PI);
2223 *a1=miu0;
2224
2225 FreeFFTBuffer(fft);
2226 }//Derivative
2227
2228 /*
2229 function Xkw: computes windowed spectrum of x and its derivatives up to order K at angular frequency omg,
2230 from x using window w and its derivatives.
2231
2232 In: x[Wid]: waveform data
2233 w[K+1][Wid]: window functions and its derivatives up to order K
2234 omg: angular frequency
2235 Out: X[K+1]: windowed spectrum and its derivatives up to order K
2236
2237 No return value. This function is for internal use.
2238 */
2239 void Xkw(cdouble* X, int K, int Wid, double* x, double** w, double omg)
2240 {
2241 int hWid=Wid/2;
2242 //calculate the first row
2243 memset(X, 0, sizeof(cdouble)*(K+1));
2244 for (int i=0; i<Wid; i++)
2245 {
2246 double n=i-hWid;
2247 double ph=omg*n;
2248 for (int k=0; k<=K; k++)
2249 {
2250 cdouble tmp=x[i]*w[k][i];
2251 X[k]+=tmp.rotate(-ph);
2252 }
2253 }
2254 //calculate the rest rows
2255 for (int k=1; k<=K; k++)
2256 {
2257 cdouble *thisX=&X[k], *lastX=&X[k-1];
2258 for (int kk=K-k; kk>=0; kk--) thisX[kk]=-lastX[kk+1]+cdouble(0, omg)*lastX[kk];
2259 }
2260 }//Xkw
2261
2262 /*
2263 function Xkw: computes windowed spectrum of x and its derivatives up to order K at angular frequency
2264 omg, from x and its derivatives using window w.
2265
2266 In: x[K+1][Wid]: waveform data and its derivatives up to order K.
2267 w[Wid]: window function
2268 omg: angular frequency
2269 Out: X[K+1]: windowed spectrum and its derivatives up to order K
2270
2271 No return value. This function is for testing only.
2272 */
2273 void Xkw(cdouble* X, int K, int Wid, double** x, double* w, double omg)
2274 {
2275 int hWid=Wid/2;
2276 memset(X, 0, sizeof(cdouble)*(K+1));
2277 for (int i=0; i<Wid; i++)
2278 {
2279 double n=i-hWid;
2280 double ph=omg*n;
2281 for (int k=0; k<=K; k++)
2282 {
2283 cdouble tmp=x[k][i]*w[i];
2284 X[k]+=tmp.rotate(-ph);
2285 }
2286 }
2287 }//Xkw
2288
2289 /*
2290 function Derivative: derivative method for estimating the model log(s)=h[M]'r[M], by discarding extra
2291 equations
2292
2293 In: s[Wid]: waveform data
2294 win[][Wid]: window function and its derivatives
2295 h[M], dh[M]: pointers to basis functions and their derivatives
2296 harg: pointer argument to be used by calls to functions in h[] amd dh[].
2297 p0[p0s]: zero-constraints on real parts of r, i.e. Re(r[p0[*]]) are constrained to 0.
2298 q0[q0s]: zero-constraints on imaginary parts of r, i.e. Im(r[q0[*]]) are constrained to 0.
2299 omg: initial angular frequency
2300 Out: r[M]: estimated coefficients to h[M].
2301
2302 No return value.
2303 */
2304 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)
2305 {
2306 int hWid=Wid/2, M1=M-1;
2307 int Kr=(M1)*2-p0s-q0s; //number of real unknowns apart from p0 and q0
2308 int Kc=ceil(Kr/2.0); //number of derivatives required
2309
2310 //ind marks the 2*M1 real elements of an M1-array of complex unknowns with
2311 // numerical indices (0-based) or -1 if it is not a real unknown variable
2312 //uind marks the Kr real unknowns with their positions in ind
2313 int *uind=new int[Kr], *ind=new int[2*M1];
2314 memset(ind, 0, sizeof(int)*2*M1);
2315 for (int p=0; p<p0s; p++) ind[2*(p0[p]-1)]=-1;
2316 for (int q=0; q<q0s; q++) ind[2*(q0[q]-1)+1]=-1;
2317 {
2318 int p=0, up=0;
2319 while (p<2*M1)
2320 {
2321 if (ind[p]>=0)
2322 {
2323 uind[up]=p;
2324 ind[p]=up;
2325 up++;
2326 }
2327 p++;
2328 }
2329 if (up!=Kr) throw("");
2330 }
2331
2332 cdouble* Skw=new cdouble[M];
2333 Xkw(Skw, Kc, Wid, s, win, omg);
2334
2335 double* x=new double[Wid];
2336 cdouble** Allocate2(cdouble, M, Kc, Smkw);
2337 for (int m=1; m<M; m++)
2338 {
2339 for (int i=0; i<Wid; i++) x[i]=dh[m](i-hWid, harg)*s[i];
2340 Xkw(Smkw[m], Kc-1, Wid, x, win, omg);
2341 }
2342
2343 //allocate buffer for linear system A(pq)=b
2344 Alloc2(2*Kc+2, Kr, A); double** AA; double *bb, *pqpq;
2345 double *b=A[2*Kc], *pq=A[2*Kc+1];
2346 for (int k=0; k<Kr; k++) b[k]=((double*)(&Skw[1]))[k];
2347 // *pq=(double*)(&r[1]);
2348 for (int k=0; k<Kc; k++) //looping through rows of A
2349 {
2350 //columns of A includes rows of Smkw corresponding to real unknowns
2351 for (int m=0; m<M1; m++)
2352 {
2353 int lind;
2354 if ((lind=ind[2*m])>=0) //the real part being unknown
2355 {
2356 A[2*k][lind]=Smkw[m+1][k].x;
2357 A[2*k+1][lind]=Smkw[m+1][k].y;
2358 }
2359 if ((lind=ind[2*m+1])>=0) //the imag part being unknown
2360 {
2361 A[2*k+1][lind]=Smkw[m+1][k].x;
2362 A[2*k][lind]=-Smkw[m+1][k].y;
2363 }
2364 }
2365 }
2366
2367 bool dropeq=(2*Kc-1==Kr);
2368 if (dropeq)
2369 {
2370 Allocate2(double, Kr+2, Kr, AA);
2371 bb=AA[Kr], pqpq=AA[Kr+1];
2372 memcpy(AA[0], A[0], sizeof(double)*Kr*(Kr-1));
2373 memcpy(AA[Kr-1], A[Kr], sizeof(double)*Kr);
2374 memcpy(bb, b, sizeof(double)*(Kr-1));
2375 bb[Kr-1]=((double*)(&Skw[1]))[Kr];
2376 }
2377
2378 double det;
2379 GECP(Kr, pq, A, b, &det);
2380 if (dropeq)
2381 {
2382 double det2;
2383 GECP(Kr, pqpq, AA, bb, &det2);
2384 if (fabs(det2)>fabs(det)) memcpy(pq, pqpq, sizeof(double)*Kr);
2385 DeAlloc2(AA);
2386 }
2387 memset(&r[1], 0, sizeof(double)*M1*2);
2388 for (int k=0; k<Kr; k++) ((double*)(&r[1]))[uind[k]]=pq[k];
2389
2390 //estiamte r0
2391 cdouble e0=0;
2392 for (int i=0; i<Wid; i++)
2393 {
2394 cdouble expo=0;
2395 double n=i-hWid;
2396 for (int m=1; m<M; m++){double lhm=h[m](n, harg); expo+=r[m]*lhm;}
2397 cdouble tmp=exp(expo)*win[0][i];
2398 e0+=tmp.rotate(-omg*n);
2399 }
2400 r[0]=log(Skw[0]/e0);
2401
2402 delete[] x;
2403 delete[] Skw;
2404 delete[] uind;
2405 delete[] ind;
2406 DeAlloc2(Smkw);
2407 DeAlloc2(A);
2408 }//Derivative*/
2409
2410 /*
2411 function DerivativeLS: derivative method for estimating the model log(s)=h[M]'r[M], least-square
2412 implementation
2413
2414 In: s[Wid]: waveform data
2415 win[][Wid]: window function and its derivatives
2416 h[M], dh[M]: pointers to basis functions and their derivatives
2417 harg: pointer argument to be used by calls to functions in h[] amd dh[].
2418 K: number of derivatives to take
2419 p0[p0s]: zero-constraints on real parts of r, i.e. Re(r[p0[*]]) are constrained to 0.
2420 q0[q0s]: zero-constraints on imaginary parts of r, i.e. Im(r[q0[*]]) are constrained to 0.
2421 omg: initial angular frequency
2422 Out: r[M]: estimated coefficients to h[M].
2423
2424 No return value.
2425 */
2426 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)
2427 {
2428 int hWid=Wid/2, M1=M-1;
2429 int Kr=(M1)*2-p0s-q0s; //number of real unknowns apart from p0 and q0
2430 int Kc=ceil(Kr/2.0); //number of derivatives required
2431 if (Kc<K) Kc=K;
2432
2433 int *uind=new int[Kr], *ind=new int[2*M1];
2434 memset(ind, 0, sizeof(int)*2*M1);
2435 for (int p=0; p<p0s; p++) ind[2*(p0[p]-1)]=-1;
2436 for (int q=0; q<q0s; q++) ind[2*(q0[q]-1)+1]=-1;
2437 {int p=0, up=0; while (p<2*M1){if (ind[p]>=0){uind[up]=p; ind[p]=up; up++;} p++;} if (up!=Kr) throw("");}
2438
2439 //allocate buffer for linear system A(pq)=b
2440 cdouble* Skw=new cdouble[Kc+1];
2441 double* x=new double[Wid];
2442 cdouble** Allocate2(cdouble, M, Kc, Smkw);
2443
2444 Alloc2(2*Kc+2, 2*Kc, A);
2445 double *b=A[2*Kc], *pq=A[2*Kc+1];
2446
2447 Xkw(Skw, Kc, Wid, s, win, omg);
2448 for (int m=1; m<M; m++)
2449 {
2450 for (int i=0; i<Wid; i++) x[i]=dh[m](i-hWid, harg)*s[i];
2451 Xkw(Smkw[m], Kc-1, Wid, x, win, omg);
2452 }
2453
2454 for (int k=0; k<2*Kc; k++) b[k]=((double*)(&Skw[1]))[k];
2455 for (int k=0; k<Kc; k++)
2456 {
2457 for (int m=0; m<M1; m++)
2458 {
2459 int lind;
2460 if ((lind=ind[2*m])>=0)
2461 {
2462 A[2*k][lind]=Smkw[m+1][k].x;
2463 A[2*k+1][lind]=Smkw[m+1][k].y;
2464 }
2465 if ((lind=ind[2*m+1])>=0)
2466 {
2467 A[2*k+1][lind]=Smkw[m+1][k].x;
2468 A[2*k][lind]=-Smkw[m+1][k].y;
2469 }
2470 }
2471 }
2472
2473 if (2*Kc==Kr) GECP(Kr, pq, A, b);
2474 else LSLinear2(2*Kc, Kr, pq, A, b);
2475
2476 memset(&r[1], 0, sizeof(double)*M1*2);
2477 for (int k=0; k<Kr; k++) ((double*)(&r[1]))[uind[k]]=pq[k];
2478 //estiamte r0
2479 if (r0)
2480 {
2481 cdouble e0=0;
2482 for (int i=0; i<Wid; i++)
2483 {
2484 cdouble expo=0;
2485 double n=i-hWid;
2486 for (int m=1; m<M; m++){double lhm=h[m](n, harg); expo+=r[m]*lhm;}
2487 cdouble tmp=exp(expo)*win[0][i];
2488 e0+=tmp.rotate(-omg*n);
2489 }
2490 r[0]=log(Skw[0]/e0);
2491 }
2492 delete[] x;
2493 delete[] Skw;
2494 delete[] uind;
2495 delete[] ind;
2496 DeAlloc2(Smkw);
2497 DeAlloc2(A);
2498 }//DerivativeLS
2499
2500 /*
2501 function DerivativeLS: derivative method for estimating the model log(s)=h[M]'r[M] using Fr
2502 measurement points a quarter of Wid apart from each other, implemented by least-square.
2503
2504 In: s[Wid+(Fr-1)*Wid/4]: waveform data
2505 win[][Wid]: window function and its derivatives
2506 h[M], dh[M]: pointers to basis functions and their derivatives
2507 harg: pointer argument to be used by calls to functions in h[] amd dh[].
2508 Fr: number of measurement points
2509 K: number of derivatives to take at each measurement point
2510 p0[p0s]: zero-constraints on real parts of r, i.e. Re(r[p0[*]]) are constrained to 0.
2511 q0[q0s]: zero-constraints on imaginary parts of r, i.e. Im(r[q0[*]]) are constrained to 0.
2512 omg: initial angular frequency
2513 r0: specifies if r[0] is to be computed.
2514 Out: r[M]: estimated coefficients to h[M].
2515
2516 No return value.
2517 */
2518 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)
2519 {
2520 int hWid=Wid/2, qWid=Wid/4, M1=M-1;
2521 int Kr=(M1)*2-p0s-q0s; //number of real unknowns apart from p0 and q0
2522 int Kc=ceil(Kr/2.0/Fr); //number of derivatives required
2523 if (Kc<K) Kc=K;
2524
2525 int *uind=new int[Kr], *ind=new int[2*M1];
2526 memset(ind, 0, sizeof(int)*2*M1);
2527 for (int p=0; p<p0s; p++) ind[2*(p0[p]-1)]=-1;
2528 for (int q=0; q<q0s; q++) ind[2*(q0[q]-1)+1]=-1;
2529 {int p=0, up=0; while (p<2*M1){if (ind[p]>=0){uind[up]=p; ind[p]=up; up++;} p++;}}
2530
2531 //allocate buffer for linear system A(pq)=b
2532 cdouble* Skw=new cdouble[Kc+1], Skw00;
2533 double* x=new double[Wid];
2534 cdouble** Allocate2(cdouble, M, Kc, Smkw);
2535
2536 Alloc2(2*Fr*Kc, 2*Fr*Kc, A);
2537 double *pq=new double[2*Fr*Kc], *b=new double[2*Fr*Kc];
2538
2539 for (int fr=0; fr<Fr; fr++)
2540 {
2541 int Offst=qWid*fr; double* ss=&s[Offst];
2542
2543 Xkw(Skw, Kc, Wid, ss, win, omg); if (fr==0) Skw00=Skw[0];
2544 for (int m=1; m<M; m++)
2545 {
2546 for (int i=0; i<Wid; i++) x[i]=dh[m](i+Offst-hWid, harg)*ss[i];
2547 Xkw(Smkw[m], Kc-1, Wid, x, win, omg);
2548 }
2549
2550 for (int k=0; k<2*Kc; k++) b[2*fr*Kc+k]=((double*)(&Skw[1]))[k];
2551 for (int k=0; k<Kc; k++)
2552 {
2553 for (int m=0; m<M1; m++)
2554 {
2555 int lind;
2556 if ((lind=ind[2*m])>=0)
2557 {
2558 A[2*fr*Kc+2*k][lind]=Smkw[m+1][k].x;
2559 A[2*fr*Kc+2*k+1][lind]=Smkw[m+1][k].y;
2560 }
2561 if ((lind=ind[2*m+1])>=0)
2562 {
2563 A[2*fr*Kc+2*k+1][lind]=Smkw[m+1][k].x;
2564 A[2*fr*Kc+2*k][lind]=-Smkw[m+1][k].y;
2565 }
2566 }
2567 }
2568 }
2569 if (2*Fr*Kc==Kr) GECP(Kr, pq, A, b);
2570 else LSLinear2(2*Fr*Kc, Kr, pq, A, b);
2571
2572 memset(&r[1], 0, sizeof(double)*M1*2);
2573 for (int k=0; k<Kr; k++) ((double*)(&r[1]))[uind[k]]=pq[k];
2574 //estiamte r0
2575 if (r0)
2576 {
2577 cdouble e0=0;
2578 for (int i=0; i<Wid; i++)
2579 {
2580 cdouble expo=0;
2581 double n=i-hWid;
2582 for (int m=1; m<M; m++){double lhm=h[m](n, harg); expo+=r[m]*lhm;}
2583 cdouble tmp=exp(expo)*win[0][i];
2584 e0+=tmp.rotate(-omg*n);
2585 }
2586 r[0]=log(Skw00/e0);
2587 }
2588 delete[] x;
2589 delete[] Skw;
2590 delete[] uind;
2591 delete[] ind;
2592 DeAlloc2(Smkw);
2593 DeAlloc2(A);
2594 delete[] pq; delete[] b;
2595 }//DerivativeLS
2596
2597 //---------------------------------------------------------------------------
2598 /*
2599 Abe-Smith sinusoid estimator 2005
2600
2601 Further reading: M. Abe and J. O. Smith III, ¡°AM/FM rate estimation for time-varying sinusoidal
2602 modeling,¡± in Proc. ICASSP'05, Philadelphia, 2005.
2603 */
2604
2605 /*
2606 function RDFTW: windowed DTFT at frequency k bins
2607
2608 In: data[Wid]: waveform data
2609 w[Wid]: window function
2610 k: frequency, in bins
2611 Out: Xr, Xi: real and imaginary parts of the DTFT of xw at frequency k bins
2612
2613 No return value.
2614 */
2615 void RDFTW(double& Xr, double& Xi, double k, int Wid, double* data, double* w)
2616 {
2617 Xr=Xi=0;
2618 int hWid=Wid/2;
2619 double* lw=&w[Wid];
2620 for (int i=0; i<=Wid; i++)
2621 {
2622 double tmp;
2623 tmp=*data**lw;
2624 data++, lw--;
2625 //*
2626 double ph=-2*M_PI*(i-hWid)*k/Wid;
2627 Xr+=tmp*cos(ph);
2628 Xi+=tmp*sin(ph); //*/
2629 }
2630 }//RDFTW
2631
2632 /*
2633 function TFAS05: the Abe-Smith method 2005
2634
2635 In: data[Wid]: waveform data
2636 w[Wid]: window function
2637 res: resolution of frequency for QIFFT
2638 Out: f, a, ph: frequency, amplitude and phase angle estimates
2639 aesp, fslope: estimates of log amplitude and frequency derivatives
2640
2641 No return value.
2642 */
2643 void TFAS05(double& f, double& t, double& a, double& ph, double& aesp, double& fslope, int Wid, double* data, double* w, double res)
2644 {
2645 double fi=floor(f*Wid+0.5); //frequency (int) in bins
2646 double xr0, xi0, xr_1, xi_1, xr1, xi1;
2647 RDFTW(xr0, xi0, fi, Wid, data, w);
2648 RDFTW(xr_1, xi_1, fi-res, Wid, data, w);
2649 RDFTW(xr1, xi1, fi+res, Wid, data, w);
2650 double winnorm=0; for (int i=0; i<=Wid; i++) winnorm+=w[i];
2651 double y0=log(sqrt(xr0*xr0+xi0*xi0)/winnorm),
2652 y_1=log(sqrt(xr_1*xr_1+xi_1*xi_1)/winnorm),
2653 y1=log(sqrt(xr1*xr1+xi1*xi1)/winnorm);
2654 double df=0;
2655 //*
2656 if (y0<y1)
2657 {
2658 double newfi=fi+res;
2659 while (y0<y1)
2660 {
2661 y_1=y0, xr_1=xr0, xi_1=xi0;
2662 y0=y1, xr0=xr1, xi0=xi1;
2663 newfi+=res;
2664 RDFTW(xr1, xi1, newfi, Wid, data, w);
2665 y1=log(sqrt(xr1*xr1+xi1*xi1)/winnorm);
2666 fi+=res;
2667 }
2668 }
2669 else if(y0<y_1)
2670 {
2671 double newfi=fi-res;
2672 while (y0<y_1)
2673 {
2674 y1=y0, xr1=xr0, xi1=xi0;
2675 y0=y_1, xr0=xr_1, xi0=xi_1;
2676 newfi-=res;
2677 RDFTW(xr_1, xi_1, newfi, Wid, data, w);
2678 y_1=log(sqrt(xr_1*xr_1+xi_1*xi_1)/winnorm);
2679 fi-=res;
2680 }
2681 } //*/
2682
2683 double a2=(y1+y_1)*0.5-y0, a1=(y1-y_1)*0.5, a0=y0;
2684 df=-a1*0.5/a2;
2685 f=fi+df*res; //in bins
2686 double y=a0-0.25*a1*a1/a2;
2687 a=exp(y);
2688 double ph0=(xi0==0 && xr0==0)?0:atan2(xi0, xr0),
2689 ph_1=(xi_1==0 && xr_1==0)?0:atan2(xi_1, xr_1),
2690 ph1=(xi1==0 && xr1==0)?0:atan2(xi1, xr1);
2691 if (fabs(ph_1-ph0)>M_PI)
2692 {
2693 if (ph_1-ph0>0) ph_1-=M_PI*2;
2694 else ph_1+=M_PI*2;
2695 }
2696 if (fabs(ph1-ph0)>M_PI)
2697 {
2698 if (ph1-ph0>0) ph1-=M_PI*2;
2699 else ph1+=M_PI*2;
2700 }
2701 double b2=(ph1+ph_1)*0.5-ph0, b1=(ph1-ph_1)*0.5, b0=ph0;
2702 ph=b0+b1*(df+b2*df);
2703 //now we have the QI estimates
2704 double uff=2*a2, vf=b1+2*b2*df, vff=2*b2;
2705 double dfdp=Wid/(2*M_PI*res);
2706 double upp=uff*dfdp*dfdp, vp=vf*dfdp, vpp=vff*dfdp*dfdp;
2707 double p=-upp*0.5/(upp*upp+vpp*vpp);
2708 double alf=-2*p*vp, beta=p*vpp/upp;
2709 //*direct method
2710 double beta_p=beta/p;
2711 double feses=f-alf*beta/p /(2*M_PI)*Wid,
2712 yeses=y-alf*alf*0.25/p+0.25*log(1+beta_p*beta_p),
2713 pheses=ph+alf*alf*beta*0.25/p-0.5*atan(beta_p); //*/
2714 /*adapted method
2715 double zt[]={0, 0.995354, 0.169257, 1.393056, 0.442406, -0.717980, -0.251620, 0.177511, 0.158120, -0.503299};
2716 double delt=res/Wid; double delt0=df*delt;
2717 beta=zt[3]*beta+zt[4]*delt0*alf;
2718 alf=(zt[1]+zt[2]*delt*delt)*alf;
2719 double beta_p=beta/p;
2720 double feses=f+zt[5]*alf*beta/p /(2*M_PI)*Wid,
2721 yeses=y+zt[6]*alf*alf/p+zt[7]*log(1+beta_p*beta_p),
2722 pheses=ph+zt[8]*alf*alf*beta/p+zt[9]*atan(beta_p); //*/
2723 f=feses/Wid, a=exp(yeses), ph=pheses, fslope=2*beta/2/M_PI, aesp=alf;
2724 }//TFAS05
2725
2726 /*
2727 function TFAS05_enh: the Abe-Smith method 2005 enhanced by LSE amplitude and phase estimation
2728
2729 In: data[Wid]: waveform data
2730 w[Wid]: window function
2731 res: resolution of frequency for QIFFT
2732 Out: f, a, ph: frequency, amplitude and phase angle estimates
2733 aesp, fslope: estimates of log amplitude and frequency derivatives
2734
2735 No return value.
2736 */
2737 void TFAS05_enh(double& f, double& t, double& a, double& ph, double& aesp, double& fslope, int Wid, double* data, double* w, double res)
2738 {
2739 TFAS05(f, t, a, ph, aesp, fslope, Wid, data, w, res);
2740 double xr=0, xi=0, p, win2=0;
2741 for (int n=0; n<=Wid; n++)
2742 {
2743 double ni=n-Wid/2, tmp=data[n]*w[n]*w[n];//*exp(-aesp*(n-Wid/2)); if (IsInfinite(tmp)) continue;
2744 p=-2*M_PI*(f+0.5*fslope*ni)*ni;
2745 xr+=tmp*cos(p);
2746 xi+=tmp*sin(p);
2747 win2+=w[n]*w[n];
2748 }
2749 a=sqrt(xr*xr+xi*xi)/win2;
2750 ph=(xr==0 && xi==0)?0:atan2(xi, xr);
2751 }//TFAS05_enh
2752 //version without returning aesp and fslope
2753 void TFAS05_enh(double& f, double& t, double& a, double& ph, int Wid, double* data, double* w, double res)
2754 {
2755 double aesp, fslope;
2756 TFAS05_enh(f, t, a, ph, aesp, fslope, Wid, data, w, res);
2757 }//TFAS05_enh
2758
2759 //---------------------------------------------------------------------------
2760 /*
2761 function DerivativeLSv_AmpPh: estimate the constant-term in the local derivative method. This is used
2762 by the local derivative algorithm, whose implementation is found in the header file as templates.
2763
2764 In: sv0: inner product <s, v0>, where s is the sinusoid being estimated.
2765 integr_h[M][Wid]: M vectors containing samples of the integral of basis functions h[M].
2766 v0[M]: a test function
2767 lmd[M]: coefficients to h[M]
2768
2769 Returns coefficient of integr_h[0]=1.
2770 */
2771 cdouble DerivativeLSv_AmpPh(int Wid, int M, double** integr_h, cdouble* lmd, cdouble* v0, cdouble sv0)
2772 {
2773 cdouble e0=0;
2774 for (int n=0; n<Wid; n++)
2775 {
2776 cdouble expo=0;
2777 for (int m=1; m<=M; m++) expo+=lmd[m]*integr_h[m][n];
2778 e0+=exp(expo)**v0[n];
2779 }
2780 return log(sv0/e0);
2781 }//DerivativeLSv_AmpPh
2782
2783 //---------------------------------------------------------------------------
2784 /*
2785 Piecewise derivative algorithm
2786
2787 Further reading: Wen X. and M. Sandler, "Spline exponential approximation of time-varying
2788 sinusoids," under review.
2789 */
2790
2791 /*
2792 function setv: computes I test functions v[I] by modulation u[I] to frequency f
2793
2794 In: u[I+1][Wid], du[I+1][Wid]: base-band test functions and their derivatives
2795 f: carrier frequency
2796 Out: v[I][Wid], dv[I][Wid]: test functions and their derivatives
2797
2798 No return value.
2799 */
2800 void setv(int I, int Wid, cdouble** v, cdouble** dv, double f, cdouble** u, cdouble** du)
2801 {
2802 double fbin=floor(f*Wid+0.5)/Wid;
2803 double omg=fbin*2*M_PI;
2804 cdouble jomg=cdouble(0, omg);
2805 for (int c=0; c<Wid; c++)
2806 {
2807 double t=c;
2808 cdouble rot=polar(1.0, omg*t);
2809 for (int i=0; i<I-1; i++) v[i][c]=u[i][c]*rot;
2810 for (int i=0; i<I-1; i++) dv[i][c]=du[i][c]*rot+jomg*v[i][c];
2811 //Here it is assumed that elements of u[] are modulated at 0, 1, -1, 2, -2, 3, -3, 4, ...;
2812 //if f is under fbin then the closest ones are in order 0, -1, 1, -2, 3, -3, 3, .... This
2813 //makes a difference to the whole of v[] only if I is even.
2814 if (f>=fbin || I%2==1){v[I-1][c]=u[I-1][c]*rot; dv[I-1][c]=du[I-1][c]*rot+jomg*v[I-1][c];}
2815 else{v[I-1][c]=u[I][c]*rot; dv[I-1][c]=du[I][c]*rot+jomg*v[I-1][c];}
2816 }
2817 }//setv
2818
2819 /*
2820 function setvhalf: computes I half-size test functions v[I] by modulation u[I] to frequency f.
2821
2822 In: u[I][hWid*2], du[I][Wid*2]: base-band test functions and their derivatives
2823 f: carrier frequency
2824 Out: v[I][hWid], dv[hWid]: half-size test functions and their derivatives
2825
2826 No return value.
2827 */void setvhalf(int I, int hWid, cdouble** v, cdouble** dv, double f, cdouble** u, cdouble** du)
2828 {
2829 double fbin=floor(f*hWid)/hWid;
2830 double omg=fbin*2*M_PI;
2831 cdouble jomg=cdouble(0, omg);
2832 for (int c=0; c<hWid; c++)
2833 {
2834 double t=c;
2835 cdouble rot=polar(1.0, omg*t);
2836 for (int i=0; i<I; i++) v[i][c]=u[i][c*2]*rot;
2837 for (int i=0; i<I; i++) dv[i][c]=rot*du[i][c*2]*cdouble(2.0)+jomg*v[i][c];
2838 }
2839 }//setvhalf
2840
2841 //#define ERROR_CHECK
2842
2843 /*
2844 function DerivativePiecewise: Piecewise derivative algorithm. In this implementation of the piecewise
2845 method the test functions v are constructed from I "basic" (single-frame) test functions, each
2846 covering the same period of 2T, by shifting these I functions by steps of T. A total number of (L-1)I
2847 test functions are used.
2848
2849 In: s[LT+1]: waveform data
2850 ds[LT+1]: derivative of s[LT], used only if ERROR_CHECK is defined.
2851 L, T: number and length of pieces.
2852 N: number of independent coefficients
2853 h[M][T]: piecewise basis functions
2854 A[L][M][N]: L matrices that map independent coefficients onto component coefficients over the L pieces
2855 u[I][2T}, du[I][2T]: base-band test functions
2856 f[L+1]: reference frequencies at 0, T, ..., LT, only f[1]...f[L-1] are used
2857 endmode: set to 1 or 3 to apply half-size testing over [0, T], to 2 or 3 to apply over [LT-T, LT]
2858 Out: aita[N]: independent coefficients
2859
2860 No return value.
2861 */
2862 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, cdouble* ds)
2863 {
2864 MList* mlist=new MList;
2865 int L_1=(endmode==0)?(L-1):((endmode==3)?(L+1):L);
2866 cdouble** Allocate2L(cdouble, L_1, I, sv, mlist);
2867 cdouble** Allocate2(cdouble, I, T*2, v);
2868 cdouble** Allocate2(cdouble, I, T*2, dv);
2869 //compute <sr, v>
2870 cdouble*** Allocate3L(cdouble, L_1, I, N, srv, mlist);
2871 cdouble** Allocate2L(cdouble, I, M, shv1, mlist);
2872 cdouble** Allocate2L(cdouble, I, M, shv2, mlist);
2873
2874 #ifdef ERROR_CHECK
2875 cdouble dsv1[128], dsv2[128];
2876 #endif
2877 for (int l=0; l<L-1; l++)
2878 {
2879 //v from u given f[l]
2880 double fbin=floor(f[l+1]*T*2)/(T*2.0);
2881 double omg=fbin*2*M_PI;
2882 cdouble jomg=cdouble(0, omg);
2883 for (int c=0; c<T*2; c++)
2884 {
2885 double t=c-T;
2886 cdouble rot=polar(1.0, omg*t);
2887 for (int i=0; i<I; i++) v[i][c]=u[i][c]*rot;
2888 for (int i=0; i<I; i++) dv[i][c]=du[i][c]*rot+jomg*v[i][c];
2889 }
2890
2891 //compute -<s, v'> over the lth frame
2892 cdouble* ls=&s[l*T]; for (int i=0; i<I; i++) sv[l][i]=-Inner(2*T, ls, dv[i]);
2893
2894 //compute <sr, v> over the lth frame
2895 cdouble *ls1=&s[l*T], *ls2=&s[l*T+T];
2896 for (int i=0; i<I; i++)
2897 for (int m=0; m<M; m++)
2898 shv1[i][m]=Inner(T, ls1, h[m], v[i]), shv2[i][m]=Inner(T, ls2, h[m], &v[i][T]);
2899 //memset(srv[l][0], 0, sizeof(cdouble)*I*N);
2900 MultiplyXY(I, M, N, srv[l], shv1, A[l]);
2901 MultiAddXY(I, M, N, srv[l], shv2, A[l+1]);
2902
2903 #ifdef ERROR_CHECK
2904 //error check: <s', v>=-<s, v'>
2905 if (ds)
2906 {
2907 cdouble* lds=&ds[l*T];
2908 for (int i=0; i<I && l*I+1<36; i++)
2909 {
2910 cdouble lsv=Inner(2*T, lds, v[i]); //compute <s', v[i]>
2911 //cdouble* ls=&s[l*T];
2912 //cdouble lsv2=Inner(2*T, ls, dv[i]);
2913 dsv1[l*I+i]=lsv-sv[l][i]; //i.e. <s', v[i]>=-<s, v[i]'>+dsv1[lI+i]
2914 }
2915
2916 //error check: srv[l]*pq=<s',v>
2917 for (int i=0; i<I && l*I+i<36; i++)
2918 {
2919 cdouble lsv=0;
2920 for (int n=0; n<N; n++) lsv+=srv[l][i][n]*aita[n];
2921 dsv2[l*I+i]=lsv-sv[l][i]-dsv1[l*I+i];
2922 }
2923 }
2924 #endif
2925 }
2926 L_1=L-1;
2927 if (endmode==1 || endmode==3)
2928 {
2929 //v from u given f[l]
2930 int hT=T/2;
2931 double fbin=floor((f[0]+f[1])*hT)/T;
2932 double omg=fbin*2*M_PI;
2933 cdouble jomg=cdouble(0, omg);
2934 for (int c=0; c<T; c++)
2935 {
2936 double t=c-hT;
2937 cdouble rot=polar(1.0, omg*t);
2938 for (int i=0; i<I; i++) v[i][c]=u[i][c*2]*rot;
2939 for (int i=0; i<I; i++) dv[i][c]=rot*du[i][c*2]*cdouble(2.0)+jomg*v[i][c];
2940 }
2941
2942 //compute -<s, v'> over the lth frame
2943 cdouble* ls=&s[0]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
2944
2945 //compute <sr, v> over the lth frame
2946 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
2947 //memset(srv[L_1][0], 0, sizeof(cdouble)*I*N);
2948 MultiplyXY(I, M, N, srv[L_1], shv1, A[0]);
2949 #ifdef ERROR_CHECK
2950 //error check: <s', v>=-<s, v'>
2951 if (ds)
2952 {
2953 cdouble* lds=&ds[0];
2954 for (int i=0; i<I && L_1*I+1<36; i++)
2955 {
2956 cdouble lsv=Inner(T, lds, v[i]); //compute <s', v[i]>
2957 //cdouble* ls=&s[l*T];
2958 //cdouble lsv2=Inner(2*T, ls, dv[i]);
2959 dsv1[L_1*I+i]=lsv-sv[L_1][i]; //i.e. <s', v[i]>=-<s, v[i]'>+dsv1[lI+i]
2960 }
2961
2962 //error check: srv[l]*pq=<s',v>
2963 for (int i=0; i<I && L_1*I+i<36; i++)
2964 {
2965 cdouble lsv=0;
2966 for (int n=0; n<N; n++) lsv+=srv[L_1][i][n]*aita[n];
2967 dsv2[L_1*I+i]=lsv-sv[L_1][i]-dsv1[L_1*I+i];
2968 }
2969 }
2970 #endif
2971 L_1++;
2972 }
2973 if (endmode==2 || endmode==3)
2974 {
2975 //v from u given f[l]
2976 int hT=T/2;
2977 double fbin=floor((f[L-1]+f[L])*hT)/T;
2978 double omg=fbin*2*M_PI;
2979 cdouble jomg=cdouble(0, omg);
2980 for (int c=0; c<T; c++)
2981 {
2982 double t=c-hT;
2983 cdouble rot=polar(1.0, omg*t);
2984 for (int i=0; i<I; i++) v[i][c]=u[i][c*2]*rot;
2985 for (int i=0; i<I; i++) dv[i][c]=cdouble(2.0)*du[i][c*2]*rot+jomg*v[i][c];
2986 }
2987
2988 //compute -<s, v'> over the lth frame
2989 cdouble* ls=&s[(L-1)*T]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
2990
2991 //compute <sr, v> over the lth frame
2992 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
2993 //memset(srv[L_1][0], 0, sizeof(cdouble)*I*N);
2994 MultiplyXY(I, M, N, srv[L_1], shv1, A[L-1]);
2995 #ifdef ERROR_CHECK
2996 //error check: <s', v>=-<s, v'>
2997 if (ds)
2998 {
2999 cdouble* lds=&ds[(L-1)*T];
3000 for (int i=0; i<I && L_1*I+1<36; i++)
3001 {
3002 cdouble lsv=Inner(T, lds, v[i]); //compute <s', v[i]>
3003 //cdouble* ls=&s[l*T];
3004 //cdouble lsv2=Inner(2*T, ls, dv[i]);
3005 dsv1[L_1*I+i]=lsv-sv[L_1][i]; //i.e. <s', v[i]>=-<s, v[i]'>+dsv1[lI+i]
3006 }
3007
3008 //error check: srv[l]*pq=<s',v>
3009 for (int i=0; i<I && L_1*I+i<36; i++)
3010 {
3011 cdouble lsv=0;
3012 for (int n=0; n<N; n++) lsv+=srv[L_1][i][n]*aita[n];
3013 dsv2[L_1*I+i]=lsv-sv[L_1][i]-dsv1[L_1*I+i];
3014 }
3015 }
3016 #endif
3017 L_1++;
3018 }
3019
3020 if (L_1*2*I==2*N) GECP(N, aita, srv[0], sv[0]);
3021 else LSLinear(L_1*I, N, aita, srv[0], sv[0]);
3022
3023 delete mlist;
3024 }//DerivativePiecewise
3025
3026 /*
3027 function DerivativePiecewise2: Piecewise derivative algorithm in which the real and imaginary parts of
3028 the exponent are modelled separately. In this implementation of the piecewise method the test
3029 functions v are constructed from I "basic" (single-frame) test functions, each covering the same
3030 period of 2T, by shifting these I functions by steps of T. A total number of (L-1)I test functions are
3031 used.
3032
3033 In: s[LT+1]: waveform data
3034 ds[LT+1]: derivative of s[LT], used only if ERROR_CHECK is defined.
3035 L, T: number and length of pieces.
3036 N: number of independent coefficients
3037 h[M][T]: piecewise basis functions
3038 A[L][M][Np]: L matrices that do coefficient mapping (real part) over the L pieces
3039 B[L][M][Nq]: L matrices that do coefficient mapping (imaginary part) over the L pieces
3040 u[I][2T}, du[I][2T]: base-band test functions
3041 f[L+1]: reference frequencies at 0, T, ..., LT, only f[1]...f[L-1] are used
3042 endmode: set to 1 or 3 to apply half-size testing over [0, T], to 2 or 3 to apply over [LT-T, LT]
3043 Out: p[Np], q[Nq]: independent coefficients
3044
3045 No return value.
3046 */
3047 void DerivativePiecewise2(int Np, double* p, int Nq, double* q, int L, double* f, int T, cdouble* s, double*** A, double*** B,
3048 int M, double** h, int I, cdouble** u, cdouble** du, int endmode, cdouble* ds)
3049 {
3050 MList* mlist=new MList;
3051 int L_1=(endmode==0)?(L-1):((endmode==3)?(L+1):L);
3052 cdouble** Allocate2L(cdouble, L_1, I, sv, mlist);
3053 cdouble** Allocate2(cdouble, I, T*2, v);
3054 cdouble** Allocate2(cdouble, I, T*2, dv);
3055 //compute <sr, v>
3056 cdouble*** Allocate3L(cdouble, L_1, I, Np, srav, mlist);
3057 cdouble*** srbv;
3058 if (Np==Nq && B==A) srbv=srav; else {Allocate3L(cdouble, L_1, I, Nq, srbv, mlist);} //same model for amplitude and phase
3059 cdouble** Allocate2L(cdouble, I, M, shv1, mlist);
3060 cdouble** Allocate2L(cdouble, I, M, shv2, mlist);
3061
3062 for (int l=0; l<L-1; l++)
3063 {
3064 //v from u given f[l]
3065 double fbin=floor(f[l+1]*T*2)/(T*2.0);
3066 double omg=fbin*2*M_PI;
3067 cdouble jomg=cdouble(0, omg);
3068 for (int c=0; c<T*2; c++)
3069 {
3070 double t=c-T;
3071 cdouble rot=polar(1.0, omg*t);
3072 for (int i=0; i<I; i++) v[i][c]=u[i][c]*rot;
3073 for (int i=0; i<I; i++) dv[i][c]=du[i][c]*rot+jomg*v[i][c];
3074 }
3075
3076 //compute -<s, v'> over the lth frame
3077 cdouble* ls=&s[l*T]; for (int i=0; i<I; i++) sv[l][i]=-Inner(2*T, ls, dv[i]);
3078
3079 //compute <sr, v> over the lth frame
3080 cdouble *ls1=&s[l*T], *ls2=&s[l*T+T];
3081 for (int i=0; i<I; i++)
3082 for (int m=0; m<M; m++)
3083 shv1[i][m]=Inner(T, ls1, h[m], v[i]), shv2[i][m]=Inner(T, ls2, h[m], &v[i][T]);
3084 memset(srav[l][0], 0, sizeof(cdouble)*I*Np);
3085 MultiplyXY(I, M, Np, srav[l], shv1, A[l]);
3086 MultiAddXY(I, M, Np, srav[l], shv2, A[l+1]);
3087 if (srbv!=srav) //so that either B!=A or Np!=Nq
3088 {
3089 //memset(srbv[l][0], 0, sizeof(cdouble)*I*Nq);
3090 MultiplyXY(I, M, Nq, srbv[l], shv1, B[l]);
3091 MultiAddXY(I, M, Nq, srbv[l], shv2, B[l+1]);
3092 }
3093 }
3094 L_1=L-1;
3095 if (endmode==1 || endmode==3)
3096 {
3097 //v from u given f[l]
3098 int hT=T/2;
3099 double fbin=floor((f[0]+f[1])*hT)/T;
3100 double omg=fbin*2*M_PI;
3101 cdouble jomg=cdouble(0, omg);
3102 for (int c=0; c<T; c++)
3103 {
3104 double t=c-hT;
3105 cdouble rot=polar(1.0, omg*t);
3106 for (int i=0; i<I; i++) v[i][c]=u[i][c*2]*rot;
3107 for (int i=0; i<I; i++) dv[i][c]=rot*du[i][c*2]*cdouble(2.0)+jomg*v[i][c];
3108 }
3109
3110 //compute -<s, v'> over the lth frame
3111 cdouble* ls=&s[0]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
3112
3113 //compute <sr, v> over the lth frame
3114 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
3115 //memset(srav[L_1][0], 0, sizeof(cdouble)*I*Np);
3116 MultiplyXY(I, M, Np, srav[L_1], shv1, A[0]);
3117 if (srbv!=srav) {memset(srbv[L_1][0], 0, sizeof(cdouble)*I*Nq); MultiplyXY(I, M, Nq, srbv[L_1], shv1, B[0]);}
3118 L_1++;
3119 }
3120 if (endmode==2 || endmode==3)
3121 {
3122 //v from u given f[l]
3123 int hT=T/2;
3124 double fbin=floor((f[L-1]+f[L])*hT)/T;
3125 double omg=fbin*2*M_PI;
3126 cdouble jomg=cdouble(0, omg);
3127 for (int c=0; c<T; c++)
3128 {
3129 double t=c-hT;
3130 cdouble rot=polar(1.0, omg*t);
3131 for (int i=0; i<I; i++) v[i][c]=u[i][c*2]*rot;
3132 for (int i=0; i<I; i++) dv[i][c]=cdouble(2.0)*du[i][c*2]*rot+jomg*v[i][c];
3133 }
3134
3135 //compute -<s, v'> over the lth frame
3136 cdouble* ls=&s[(L-1)*T]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
3137
3138 //compute <sr, v> over the lth frame
3139 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
3140 memset(srav[L_1][0], 0, sizeof(cdouble)*I*Np);
3141 MultiplyXY(I, M, Np, srav[L_1], shv1, A[L-1]);
3142 if (srbv!=srav)
3143 {
3144 //memset(srbv[L_1][0], 0, sizeof(cdouble)*I*Nq);
3145 MultiplyXY(I, M, Nq, srbv[L_1], shv1, B[L-1]);
3146 }
3147 L_1++;
3148 }
3149
3150 //real implementation of <sr,v>aita=<s',v>
3151 double** Allocate2L(double, L_1*I*2, Np+Nq, AM, mlist);
3152 for (int l=0; l<L_1; l++) for (int i=0; i<I; i++)
3153 {
3154 int li=l*I+i, li_H=li+L_1*I;
3155 for (int n=0; n<Np; n++)
3156 {
3157 AM[li][n]=srav[l][i][n].x;
3158 AM[li_H][n]=srav[l][i][n].y;
3159 }
3160 for (int n=0; n<Nq; n++)
3161 {
3162 AM[li][Np+n]=-srbv[l][i][n].y;
3163 AM[li_H][Np+n]=srbv[l][i][n].x;
3164 }
3165 }
3166 //least-square solution of (srv)(aita)=(sv)
3167 double* pq=new double[Np+Nq]; mlist->Add(pq, 1);
3168 double* b=new double[2*L_1*I]; for (int i=0; i<L_1*I; i++) b[i]=sv[0][i].x, b[i+L_1*I]=sv[0][i].y;
3169
3170 if (L_1*2*I==Np+Nq) GECP(Np+Nq, pq, AM, b);
3171 else LSLinear(2*L_1*I, Np+Nq, pq, AM, b);
3172
3173 memcpy(p, pq, sizeof(double)*Np); memcpy(q, &pq[Np], sizeof(double)*Nq);
3174
3175 delete mlist;
3176 }//DerivativePiecewise2
3177
3178 /*
3179 Error check: test that ds[LT] equals s[LT] times reconstructed R'. Notice that DA is D time A where D
3180 is a pre-emphasis because p[Np] applies to log amplitude rather than its derivative.
3181 */
3182 double testds_pqA(int Np, double* p, int Nq, double* q, int L, int T, cdouble* s, cdouble* ds, int M, double** h, double** dh, double*** DA, double*** B, cdouble* errds=0)
3183 {
3184 double err=0, ene=0, *lamdax=new double[M*2], *lamday=&lamdax[M];
3185 for (int l=0; l<L; l++)
3186 {
3187 MultiplyXy(M, Np, lamdax, DA[l], p);
3188 MultiplyXy(M, Nq, lamday, B[l], q);
3189 for (int t=0; t<T; t++)
3190 {
3191 double drtx=0; for (int m=0; m<M; m++) drtx+=lamdax[m]*h[m][t];
3192 double drty=0; for (int m=0; m<M; m++) drty+=lamday[m]*h[m][t];
3193 cdouble drt=cdouble(drtx, drty);
3194 cdouble eds=ds[l*T+t]-s[l*T+t]*drt;
3195 err+=~eds; ene+=~ds[l*T+t];
3196 if (errds) errds[l*T+t]=eds;
3197 }
3198 }
3199 delete[] lamdax;
3200 return err/ene;
3201 }//testds_pqA
3202
3203 /*
3204 Error check: dsv1[I] tests that <s', v[I]> equals -<s, v[I]'>, dsv2[I] tests that <sr, v[I]>*pq=
3205 <s',v[I]>
3206 */
3207 void testdsv(cdouble* dsv1, cdouble* dsv2, int Np, double* p, int Nq, double* q, int TT, cdouble* dsl, int I, cdouble** vl, cdouble* svl, cdouble** sravl, cdouble** srbvl)
3208 {
3209 for (int i=0; i<I; i++)
3210 {
3211 cdouble lsv=Inner(TT, dsl, vl[i]); //compute <s', v[i]>
3212 //cdouble* ls=&s[l*T];
3213 dsv1[i]=lsv-svl[i]; //i.e. <s', v[i]>=-<s, v[i]'>+dsv1[lI+i]
3214 //sv[l][i]=lsv;
3215 }
3216 //error check: srv[l]*pq=<s',v>
3217 for (int i=0; i<I; i++)
3218 {
3219 cdouble lsv=0;
3220 for (int n=0; n<Np; n++) lsv+=sravl[i][n]*p[n];
3221 for (int n=0; n<Nq; n++) lsv+=srbvl[i][n]*cdouble(0, q[n]);
3222 dsv2[i]=lsv-svl[i]-dsv1[i];
3223 }
3224 }//testdsv
3225
3226 /*
3227 Error check: tests A[MN]x[N1]=b[N1], returns square error
3228 */
3229 double testlinearsystem(int M, int N, double** A, double* x, double* b)
3230 {
3231 double err=0;
3232 for (int m=0; m<M; m++)
3233 {
3234 double errli=Inner(N, A[m], x)-b[m];
3235 err+=errli*errli;
3236 }
3237 return err;
3238 }//testlinearsystem
3239
3240 /*
3241 Error check: test the total square norm of <s, v>
3242 */
3243 double testsv(int L, double* f, int T, cdouble* s, int I, cdouble** u, cdouble** du, int endmode)
3244 {
3245 cdouble** Allocate2(cdouble, I, T*2, v);
3246 cdouble** Allocate2(cdouble, I, T*2, dv);
3247 double ene=0;
3248 for (int l=0; l<L-1; l++)
3249 {
3250 //v from u given f[l]
3251 setv(I, T*2, v, dv, f[l+1], u, du);
3252 //compute -<s, v'> over the lth frame
3253 cdouble* ls=&s[l*T];
3254 for (int i=0; i<I; i++)
3255 {
3256 cdouble d=Inner(2*T, ls, v[i]);
3257 ene+=~d;
3258 }
3259 }
3260 if (endmode==1 || endmode==3)
3261 {
3262 //v from u given f[l]
3263 setvhalf(I, T, v, dv, (f[0]+f[1])/2, u, du);
3264 cdouble* ls=&s[0];
3265 for (int i=0; i<I; i++)
3266
3267 ene+=~Inner(T, ls, v[i]);
3268 }
3269 if (endmode==2 || endmode==3)
3270 {
3271 //v from u given f[l]
3272 setvhalf(I, T, v, dv, (f[L-1]+f[L])/2, u, du);
3273 cdouble* ls=&s[(L-1)*T];
3274 for (int i=0; i<I; i++)
3275 ene+=~Inner(T, ls, v[i]);
3276 }
3277 DeAlloc2(v); DeAlloc2(dv);
3278 return ene;
3279 }//testsv
3280
3281 /*
3282 function DerivativePiecewise3: Piecewise derivative algorithm in which the log amplitude and frequeny
3283 are modeled separately as piecewise functions. In this implementation of the piecewise method the test
3284 functions v are constructed from I "basic" (single-frame) test functions, each covering the same
3285 period of 2T, by shifting these I functions by steps of T. A total number of (L-1)I test functions are
3286 used.
3287
3288 In: s[LT+1]: waveform data
3289 ds[LT+1]: derivative of s[LT], used only if ERROR_CHECK is defined.
3290 L, T: number and length of pieces.
3291 N: number of independent coefficients
3292 h[M][T]: piecewise basis functions
3293 dh[M][T]: derivative of h[M][T], used only if ERROR_CHECK is defined.
3294 DA[L][M][Np]: L matrices that do coefficient mapping (real part) over the L pieces
3295 B[L][M][Nq]: L matrices that do coefficient mapping (imaginary part) over the L pieces
3296 u[I][2T}, du[I][2T]: base-band test functions
3297 f[L+1]: reference frequencies at 0, T, ..., LT, only f[1]...f[L-1] are used
3298 endmode: set to 1 or 3 to apply half-size testing over [0, T], to 2 or 3 to apply over [LT-T, LT]
3299 Out: p[Np], q[Nq]: independent coefficients
3300
3301 No return value.
3302 */
3303 void DerivativePiecewise3(int Np, double* p, int Nq, double* q, int L, double* f, int T, cdouble* s, double*** DA, double*** B,
3304 int M, double** h, int I, cdouble** u, cdouble** du, int endmode, cdouble* ds, double** dh)
3305 {
3306 MList* mlist=new MList;
3307 int L_1=(endmode==0)?(L-1):((endmode==3)?(L+1):L);
3308 cdouble** Allocate2L(cdouble, L_1, I, sv, mlist);
3309 cdouble** Allocate2L(cdouble, I, T*2, v, mlist);
3310 cdouble** Allocate2L(cdouble, I, T*2, dv, mlist);
3311 //compute <sr, v>
3312 cdouble*** Allocate3L(cdouble, L_1, I, Np, srav, mlist);
3313 cdouble*** srbv;
3314 if (Np==Nq && B==DA) srbv=srav; else {Allocate3L(cdouble, L_1, I, Nq, srbv, mlist);} //same model for amplitude and phase
3315 cdouble** Allocate2L(cdouble, I, M, shv1, mlist);
3316 cdouble** Allocate2L(cdouble, I, M, shv2, mlist);
3317
3318 #ifdef ERROR_CHECK
3319 cdouble dsv1in[128], dsv2in[128];
3320 #endif
3321
3322 for (int l=0; l<L-1; l++)
3323 {
3324 //v from u given f[l]
3325 setv(I, T*2, v, dv, f[l+1], u, du);
3326 //compute -<s, v'> over the lth frame
3327 cdouble* ls=&s[l*T]; for (int i=0; i<I; i++) sv[l][i]=-Inner(2*T, ls, dv[i]);
3328
3329 //compute <sr, v> over the lth frame
3330 cdouble *ls1=&s[l*T], *ls2=&s[l*T+T];
3331 for (int i=0; i<I; i++)
3332 for (int m=0; m<M; m++)
3333 shv1[i][m]=Inner(T, ls1, h[m], v[i]), shv2[i][m]=Inner(T, ls2, h[m], &v[i][T]);
3334 memset(srav[l][0], 0, sizeof(cdouble)*I*Np);
3335 MultiplyXY(I, M, Np, srav[l], shv1, DA[l]);
3336 MultiAddXY(I, M, Np, srav[l], shv2, DA[l+1]);
3337 if (srbv!=srav) //so that either B!=A or Np!=Nq
3338 {
3339 MultiplyXY(I, M, Nq, srbv[l], shv1, B[l]);
3340 MultiAddXY(I, M, Nq, srbv[l], shv2, B[l+1]);
3341 }
3342 #ifdef ERROR_CHECK
3343 //error check: <s', v>=-<s, v'> and srv[l]*pq=<s',v>
3344 if (ds) testdsv(&dsv1in[l*I], &dsv2in[l*I], Np, p, Nq, q, T*2, &ds[l*T], I, v, sv[l], srav[l], srbv[l]);
3345 #endif
3346 }
3347 L_1=L-1;
3348 if (endmode==1 || endmode==3)
3349 {
3350 //v from u given f[l]
3351 setvhalf(I, T, v, dv, (f[0]+f[1])/2, u, du);
3352 //compute -<s, v'> over the lth frame
3353 cdouble* ls=&s[0]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
3354 //compute <sr, v> over the lth frame
3355 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
3356 //memset(srav[L_1][0], 0, sizeof(cdouble)*I*Np);
3357 MultiplyXY(I, M, Np, srav[L_1], shv1, DA[0]);
3358 if (srbv!=srav) {memset(srbv[L_1][0], 0, sizeof(cdouble)*I*Nq); MultiplyXY(I, M, Nq, srbv[L_1], shv1, B[0]);}
3359 #ifdef ERROR_CHECK
3360 //error check: <s', v>=-<s, v'> and srv[l]*pq=<s',v>
3361 if (ds) testdsv(&dsv1in[L_1*I], &dsv2in[L_1*I], Np, p, Nq, q, T, &ds[0], I, v, sv[L_1], srav[L_1], srbv[L_1]);
3362 #endif
3363 L_1++;
3364 }
3365 if (endmode==2 || endmode==3)
3366 {
3367 //v from u given f[l]
3368 setvhalf(I, T, v, dv, (f[L-1]+f[L])/2, u, du);
3369 //compute -<s, v'> over the lth frame
3370 cdouble* ls=&s[(L-1)*T]; for (int i=0; i<I; i++) sv[L_1][i]=-Inner(T, ls, dv[i]);
3371 //compute <sr, v> over the lth frame
3372 for (int i=0; i<I; i++) for (int m=0; m<M; m++) shv1[i][m]=Inner(T, ls, h[m], v[i]);
3373 memset(srav[L_1][0], 0, sizeof(cdouble)*I*Np);
3374 MultiplyXY(I, M, Np, srav[L_1], shv1, DA[L-1]);
3375 if (srbv!=srav) MultiplyXY(I, M, Nq, srbv[L_1], shv1, B[L-1]);
3376 #ifdef ERROR_CHECK
3377 //error check: <s', v>=-<s, v'> and srv[l]*pq=<s',v>
3378 if (ds) testdsv(&dsv1in[L_1*I], &dsv2in[L_1*I], Np, p, Nq, q, T, &ds[(L-1)*T], I, v, sv[L_1], srav[L_1], srbv[L_1]);
3379 #endif
3380 L_1++;
3381 }
3382
3383 //real implementation of <sr,v>aita=<s',v>
3384 double** Allocate2L(double, L_1*I*2, Np+Nq, AM, mlist);
3385 for (int l=0; l<L_1; l++) for (int i=0; i<I; i++)
3386 {
3387 int li=l*I+i, li_H=li+L_1*I;
3388 for (int n=0; n<Np; n++)
3389 {
3390 AM[li][n]=srav[l][i][n].x;
3391 AM[li_H][n]=srav[l][i][n].y;
3392 }
3393 for (int n=0; n<Nq; n++)
3394 {
3395 AM[li][Np+n]=-srbv[l][i][n].y;
3396 AM[li_H][Np+n]=srbv[l][i][n].x;
3397 }
3398 }
3399 //least-square solution of (srv)(aita)=(sv)
3400 double* pq=new double[Np+Nq]; mlist->Add(pq, 1);
3401 double* b=new double[2*L_1*I]; for (int i=0; i<L_1*I; i++) b[i]=sv[0][i].x, b[i+L_1*I]=sv[0][i].y; mlist->Add(b, 1);
3402 #ifdef ERROR_CHECK
3403 //tests that AM is invariant to a constant shift of p
3404 double errAM=0, errAM2=0, err1, err2;
3405 for (int l=0; l<L_1*I; l++){double errli=0; for (int n=0; n<Np; n++) errli+=AM[l][n]; errAM+=errli*errli; errli=0; for (int n=0; n<Np; n+=2) errli+=AM[l][n]; errAM2+=errli*errli;}
3406 //test square error of the input pq
3407 if (ds)
3408 {
3409 memcpy(pq, p, sizeof(double)*Np); memcpy(&pq[Np], q, sizeof(double)*Nq);
3410 err1=testlinearsystem(L_1*I*2, Np+Nq, AM, pq, b);
3411 }
3412 //test error of s'-sR where R is synthesized from the input pq
3413 double errdsin, errdsvin; cdouble* edsin;
3414 if (ds && dh)
3415 {
3416 edsin=new cdouble[L*T]; mlist->Add(edsin, 1);
3417 errdsin=testds_pqA(Np, p, Nq, q, L, T, s, ds, M, h, dh, DA, B, edsin);
3418 errdsvin=testsv(L, f, T, edsin, I, u, du, endmode);
3419 }
3420 #endif
3421 Alloc2L(L_1*I*2, Np+Nq-1, Am, mlist);
3422 for (int l=0; l<L_1*I*2; l++) memcpy(Am[l], &AM[l][1], sizeof(double)*(Np+Nq-1));
3423 pq[0]=0;
3424 //if (L_1*2*I==Np+Nq) GECP(Np+Nq, pq, AM, b);
3425 //else LSLinear(2*L_1*I, Np+Nq, pq, AM, b);
3426 if (L_1*2*I==Np+Nq-1) GECP(Np+Nq-1, &pq[1], Am, b);
3427 else LSLinear(2*L_1*I, Np+Nq-1, &pq[1], Am, b);
3428 #ifdef ERROR_CHECK
3429 //test square error of output pq
3430 if (ds) err2=testlinearsystem(L_1*I*2, Np+Nq, AM, pq, b);
3431 //test error of s'-sR of the output pq
3432 double errdsout, errdsvout; cdouble* edsout;
3433 if (ds && dh)
3434 {
3435 edsout=new cdouble[L*T]; mlist->Add(edsout, 1);
3436 errdsout=testds_pqA(Np, pq, Nq, &pq[Np], L, T, s, ds, M, h, dh, DA, B, edsout);
3437 errdsvout=testsv(L, f, T, edsout, I, u, du, endmode);
3438 }
3439 #endif
3440 memcpy(p, pq, sizeof(double)*Np); memcpy(q, &pq[Np], sizeof(double)*Nq);
3441
3442 delete mlist;
3443 }//DerivativePiecewise3
3444
3445 //initialization routines for the piecewise derivative method
3446
3447 /*
3448 function seth: set h[M] to a series of power functions.
3449
3450 In: M, T.
3451 Out: h[M][T], where h[m] is power function of order m.
3452
3453 No return value. h is allocated anew and must be freed by caller.
3454 */
3455 void seth(int M, int T, double**& h, MList* mlist)
3456 {
3457 if (M<=0){h=0; return;}
3458 Allocate2L(double, M, T, h, mlist);
3459 double* hm=h[0]; for (int t=0; t<T; t++) hm[t]=1;
3460 for (int m=1; m<M; m++)
3461 {
3462 hm=h[m]; for (int t=0; t<T; t++) hm[t]=pow(t*1.0, m);
3463 }
3464 }//seth
3465
3466 /*
3467 function setdh: set dh[M] to the derivative of a series of power functions.
3468
3469 In: M, T.
3470 Out: dh[M][T], where dh[m] is derivative of the power function of order m.
3471
3472 No return value. dh is allocated anew and must be freed by caller.
3473 */
3474 void setdh(int M, int T, double**& dh, MList* mlist)
3475 {
3476 if (M<=0){dh=0; return;}
3477 Allocate2L(double, M, T, dh, mlist);
3478 double* dhm=dh[0]; memset(dhm, 0, sizeof(double)*T);
3479 if (M>1){dhm=dh[1]; for (int t=0; t<T; t++) dhm[t]=1;}
3480 for (int m=2; m<M; m++)
3481 {
3482 dhm=dh[m]; for (int t=0; t<T; t++) dhm[t]=m*pow(t*1.0, m-1);
3483 }
3484 }//setdh
3485
3486 /*
3487 function setdih: set dih[M] to the difference of the integral of a series of power functions.
3488
3489 In: M, I
3490 Out: dih[M][I], where the accumulation of dih[m] is the integral of the power function of order m.
3491
3492 No return value. dih is allocated anew and must be freed by caller.
3493 */
3494 void setdih(int M, int T, double**& dih, MList* mlist)
3495 {
3496 if (M<=0){dih=0; return;}
3497 Allocate2L(double, M, T, dih, mlist);
3498 double* dihm=dih[0]; for (int t=0; t<T; t++) dihm[t]=1;
3499 for (int m=1; m<M; m++)
3500 {
3501 dihm=dih[m]; for (int t=0; t<T; t++) dihm[t]=(pow(t+1.0, m+1)-pow(t*1.0, m+1))/(m+1);
3502 }
3503 }//setdih
3504
3505 /*
3506 function sshLinear: sets M and h[M] for the linear spline model
3507
3508 In: T
3509 Out: M=2, h[2][T] filled out for linear spline model.
3510
3511 No return value. h is allocated anew and must be freed by caller.
3512 */
3513 void sshLinear(int T, int& M, double** &h, MList* mlist)
3514 {
3515 M=2; Allocate2L(double, M, T, h, mlist);
3516 for (int t=0; t<T; t++) h[0][t]=1, h[1][t]=t;
3517 }//sshLinear
3518
3519 /*
3520 function sdihLinear: sets dih[M] for the linear spline model. For testing only.
3521
3522 In: T
3523 Out: dih[2][T] filled out for linear spline model.
3524
3525 No return value. dih is allocated anew and must be freed by caller.
3526 */
3527 void sdihLinear(int T, double**& dih, MList* mlist)
3528 {
3529 Allocate2L(double, 2, T, dih, mlist);
3530 for (int t=0; t<T; t++) dih[0][t]=1, dih[1][t]=t+0.5;
3531 }//sdihLinear
3532
3533 /*
3534 function sshCubic: sets M and h[M] for cubic spline models.
3535
3536 In: T
3537 Out: M=4 and h[M] filled out for cubic spline models, including cubic and cubic-Hermite.
3538
3539 No return value. h is allocated anew and must be freed by caller.
3540 */
3541 void sshCubic(int T, int& M, double** &h, MList* mlist)
3542 {
3543 M=4; Allocate2L(double, M, T, h, mlist);
3544 for (int t=0; t<T; t++) h[3][t]=t*t*t, h[2][t]=t*t, h[1][t]=t, h[0][t]=1;
3545 }//sshCubic
3546
3547 /*
3548 function sdihCubic: sets dih[M] for cubic spline models.
3549
3550 In: T
3551 Out: dih[4] filled out for cubic spline models.
3552
3553 No return value. dih is allocated anew and must be freed by caller.
3554 */
3555 void sdihCubic(int T, double** &dih, MList* mlist)
3556 {
3557 Allocate2L(double, 4, T, dih, mlist);
3558 for (int t=0; t<T; t++)
3559 {
3560 dih[3][t]=t*(t*(t+1.5)+1)+0.25, dih[2][t]=t*(t+1)+1.0/3, dih[1][t]=t+0.5, dih[0][t]=1;
3561 }
3562 }//sdihCubic*/
3563
3564 /*
3565 function ssALinearSpline: sets N and A[L] for the linear spline model
3566
3567 In: L, M, T
3568 Out: N=L+1, A[L][M][N] filled out for the linear spline model
3569
3570 No return value. A is created anew and bust be freed by caller.
3571 */
3572 void ssALinearSpline(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode)
3573 {
3574 N=L+1;
3575 Allocate3L(double, L, M, N, A, mlist);
3576 memset(A[0][0], 0, sizeof(double)*L*M*N);
3577 double iT=1.0/T; for (int l=0; l<L; l++) A[l][0][l]=1, A[l][1][l]=-iT, A[l][1][l+1]=iT;
3578 }//ssALinearSpline
3579
3580 /*
3581 function ssLinearSpline: sets M, N, h and A for the linear spline model
3582
3583 In: L, M, T
3584 Out: N and h[][] and A[][][] filled out for the linear spline model
3585
3586 No reutrn value. A and h are created anew and bust be freed by caller.
3587 */
3588 void ssLinearSpline(int L, int T, int M, int &N, double** &h, double*** &A, MList* mlist, int mode)
3589 {
3590 seth(M, T, h, mlist);
3591 ssALinearSpline(L, T, M, N, A, mlist);
3592 }//ssLinearSpline
3593
3594 /*
3595 function ssACubicHermite: sets N and A[L] for cubic Hermite spline model
3596
3597 In: L, M, T
3598 Out: N=2(L+1), A[L][M][N] filled out for the cubic Hermite spline
3599
3600 No return value. A is created anew and must be freed by caller.
3601 */
3602 void ssACubicHermite(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode)
3603 {
3604 N=2*(L+1);
3605 Allocate3L(double, L, M, N, A, mlist); memset(A[0][0], 0, sizeof(double)*L*M*N);
3606 double iT=1.0/T, iT2=iT*iT, iT3=iT2*iT;
3607 for (int l=0; l<L; l++)
3608 {
3609 A[l][3][2*l]=2*iT3; A[l][3][2*l+2]=-2*iT3; A[l][3][2*l+1]=A[l][3][2*l+3]=iT2;
3610 A[l][2][2*l]=-3*iT2; A[l][2][2*l+1]=-2*iT; A[l][2][2*l+2]=3*iT2; A[l][2][2*l+3]=-iT;
3611 A[l][1][2*l+1]=1;
3612 A[l][0][2*l]=1;
3613 }
3614 }//ssACubicHermite
3615
3616 /*
3617 function ssLinearSpline: sets M, N, h and A for the cubic Hermite spline model
3618
3619 In: L, M, T
3620 Out: N and h[][] and A[][][] filled out for the cubic Hermite spline model
3621
3622 No reutrn value. A and h are created anew and bust be freed by caller.
3623 */
3624 void ssCubicHermite(int L, int T, int M, int& N, double** &h, double*** &A, MList* mlist, int mode)
3625 {
3626 seth(M, T, h, mlist);
3627 ssACubicHermite(L, T, M, N, A, mlist);
3628 }//ssCubicHermite
3629
3630 /*
3631 function ssACubicSpline: sets N and A[L] for cubic spline model
3632
3633 In: L, M, T
3634 mode: boundary mode of cubic spline, 0=natural, 1=quadratic run-out, 2=cubic run-out
3635 Out: N=2(L+1), A[L][M][N] filled out for the cubic spline
3636
3637 No return value. A is created anew and must be freed by caller.
3638 */
3639 void ssACubicSpline(int L, int T, int M, int& N, double*** &A, MList* mlist, int mode)
3640 {
3641 N=L+1;
3642 Allocate3L(double, L, M, N, A, mlist); memset(A[0][0], 0, sizeof(double)*L*M*N);
3643 Alloc2(L+1, L+1, ML); memset(ML[0], 0, sizeof(double)*(L+1)*(L+1));
3644 Alloc2(L+1, L+1, MR); memset(MR[0], 0, sizeof(double)*(L+1)*(L+1));
3645 //fill in ML and MR. The only difference between various cubic splines are ML.
3646 double _6iT2=6.0/(T*T);
3647 ML[0][0]=ML[L][L]=1;
3648 for (int l=1; l<L; l++) ML[l][l-1]=ML[l][l+1]=1, ML[l][l]=4,
3649 MR[l][l-1]=MR[l][l+1]=_6iT2, MR[l][l]=-2*_6iT2;
3650 if (mode==0){} //no more coefficients are needed for natural cubic spline
3651 else if (mode==1) ML[0][1]=ML[L][L-1]=-1; //setting for quadratic run-out
3652 else if (mode==2) ML[0][1]=ML[L][L-1]=-2, ML[0][2]=ML[L][L-2]=1; //setting for cubic run-out
3653 GICP(L+1, ML);
3654 double** MM=MultiplyXY(L+1, ML, ML, MR);
3655 double iT=1.0/T;
3656 Alloc2(4, 2, M42); M42[3][0]=-1.0/6/T, M42[3][1]=1.0/6/T, M42[2][0]=0.5, M42[2][1]=M42[0][0]=M42[0][1]=0, M42[1][0]=-T/3.0, M42[1][1]=-T/6.0;
3657 for (int l=0; l<L; l++)
3658 {
3659 MultiplyXY(4, 2, N, A[l], M42, &MM[l]);
3660 A[l][1][l]-=iT; A[l][1][l+1]+=iT; A[l][0][l]+=1;
3661 }
3662 DeAlloc2(ML); DeAlloc2(MR); DeAlloc2(M42);
3663 }//ssACubicSpline
3664
3665 /*
3666 function ssLinearSpline: sets M, N, h and A for the cubic spline model
3667
3668 In: L, M, T
3669 Out: N and h[][] and A[][][] filled out for the cubic spline model
3670
3671 No reutrn value. A and h are created anew and bust be freed by caller.
3672 */
3673 void ssCubicSpline(int L, int T, int M, int& N, double** &h, double*** &A, MList* mlist, int mode)
3674 {
3675 seth(M, T, h, mlist);
3676 ssACubicSpline(L, T, M, N, A, mlist, mode);
3677 }//ssCubicSpline
3678
3679 /*
3680 function setu: sets u[I+1] as base-band windowed Fourier atoms, whose frequencies come in the order of
3681 0, 1, -1, 2, -2, 3, -3, 4, etc, in bins.
3682
3683 In: I, Wid: number and size of atoms to generate.
3684 WinOrder: order (=vanishing moment) of window function to use (2=Hann, 4=Hann^2, etc.)
3685 Out: u[I+1][Wid], du[I+1]{Wid]: the I+1 atoms and their derivatives.
3686
3687 No return value. u and du are created anew and must be freed by caller.
3688 */
3689 void setu(int I, int Wid, cdouble**& u, cdouble**& du, int WinOrder, MList* mlist)
3690 {
3691 Allocate2L(cdouble, I+1, Wid, u, mlist);
3692 Allocate2L(cdouble, I+1, Wid, du, mlist);
3693
3694 double** wins=CosineWindows(WinOrder, Wid, (double**)0, 2);
3695 double omg=2*M_PI/Wid; cdouble jomg=cdouble(0, omg);
3696 for (int t=0; t<Wid; t++)
3697 {
3698 u[0][t]=wins[0][t], du[0][t]=wins[1][t];
3699 int li=1;
3700 for (int i=1; i<=I; i++)
3701 {
3702 cdouble rot=polar(1.0, li*omg*t);
3703 u[i][t]=u[0][t]*rot; du[i][t]=du[0][t]*rot+jomg*li*u[i][t];
3704 li=-li; if (li>0) li++;
3705 }
3706 }
3707 DeAlloc2(wins);
3708 }//setu
3709
3710 /*
3711 function DerivativePiecewiseI: wrapper for DerivativePiecewise(), doing the initialization ,etc.
3712
3713 In: L, T: number and length of pieces
3714 s[LT]: waveform signal
3715 ds[LT]: derivative of s[LT], used only when ERROR_CHECK is defined.
3716 f[L+1]: reference frequencies at knots
3717 M: polynomial degree of piecewise approximation
3718 SpecifyA, ssmode: pointer to a function that fills A[L], and mode argument to call it
3719 WinOrder: order(=vanishing moment) of window used for constructing test functions
3720 I: number of test functions per frame.
3721 endmode: set to 1 or 3 to apply half-size frame over [0, T], to 2 or 3 to apply over [LT-T, LT]
3722 Out: aita[N]: independent coefficients, where N is specified by SpecifyA.
3723
3724 No return vlue.
3725 */
3726 void DerivativePiecewiseI(cdouble* aita, int L, double* f, int T, cdouble* s, int M,
3727 void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssmode,
3728 int WinOrder, int I, int endmode, cdouble* ds)
3729 {
3730 MList* mlist=new MList;
3731 cdouble **u, **du;
3732 setu(I, 2*T, u, du, WinOrder, mlist);
3733
3734 int N; double **h, ***A;
3735 seth(M, T, h, mlist);
3736 SpecifyA(L, T, M, N, A, mlist, ssmode);
3737
3738 DerivativePiecewise(N, aita, L, f, T, s, A, M, h, I, u, du, endmode, ds);
3739 delete mlist;
3740 }//DerivativePiecewiseI
3741
3742 /*
3743 function DerivativePiecewiseII: wrapper for DerivativePiecewise2(), doing the initialization ,etc.
3744 This models the derivative of log ampltiude and frequency as separate piecewise polynomials, the first
3745 specified by SpecifyA, the second by SpecifyB.
3746
3747 In: L, T: number and length of pieces
3748 s[LT]: waveform signal
3749 ds[LT]: derivative of s[LT], used only when ERROR_CHECK is defined.
3750 f[L+1]: reference frequencies at knots
3751 M: polynomial degree of piecewise approximation
3752 SpecifyA, ssAmode: pointer to a function that fills A[L], and mode argument to call it
3753 SpecifyB, ssBmode: pointer to a function that fills B[L], and mode argument to call it
3754 WinOrder: order(=vanishing moment) of window used for constructing test functions
3755 I: number of test functions per frame.
3756 endmode: set to 1 or 3 to apply half-size frame over [0, T], to 2 or 3 to apply over [LT-T, LT]
3757 Out: p[Np], q[Nq]: independent coefficients, where Np and Nq are specified by SpecifyA and SpecifyB.
3758
3759 No reutrn value.
3760 */
3761 void DerivativePiecewiseII(double* p, double* q, int L, double* f, int T, cdouble* s, int M,
3762 void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssAmode,
3763 void (*SpecifyB)(int L, int T, int M, int &N, double*** &B, MList* mlist, int mode), int ssBmode,
3764 int WinOrder, int I, int endmode, cdouble* ds)
3765 {
3766 MList* mlist=new MList;
3767 cdouble **u, **du;
3768 setu(I, 2*T, u, du, WinOrder, mlist);
3769
3770 int Np, Nq;
3771 double **h, ***A, ***B;
3772 seth(M, T, h, mlist);
3773 SpecifyA(L, T, M, Np, A, mlist, ssAmode);
3774 SpecifyB(L, T, M, Nq, B, mlist, ssBmode);
3775
3776 DerivativePiecewise2(Np, p, Nq, q, L, f, T, s, A, B, M, h, I, u, du, endmode, ds);
3777
3778 delete mlist;
3779 }//DerivativePiecewiseII
3780
3781 /*
3782 function DerivativePiecewiseIII: wrapper for DerivativePiecewise3(), doing the initialization ,etc.
3783 Notice that this time the log amplitude, rather than its derivative, is modeled as a piecewise
3784 polynomial specified by SpecifyA.
3785
3786 In: L, T: number and length of pieces
3787 s[LT]: waveform signal
3788 ds[LT]: derivative of s[LT], used only when ERROR_CHECK is defined.
3789 f[L+1]: reference frequencies at knots
3790 M: polynomial degree of piecewise approximation
3791 SpecifyA, ssAmode: pointer to a function that fills A[L], and mode argument to call it
3792 SpecifyB, ssBmode: pointer to a function that fills B[L], and mode argument to call it
3793 WinOrder: order(=vanishing moment) of window used for constructing test functions
3794 I: number of test functions per frame.
3795 endmode: set to 1 or 3 to apply half-size frame over [0, T], to 2 or 3 to apply over [LT-T, LT]
3796 Out: p[Np], q[Nq]: independent coefficients, where Np and Nq are specified by SpecifyA and SpecifyB.
3797
3798 No reutrn value.
3799 */
3800 void DerivativePiecewiseIII(double* p, double* q, int L, double* f, int T, cdouble* s, int M,
3801 void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int ssAmode,
3802 void (*SpecifyB)(int L, int T, int M, int &N, double*** &B, MList* mlist, int mode), int ssBmode,
3803 int WinOrder, int I, int endmode, cdouble* ds)
3804 {
3805 MList* mlist=new MList;
3806 int Np, Nq;
3807 double **h, ***A, ***B, **dh=0;
3808 cdouble **u, **du;
3809 setu(I, T*2, u, du, WinOrder, mlist);
3810 seth(M, T, h, mlist);
3811 if (ds) setdh(M, T, dh, mlist);
3812 SpecifyA(L, T, M, Np, A, mlist, ssAmode);
3813 SpecifyB(L, T, M, Nq, B, mlist, ssBmode);
3814 Alloc2L(M, M, DM, mlist);
3815 memset(DM[0], 0, sizeof(double)*M*M); for (int m=0; m<M-1; m++) DM[m][m+1]=m+1;
3816 double** DA=0;
3817
3818 for (int l=0; l<L; l++)
3819 {
3820 DA=MultiplyXY(M, M, Np, DA, DM, A[l], mlist);
3821 Copy(M, Np, A[l], DA);
3822 }
3823
3824 DerivativePiecewise3(Np, p, Nq, q, L, f, T, s, A, B, M, h, I, u, du, endmode, ds, dh);
3825
3826 delete mlist;
3827 }//DerivativePiecewiseIII
3828
3829 /*
3830 function AmpPhCorrectionExpA: model-preserving amplitude and phase correction in piecewise derivative
3831 method.
3832
3833 In: aita[N]: inital independent coefficients
3834 L, T: number and size of pieces
3835 sre[LT]: waveform data
3836 h[M][T], dih[M][T]: piecewise basis functions and their difference-integrals
3837 A[L][M][N]: L coefficient mapping matrices
3838 SpecifyA: pointer to the function used for constructing A
3839 WinOrder: order(=vanishing moment) of window used for constructing test functions
3840 Out: aita[N]: corrected independent coefficients
3841 s2[LT]: reconstruct sinusoid BEFORE correction
3842
3843 Returns the estimate of phase angle at 0.
3844 */
3845 double AmpPhCorrectionExpA(cdouble* s2, int N, cdouble* aita, int L, int T, cdouble* sre, int M, double** h, double** dih, double*** A,
3846 void (*SpecifyA)(int L, int T, int M, int &N, double*** &A, MList* mlist, int mode), int WinOrder)
3847 {
3848 MList* mlist=new MList;
3849 //*amplitude and phase correction
3850 //amplitude is done by updating p, i.e. Re(aita)
3851 double *s2ph=new double[L+1]; mlist->Add(s2ph, 1);
3852 double *phcor=new double[L+1]; mlist->Add(phcor, 1);
3853 cdouble* lamda=new cdouble[M]; mlist->Add(lamda, 1);
3854 double* lamdax=new double[M]; mlist->Add(lamdax, 1);
3855 double* lamday=new double[M]; mlist->Add(lamday, 1);
3856 {
3857 double tmpph=0;
3858 memset(s2ph, 0, sizeof(double)*(L+1));
3859 s2ph[0]=tmpph;
3860 for (int l=0; l<L; l++)
3861 {
3862 MultiplyXy(M, N, lamda, A[l], aita); for (int m=0; m<M; m++) lamdax[m]=lamda[m].x, lamday[m]=lamda[m].y;
3863 SinusoidExpA(T, &s2[l*T], M, lamdax, lamday, h, dih, tmpph); s2ph[l+1]=tmpph;
3864 }
3865 double* win=new double[2*T+1]; CosineWindows(WinOrder, 2*T, &win, 1); mlist->Add(win, 1);
3866 for (int l=1; l<L; l++)
3867 {
3868 cdouble inn=Inner(2*T, &sre[l*T-T], win, &s2[l*T-T])/Inner(2*T, &s2[l*T-T], win, &s2[l*T-T]);
3869 cdouble loginn=log(inn);
3870 if (SpecifyA==ssACubicHermite)
3871 {
3872 aita[l*2]+=loginn.x;
3873 s2ph[l]+=loginn.y;
3874 phcor[l]=loginn.y;
3875 if (l==1) aita[0]+=loginn.x, phcor[0]=loginn.y, s2ph[0]+=loginn.y;
3876 if (l==L-1) aita[L*2]+=loginn.x, phcor[L]=loginn.y, s2ph[L]+=loginn.y;
3877 }
3878 else
3879 {
3880 aita[l]+=loginn.x;
3881 s2ph[l]+=loginn.y;
3882 phcor[l]=loginn.y;
3883 if (l==1)
3884 {
3885 inn=Inner(T, sre, &win[T], s2)/Inner(T, s2, &win[T], s2);
3886 loginn=log(inn);
3887 aita[0]+=loginn.x;
3888 s2ph[0]+=loginn.y;
3889 phcor[0]=loginn.y;
3890 }
3891 if (l==L-1)
3892 {
3893 inn=Inner(T, &sre[L*T-T], win, &s2[L*T-T])/Inner(T, &s2[L*T-T], win, &s2[L*T-T]);
3894 loginn=log(inn);
3895 aita[L]+=loginn.x;
3896 s2ph[L]+=loginn.y;
3897 phcor[L]=loginn.y;
3898 }
3899 }
3900 }
3901
3902 for (int l=1; l<=L; l++)
3903 {
3904 int k=floor((phcor[l]-phcor[l-1])/(2*M_PI)+0.5);
3905 if (k!=0)
3906 phcor[l]+=2*M_PI*k;
3907 }
3908 //*
3909 //now phcor[] contains phase corrector to be interpolated
3910 double *b=new double[L], *zet=new double[L+1], *dzet=new double[L+1]; memset(zet, 0, sizeof(double)*(L+1)); memset(dzet, 0, sizeof(double)*(L+1));
3911 mlist->Add(b, 1); mlist->Add(zet, 1); mlist->Add(dzet, 1);
3912 double ihT[]={T, T/2.0*T, T/3.0*T*T, T/4.0*T*T*T};
3913
3914 Alloc2L(L, N, BB, mlist);
3915 //prepare linear system (BB)(zet)=(b)
3916 for (int l=0; l<L; l++)
3917 {
3918 MultiplyxY(N, 4, BB[l], ihT, A[l]);
3919 b[l]=phcor[l+1]-phcor[l];
3920 }
3921 Alloc2L(L, L, copyA, mlist);
3922 if (L+1==N) for (int l=0; l<L; l++) memcpy(copyA[l], &BB[l][1], sizeof(double)*L);
3923 else if (L+1==N/2) for (int l=0; l<L; l++) for (int k=0; k<L; k++) copyA[l][k]=BB[l][2*k+2];
3924 double* copyb=Copy(L, b, mlist);
3925 zet[0]=0; GECP(L, &zet[1], copyA, copyb);
3926 if (L+1==N) for (int l=0; l<L; l++) memcpy(copyA[l], &BB[l][1], sizeof(double)*L);
3927 else if (L+1==N/2) for (int l=0; l<L; l++) for (int k=0; k<L; k++) copyA[l][k]=BB[l][2*k+2];
3928 Copy(L, copyb, b); for (int l=0; l<L; l++) copyb[l]-=BB[l][0];
3929 dzet[0]=1; GECP(L, &dzet[1], copyA, copyb);
3930
3931 #ifdef ERROR_CHECK
3932 //Test that (BB)(zet)=b and (BB)(dzet)=b
3933 double* bbzet=MultiplyXy(L, L+1, BB, zet, mlist);
3934 MultiAdd(L, bbzet, bbzet, b, -1);
3935 double err1=Inner(L, bbzet, bbzet);
3936 double* bbdzet=MultiplyXy(L, L+1, BB, dzet, mlist);
3937 MultiAdd(L, bbdzet, bbdzet, b, -1);
3938 double err2=Inner(L, bbdzet, bbdzet);
3939 MultiAdd(L+1, dzet, dzet, zet, -1);
3940 //Test that (BB)dzet=0
3941 MultiplyXy(L, L+1, bbdzet, BB, dzet);
3942 double err3=Inner(L, bbzet, bbzet);
3943 #endif
3944 //now that (zet)+(miu)(dzet) is the general solution to (BB)(zet)=b,
3945 // we look for (miu) that maximizes smoothness
3946
3947 double innuv=0, innvv=0, lmd0[4], lmdd[4], clmdd[4],
3948 T2=T*T, T3=T2*T, T4=T3*T, T5=T4*T;
3949 for (int l=0; l<L; l++)
3950 {
3951 MultiplyXy(4, L+1, lmd0, A[l], zet);
3952 MultiplyXy(4, L+1, lmdd, A[l], dzet);
3953 clmdd[1]=T*lmdd[1]+T2*lmdd[2]+T3*lmdd[3];
3954 clmdd[2]=T2*lmdd[1]+(4.0/3)*T3*lmdd[2]+1.5*T4*lmdd[3];
3955 clmdd[3]=T3*lmdd[1]+1.5*T4*lmdd[2]+1.8*T5*lmdd[3];
3956 innuv+=Inner(3, &lmd0[1], &clmdd[1]);
3957 innvv+=Inner(3, &lmdd[1], &clmdd[1]);
3958 }
3959 MultiAdd(L+1, zet, zet, dzet, -innuv/innvv);
3960
3961 if (SpecifyA==ssACubicHermite)
3962 for (int l=0; l<=L; l++) aita[2*l].y+=zet[l];
3963 else
3964 for (int l=0; l<=L; l++) aita[l].y+=zet[l];
3965 //*/
3966 }
3967 double result=s2ph[0];
3968 delete mlist;
3969 return result;
3970 }//AmpPhCorrectionExpA