Mercurial > hg > x
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 *)¶ms; | |
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 *)¶ms; | |
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 |