xue@11
|
1 /*
|
xue@11
|
2 Harmonic sinusoidal modelling and tools
|
xue@11
|
3
|
xue@11
|
4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
|
xue@11
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@11
|
6 This file copyright 2011 Wen Xue.
|
xue@11
|
7
|
xue@11
|
8 This program is free software; you can redistribute it and/or
|
xue@11
|
9 modify it under the terms of the GNU General Public License as
|
xue@11
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@11
|
11 License, or (at your option) any later version.
|
xue@11
|
12 */
|
xue@1
|
13 //---------------------------------------------------------------------------
|
xue@1
|
14
|
xue@1
|
15 #include "align8.h"
|
Chris@2
|
16 #include "sinsyn.h"
|
xue@1
|
17 #include "splines.h"
|
xue@1
|
18
|
Chris@5
|
19 /** \file sinsyn.h */
|
Chris@5
|
20
|
xue@1
|
21 //---------------------------------------------------------------------------
|
Chris@5
|
22 /**
|
xue@7
|
23 function CosSin: recursive cos-sin generator with trinomial frequency
|
xue@7
|
24
|
xue@7
|
25 In: CountSt, CountEn
|
xue@7
|
26 f3, f2, f1, f0: trinomial coefficients of frequency
|
xue@7
|
27 ph: initial phase angle at 0 (NOT at CountSt)
|
xue@7
|
28 Out: datar[CountSt:CountEn-1], datai[CountSt:CountEn-1]: synthesized pair of cosine and sine functions
|
xue@7
|
29 ph: phase angle at CountEn
|
xue@7
|
30
|
xue@7
|
31 No return value.
|
xue@7
|
32 */
|
xue@7
|
33 void CosSin(double* datar, double* datai, int CountSt, int CountEn, double f3, double f2, double f1, double f0, double &ph)
|
xue@7
|
34 {
|
xue@7
|
35 int i;
|
xue@7
|
36 double dph, ddph, dddph, ddddph,
|
xue@7
|
37 sph, cph, sdph, cdph, sddph, cddph, sdddph, cdddph, sddddph, cddddph,
|
xue@7
|
38 p0=ph, p1=2*M_PI*f0, p2=M_PI*f1, p3=2.0*M_PI*f2/3, p4=2.0*M_PI*f3/4, tmp;
|
xue@7
|
39 if (CountSt==0)
|
xue@7
|
40 {
|
xue@7
|
41 dph=p1+p2+p3+p4; ddph=2*p2+6*p3+14*p4; dddph=6*p3+36*p4; ddddph=24*p4;
|
xue@7
|
42 }
|
xue@7
|
43 else
|
xue@7
|
44 {
|
xue@7
|
45 ph=p0+CountSt*(p1+CountSt*(p2+CountSt*(p3+CountSt*p4)));
|
xue@7
|
46 dph=p1+p2+p3+p4+CountSt*(2*p2+3*p3+4*p4+CountSt*(3*p3+6*p4+CountSt*4*p4));
|
xue@7
|
47 ddph=2*p2+6*p3+14*p4+CountSt*(6*p3+24*p4+CountSt*12*p4);
|
xue@7
|
48 dddph=6*p3+36*p4+CountSt*24*p4; ddddph=24*p4;
|
xue@7
|
49 }
|
xue@7
|
50 sph=sin(ph), cph=cos(ph);
|
xue@7
|
51 sdph=sin(dph), cdph=cos(dph);
|
xue@7
|
52 sddph=sin(ddph), cddph=cos(ddph);
|
xue@7
|
53 sdddph=sin(dddph), cdddph=cos(dddph);
|
xue@7
|
54 sddddph=sin(ddddph), cddddph=cos(ddddph);
|
xue@7
|
55
|
xue@7
|
56 for (i=CountSt; i<CountEn; i++)
|
xue@7
|
57 {
|
xue@7
|
58 datar[i]=cph; datai[i]=sph;
|
xue@7
|
59 tmp=cph*cdph-sph*sdph; sph=sph*cdph+cph*sdph; cph=tmp;
|
xue@7
|
60 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@7
|
61 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@7
|
62 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@7
|
63 }
|
xue@7
|
64 ph=p0+CountEn*(p1+CountEn*(p2+CountEn*(p3+CountEn*p4)));
|
xue@7
|
65 }//CosSin*/
|
xue@7
|
66
|
xue@7
|
67 /**
|
xue@1
|
68 function Sinuoid: original McAuley-Quatieri synthesizer interpolation between two measurement points.
|
xue@1
|
69
|
xue@1
|
70 In: T: length from measurement point 1 to measurement point 2
|
xue@1
|
71 a1, f1, p2: amplitude, frequency and phase angle at measurement point 1
|
xue@1
|
72 a2, f2, p2: amplitude, frequency and phase angle at measurement point 2
|
xue@1
|
73 ad: specifies if the resynthesized sinusoid is to be added to or to replace the contents of output buffer
|
xue@1
|
74 Out: data[T]: output buffer
|
xue@1
|
75 a[T], f[T], p[T]: resynthesized amplitude, frequency and phase
|
xue@1
|
76
|
xue@1
|
77 No return value.
|
xue@1
|
78 */
|
xue@1
|
79 void Sinusoid(double* data, int T, double a1, double a2, double f1, double f2, double p1, double p2, double* a, double* f, double* p, bool ad)
|
xue@1
|
80 {
|
xue@1
|
81 int M=floor(((p1-p2)/M_PI+(f1+f2)*T)/2.0+0.5);
|
xue@1
|
82 double b1=p2-p1-2*M_PI*(f1*T-M), b2=2*M_PI*(f2-f1);
|
xue@1
|
83 double pa=(3*b1/T-b2)/T, pb=(-2*b1/T+b2)/T/T, pc=2*M_PI*f1, pd=p1;
|
xue@1
|
84 double la=a1, da=(a2-a1)/T;
|
xue@1
|
85 if (ad)
|
xue@1
|
86 for (int t=0; t<T; t++)
|
xue@1
|
87 {
|
xue@1
|
88 double lp=pd+t*(pc+t*(pa+t*pb)), lf=(pc+2*pa*t+3*pb*t*t)/2/M_PI;
|
xue@1
|
89 data[t]+=la*cos(lp);
|
xue@1
|
90 a[t]=la;
|
xue@1
|
91 p[t]=lp;
|
xue@1
|
92 f[t]=lf;
|
xue@1
|
93 la=la+da;
|
xue@1
|
94 }
|
xue@1
|
95 else
|
xue@1
|
96 for (int t=0; t<T; t++)
|
xue@1
|
97 {
|
xue@1
|
98 double lp=pd+t*(pc+t*(pa+t*pb)), lf=(pc+2*pa*t+3*pb*t*t)/2/M_PI;
|
xue@1
|
99 data[t]=la*cos(lp);
|
xue@1
|
100 a[t]=la;
|
xue@1
|
101 p[t]=lp;
|
xue@1
|
102 f[t]=lf;
|
xue@1
|
103 la=la+da;
|
xue@1
|
104 }
|
xue@1
|
105 }//Sinusoid
|
xue@1
|
106
|
Chris@5
|
107 /**
|
xue@1
|
108 function Sinuoid: original McAuley-Quatieri synthesizer interpolation between two measurement points,
|
xue@1
|
109 without returning interpolated sinusoid parameters.
|
xue@1
|
110
|
xue@1
|
111 In: T: length from measurement point 1 to measurement point 2
|
xue@1
|
112 a1, f1, p2: amplitude, frequency and phase angle at measurement point 1
|
xue@1
|
113 a2, f2, p2: amplitude, frequency and phase angle at measurement point 2
|
xue@1
|
114 ad: specifies if the resynthesized sinusoid is to be added to or to replace the contents of output buffer
|
xue@1
|
115 Out: data[T]: output buffer
|
xue@1
|
116
|
xue@1
|
117 No return value.
|
xue@1
|
118 */
|
xue@1
|
119 void Sinusoid(double* data, int T, double a1, double a2, double f1, double f2, double p1, double p2, bool ad)
|
xue@1
|
120 {
|
xue@1
|
121 int M=floor(((p1-p2)/M_PI+(f1+f2)*T)/2.0+0.5);
|
xue@1
|
122 double b1=p2-p1-2*M_PI*(f1*T-M), b2=2*M_PI*(f2-f1);
|
xue@1
|
123 double pa=(3*b1/T-b2)/T, pb=(-2*b1/T+b2)/T/T, pc=2*M_PI*f1, pd=p1;
|
xue@1
|
124 double la=a1, da=(a2-a1)/T;
|
xue@1
|
125 if (ad)
|
xue@1
|
126 for (int t=0; t<T; t++)
|
xue@1
|
127 {
|
xue@1
|
128 data[t]+=la*cos(pd+t*(pc+t*(pa+t*pb)));
|
xue@1
|
129 la=la+da;
|
xue@1
|
130 }
|
xue@1
|
131 else
|
xue@1
|
132 for (int t=0; t<T; t++)
|
xue@1
|
133 {
|
xue@1
|
134 data[t]=la*cos(pd+t*(pc+t*(pa+t*pb)));
|
xue@1
|
135 la=la+da;
|
xue@1
|
136 }
|
xue@1
|
137 }//Sinusoid
|
xue@1
|
138
|
xue@1
|
139 //---------------------------------------------------------------------------
|
Chris@5
|
140 /**
|
xue@1
|
141 function Sinusoid_direct: synthesizes sinusoid over [CountSt, CountEn) from tronomial coefficients of
|
xue@1
|
142 amplitude and frequency, direct implementation.
|
xue@1
|
143
|
xue@1
|
144 In: CountSt, CountEn
|
xue@1
|
145 aa, ab, ac, ad: trinomial coefficients of amplitude
|
xue@1
|
146 fa, fb, fc, fd: trinomial coefficients of frequency
|
xue@1
|
147 p1: initial phase angle at 0 (NOT at CountSt)
|
xue@1
|
148 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
149 Out: data[CountSt:CountEn-1]: output buffer.
|
xue@1
|
150 p1: phase angle at CountEn
|
xue@1
|
151
|
xue@1
|
152 No return value.
|
xue@1
|
153 */
|
xue@1
|
154 void Sinusoid_direct(double* data, int CountSt, int CountEn, double aa, double ab, double ac, double ad,
|
xue@1
|
155 double fa, double fb, double fc, double fd, double &p1, bool add)
|
xue@1
|
156 {
|
xue@1
|
157 int i; double a, ph;
|
xue@1
|
158 for (i=CountSt; i<CountEn; i++)
|
xue@1
|
159 {
|
xue@1
|
160 a=ad+i*(ac+i*(ab+i*aa));
|
xue@1
|
161 ph=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@1
|
162 if (add) data[i]+=a*cos(ph);
|
xue@1
|
163 else data[i]=a*cos(ph);
|
xue@1
|
164 }
|
xue@1
|
165 p1=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@1
|
166 }//Sinusoid
|
xue@1
|
167
|
Chris@5
|
168 /**
|
xue@7
|
169 function Sinusoid_direct: synthesizes sinusoid over [CountSt, CountEn) from tronomial coefficients of
|
xue@7
|
170 amplitude and frequency, direct implementation returning sinusoid coefficients rather than waveform.
|
xue@7
|
171
|
xue@7
|
172 In: CountSt, CountEn
|
xue@7
|
173 aa, ab, ac, ad: trinomial coefficients of amplitude
|
xue@7
|
174 fa, fb, fc, fd: trinomial coefficients of frequency
|
xue@7
|
175 p1: initial phase angle at 0 (NOT at CountSt)
|
xue@7
|
176 Out: f[CountSt:CountEn-1], a[:], ph[:], da[:]: output buffers.
|
xue@7
|
177 p1: phase angle at CountEn
|
xue@7
|
178
|
xue@7
|
179 No return value.
|
xue@7
|
180 */
|
xue@7
|
181 void Sinusoid_direct(double* f, double* a, double* ph, double* da, int CountSt, int CountEn, double aa, double ab, double ac, double ad,
|
xue@7
|
182 double fa, double fb, double fc, double fd, double &p1, bool LogA)
|
xue@7
|
183 {
|
xue@7
|
184 int i;
|
xue@7
|
185 if (LogA)
|
xue@7
|
186 {
|
xue@7
|
187 for (i=CountSt; i<CountEn; i++)
|
xue@7
|
188 {
|
xue@7
|
189 a[i]=exp(ad+i*(ac+i*(ab+i*aa)));
|
xue@7
|
190 f[i]=fd+i*(fc+i*(fb+i*fa));
|
xue@7
|
191 ph[i]=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@7
|
192 da[i]=a[i]*(ac+i*(2*ab+3*i*aa));
|
xue@7
|
193 }
|
xue@7
|
194 }
|
xue@7
|
195 else
|
xue@7
|
196 {
|
xue@7
|
197 for (i=CountSt; i<CountEn; i++)
|
xue@7
|
198 {
|
xue@7
|
199 a[i]=ad+i*(ac+i*(ab+i*aa));
|
xue@7
|
200 f[i]=fd+i*(fc+i*(fb+i*fa));
|
xue@7
|
201 ph[i]=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@7
|
202 da[i]=ac+i*(2*ab+3*i*aa);
|
xue@7
|
203 }
|
xue@7
|
204 }
|
xue@7
|
205 p1=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@7
|
206 }//Sinusoid
|
xue@7
|
207
|
xue@7
|
208 /**
|
xue@7
|
209 function Sinusoid_direct: synthesizes sinusoid over [CountSt, CountEn) from tronomial coefficients of
|
xue@7
|
210 frequency, direct implementation returning frequency and phase rather than waveform.
|
xue@7
|
211
|
xue@7
|
212 In: CountSt, CountEn
|
xue@7
|
213 fa, fb, fc, fd: trinomial coefficients of frequency
|
xue@7
|
214 p1: initial phase angle at 0 (NOT at CountSt)
|
xue@7
|
215 Out: f[CountSt:CountEn-1], ph[CountSt:CountEn-1]: output buffers.
|
xue@7
|
216 p1: phase angle at CountEn
|
xue@7
|
217
|
xue@7
|
218 No return value.
|
xue@7
|
219 */
|
xue@7
|
220 void Sinusoid_direct(double* f, double* ph, int CountSt, int CountEn, double fa, double fb, double fc,
|
xue@7
|
221 double fd, double &p1)
|
xue@7
|
222 {
|
xue@7
|
223 int i;
|
xue@7
|
224 for (i=CountSt; i<CountEn; i++)
|
xue@7
|
225 {
|
xue@7
|
226 f[i]=fd+i*(fc+i*(fb+i*fa));
|
xue@7
|
227 ph[i]=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@7
|
228 }
|
xue@7
|
229 p1=p1+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)));
|
xue@7
|
230 }//Sinusoid
|
xue@7
|
231
|
xue@7
|
232 /**
|
xue@1
|
233 function Sinusoid: synthesizes sinusoid over [CountSt, CountEn) from tronomial coefficients of
|
xue@1
|
234 amplitude and frequency, recursive implementation.
|
xue@1
|
235
|
xue@1
|
236 In: CountSt, CountEn
|
xue@1
|
237 a3, a2, a1, a0: trinomial coefficients of amplitude
|
xue@1
|
238 f3, f2, f1, f0: trinomial coefficients of frequency
|
xue@1
|
239 ph: initial phase angle at 0 (NOT at CountSt)
|
xue@1
|
240 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
241 Out: data[CountSt:CountEn-1]: output buffer.
|
xue@1
|
242 ph: phase angle at CountEn
|
xue@1
|
243
|
xue@1
|
244 No return value. This function requires 8-byte stack alignment for optimal speed.
|
xue@1
|
245 */
|
xue@1
|
246 void Sinusoid(double* data, int CountSt, int CountEn, double a3, double a2, double a1, double a0,
|
xue@1
|
247 double f3, double f2, double f1, double f0, double &ph, bool add)
|
xue@1
|
248 {
|
xue@1
|
249 int i;
|
xue@1
|
250 double a, da, dda, ddda, dph, ddph, dddph, ddddph,
|
xue@1
|
251 sph, cph, sdph, cdph, sddph, cddph, sdddph, cdddph, sddddph, cddddph,
|
xue@1
|
252 p0=ph, p1=2*M_PI*f0, p2=M_PI*f1, p3=2.0*M_PI*f2/3, p4=2.0*M_PI*f3/4, tmp;
|
xue@1
|
253 if (CountSt==0)
|
xue@1
|
254 {
|
xue@1
|
255 a=a0; da=a1+a2+a3; dda=2*a2+6*a3; ddda=6*a3;
|
xue@1
|
256 dph=p1+p2+p3+p4; ddph=2*p2+6*p3+14*p4; dddph=6*p3+36*p4; ddddph=24*p4;
|
xue@1
|
257 }
|
xue@1
|
258 else
|
xue@1
|
259 {
|
xue@1
|
260 a=a0+CountSt*(a1+CountSt*(a2+CountSt*a3));
|
xue@1
|
261 da=a1+a2+a3+CountSt*(2*a2+3*a3+CountSt*3*a3);
|
xue@1
|
262 dda=2*a2+6*a3+CountSt*6*a3; ddda=6*a3;
|
xue@1
|
263 ph=p0+CountSt*(p1+CountSt*(p2+CountSt*(p3+CountSt*p4)));
|
xue@1
|
264 dph=p1+p2+p3+p4+CountSt*(2*p2+3*p3+4*p4+CountSt*(3*p3+6*p4+CountSt*4*p4));
|
xue@1
|
265 ddph=2*p2+6*p3+14*p4+CountSt*(6*p3+24*p4+CountSt*12*p4);
|
xue@1
|
266 dddph=6*p3+36*p4+CountSt*24*p4; ddddph=24*p4;
|
xue@1
|
267 }
|
xue@1
|
268 sph=sin(ph), cph=cos(ph);
|
xue@1
|
269 sdph=sin(dph), cdph=cos(dph);
|
xue@1
|
270 sddph=sin(ddph), cddph=cos(ddph);
|
xue@1
|
271 sdddph=sin(dddph), cdddph=cos(dddph);
|
xue@1
|
272 sddddph=sin(ddddph), cddddph=cos(ddddph);
|
xue@1
|
273 if (add)
|
xue@1
|
274 {
|
xue@1
|
275 for (i=CountSt; i<CountEn; i++)
|
xue@1
|
276 {
|
xue@1
|
277 data[i]+=a*cph;
|
xue@1
|
278 a=a+da; da=da+dda; dda=dda+ddda;
|
xue@1
|
279 tmp=cph*cdph-sph*sdph; sph=sph*cdph+cph*sdph; cph=tmp;
|
xue@1
|
280 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@1
|
281 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@1
|
282 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@1
|
283 }
|
xue@1
|
284 }
|
xue@1
|
285 else
|
xue@1
|
286 {
|
xue@1
|
287 for (i=CountSt; i<CountEn; i++)
|
xue@1
|
288 {
|
xue@1
|
289 data[i]=a*cph;
|
xue@1
|
290 a=a+da; da=da+dda; dda=dda+ddda;
|
xue@1
|
291 tmp=cph*cdph-sph*sdph; sph=sph*cdph+cph*sdph; cph=tmp;
|
xue@1
|
292 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@1
|
293 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@1
|
294 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@1
|
295 }
|
xue@1
|
296 }
|
xue@1
|
297 ph=p0+CountEn*(p1+CountEn*(p2+CountEn*(p3+CountEn*p4)));
|
xue@1
|
298 }
|
xue@1
|
299
|
Chris@5
|
300 /**
|
xue@1
|
301 function SinusoidExp: synthesizes complex sinusoid whose derivative log amplitude and frequency are
|
xue@1
|
302 trinomials
|
xue@1
|
303
|
xue@1
|
304 In: CountSt, CountEn
|
xue@1
|
305 a3, a2, a1, a0: trinomial coefficients for the derivative of log amplitude
|
xue@1
|
306 omg3, omg2, omg1, omg0: trinomial coefficients for angular frequency
|
xue@1
|
307 ea, ph: initial log amplitude and phase angle at 0
|
xue@1
|
308 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
309 Out: data[CountSt:CountEn-1]: output buffer.
|
xue@1
|
310 ea, ph: log amplitude and phase angle at CountEn.
|
xue@1
|
311
|
xue@1
|
312 No return value.
|
xue@1
|
313 */
|
xue@1
|
314 void SinusoidExp(cdouble* data, int CountSt, int CountEn, double a3, double a2, double a1, double a0,
|
xue@1
|
315 double omg3, double omg2, double omg1, double omg0, double &ea, double &ph, bool add)
|
xue@1
|
316 {
|
xue@1
|
317 double e0=ea, e1=a0, e2=0.5*a1, e3=a2/3, e4=a3/4,
|
xue@1
|
318 p0=ph, p1=omg0, p2=0.5*omg1, p3=omg2/3, p4=omg3/4;
|
xue@1
|
319 if (add) for (int i=CountSt; i<CountEn; i++)
|
xue@1
|
320 {
|
xue@1
|
321 double lea=e0+i*(e1+i*(e2+i*(e3+i*e4)));
|
xue@1
|
322 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
323 data[i]+=exp(cdouble(lea, lph));
|
xue@1
|
324 }
|
xue@1
|
325 else for (int i=CountSt; i<CountEn; i++)
|
xue@1
|
326 {
|
xue@1
|
327 double lea=e0+i*(e1+i*(e2+i*(e3+i*e4)));
|
xue@1
|
328 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
329 data[i]=exp(cdouble(lea, lph));
|
xue@1
|
330 }
|
xue@1
|
331 ea=e0+CountEn*(e1+CountEn*(e2+CountEn*(e3+CountEn*e4)));
|
xue@1
|
332 ph=p0+CountEn*(p1+CountEn*(p2+CountEn*(p3+CountEn*p4)));
|
xue@1
|
333 }//SinusoidExp
|
xue@1
|
334
|
Chris@5
|
335 /**
|
xue@1
|
336 function SinusoidExp: synthesizes complex sinusoid piece whose derivative logarithm is h[M]'lamda[M].
|
xue@1
|
337 This version also synthesizes its derivative.
|
xue@1
|
338
|
xue@1
|
339 In: h[M][T], dih[M][T]: basis functions and their difference-integrals
|
xue@1
|
340 lamda[M]: coefficients of h[M]
|
xue@1
|
341 tmpexp: inital logarithm at 0
|
xue@1
|
342 Out: s[T], ds[T]: synthesized sinusoid and its derivative
|
xue@1
|
343 tmpexp: logarithm at T
|
xue@1
|
344
|
xue@1
|
345 No return value.
|
xue@1
|
346 */
|
xue@1
|
347 void SinusoidExp(int T, cdouble* s, cdouble* ds, int M, cdouble* lamda, double** h, double** dih, cdouble& tmpexp)
|
xue@1
|
348 {
|
xue@1
|
349 for (int t=0; t<T; t++)
|
xue@1
|
350 {
|
xue@1
|
351 s[t]=exp(tmpexp);
|
xue@1
|
352 cdouble dexp=0, dR=0;
|
xue@1
|
353 for (int m=0; m<M; m++) dexp+=lamda[m]*dih[m][t], dR+=lamda[m]*h[m][t];
|
xue@1
|
354 tmpexp+=dexp;
|
xue@1
|
355 ds[t]=s[t]*dR;
|
xue@1
|
356 }
|
xue@1
|
357 }//SinusoidExp
|
xue@1
|
358
|
Chris@5
|
359 /**
|
xue@1
|
360 function SinusoidExp: synthesizes complex sinusoid piece whose derivative logarithm is h[M]'lamda[M].
|
xue@1
|
361 This version does not synthesize its derivative.
|
xue@1
|
362
|
xue@1
|
363 In: dih[M][T]: difference of integrals of basis functions h[M]
|
xue@1
|
364 lamda[M]: coefficients of h[M]
|
xue@1
|
365 tmpexp: inital logarithm at 0
|
xue@1
|
366 Out: s[T]: synthesized sinusoid
|
xue@1
|
367 tmpexp: logarithm at T
|
xue@1
|
368
|
xue@1
|
369 No return value.
|
xue@1
|
370 */
|
xue@1
|
371 void SinusoidExp(int T, cdouble* s, int M, cdouble* lamda, double** dih, cdouble& tmpexp)
|
xue@1
|
372 {
|
xue@1
|
373 for (int t=0; t<T; t++)
|
xue@1
|
374 {
|
xue@1
|
375 s[t]=exp(tmpexp);
|
xue@1
|
376 cdouble dexp=0;
|
xue@1
|
377 for (int m=0; m<M; m++) dexp+=lamda[m]*dih[m][t];
|
xue@1
|
378 tmpexp+=dexp;
|
xue@1
|
379 }
|
xue@1
|
380 }//SinusoidExp
|
xue@1
|
381
|
Chris@5
|
382 /**
|
xue@1
|
383 function SinusoidExpA: synthesizes complex sinusoid whose log amplitude and frequency are trinomials
|
xue@1
|
384
|
xue@1
|
385 In: CountSt, CountEn
|
xue@1
|
386 a3, a2, a1, a0: trinomial coefficients for log amplitude
|
xue@1
|
387 omg3, omg2, omg1, omg0: trinomial coefficients for angular frequency
|
xue@1
|
388 ph: initial phase angle at 0
|
xue@1
|
389 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
390 Out: data[CountSt:CountEn-1]: output buffer.
|
xue@1
|
391 ph: phase angle at CountEn.
|
xue@1
|
392
|
xue@1
|
393 No return value.
|
xue@1
|
394 */
|
xue@1
|
395 void SinusoidExpA(cdouble* data, int CountSt, int CountEn, double a3, double a2, double a1, double a0,
|
xue@1
|
396 double omg3, double omg2, double omg1, double omg0, double &ph, bool add)
|
xue@1
|
397 {
|
xue@1
|
398 double p0=ph, p1=omg0, p2=0.5*omg1, p3=omg2/3, p4=omg3/4;
|
xue@1
|
399 if (add) for (int i=CountSt; i<CountEn; i++)
|
xue@1
|
400 {
|
xue@1
|
401 double lea=a0+i*(a1+i*(a2+i*a3));
|
xue@1
|
402 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
403 data[i]+=exp(cdouble(lea, lph));
|
xue@1
|
404 }
|
xue@1
|
405 else for (int i=CountSt; i<CountEn; i++)
|
xue@1
|
406 {
|
xue@1
|
407 double lea=a0+i*(a1+i*(a2+i*a3));
|
xue@1
|
408 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
409 data[i]=exp(cdouble(lea, lph));
|
xue@1
|
410 }
|
xue@1
|
411 ph=p0+CountEn*(p1+CountEn*(p2+CountEn*(p3+CountEn*p4)));
|
xue@1
|
412 }//SinusoidExpA
|
xue@1
|
413
|
Chris@5
|
414 /**
|
xue@1
|
415 function SinusoidExpA: synthesizes complex sinusoid whose log amplitude and frequency are trinomials
|
xue@1
|
416 with phase angle specified at both ends.
|
xue@1
|
417
|
xue@7
|
418 In: T
|
xue@1
|
419 a3, a2, a1, a0: trinomial coefficients for log amplitude
|
xue@1
|
420 omg3, omg2, omg1, omg0: trinomial coefficients for angular frequency
|
xue@1
|
421 ph0, ph2: phase angles at 0 and CountEn.
|
xue@1
|
422 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@7
|
423 Out: data[T]: output buffer.
|
xue@1
|
424
|
xue@1
|
425 No return value.
|
xue@1
|
426 */
|
xue@7
|
427 void SinusoidExpA(int T, cdouble* data, double a3, double a2, double a1, double a0,
|
xue@1
|
428 double omg3, double omg2, double omg1, double omg0, double ph0, double ph2, bool add)
|
xue@1
|
429 {
|
xue@1
|
430 double p0=ph0, p1=omg0, p2=0.5*omg1, p3=omg2/3, p4=omg3/4;
|
xue@7
|
431 double pend=p0+T*(p1+T*(p2+T*(p3+T*p4)));
|
xue@1
|
432
|
xue@1
|
433 int k=floor((pend-ph2)/2/M_PI+0.5);
|
xue@1
|
434 double d=ph2-pend+2*M_PI*k;
|
xue@7
|
435 double _p=-2*d/T/T/T;
|
xue@7
|
436 double _q=3*d/T/T;
|
xue@1
|
437
|
xue@7
|
438 if (add) for (int i=0; i<T; i++)
|
xue@1
|
439 {
|
xue@1
|
440 double lea=a0+i*(a1+i*(a2+i*a3));
|
xue@1
|
441 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
442 data[i]+=exp(cdouble(lea, lph+(i*i*(_q+i*_p))));
|
xue@1
|
443 }
|
xue@7
|
444 else for (int i=0; i<T; i++)
|
xue@1
|
445 {
|
xue@1
|
446 double lea=a0+i*(a1+i*(a2+i*a3));
|
xue@1
|
447 double lph=p0+i*(p1+i*(p2+i*(p3+i*p4)));
|
xue@1
|
448 data[i]=exp(cdouble(lea, lph+(i*i*(_q+i*_p))));
|
xue@1
|
449 }
|
xue@1
|
450 }//SinusoidExpA
|
xue@1
|
451
|
Chris@5
|
452 /**
|
xue@1
|
453 function SinusoidExpA: synthesizes complex sinusoid piece whose log amplitude is h[M]'p[M] and
|
xue@1
|
454 frequency is h[M]'q[M]. This version also synthesizes its derivative.
|
xue@1
|
455
|
xue@1
|
456 In: h[M][T], dh[M][T], dih[M][T]: basis functions and their derivatives and difference-integrals
|
xue@1
|
457 p[M], q[M]: real and imaginary parts of coefficients of h[M]
|
xue@1
|
458 tmpph: inital phase angle at 0
|
xue@1
|
459 Out: s[T], ds[T]: synthesized sinusoid and its derivative
|
xue@1
|
460 tmpph: phase angle at T
|
xue@1
|
461
|
xue@1
|
462 No return value.
|
xue@1
|
463 */
|
xue@1
|
464 void SinusoidExpA(int T, cdouble* s, cdouble* ds, int M, double* p, double* q, double** h, double** dh, double** dih, double& tmpph)
|
xue@1
|
465 {
|
xue@1
|
466 for (int t=0; t<T; t++)
|
xue@1
|
467 {
|
xue@1
|
468 double e=0, dph=0, drr=0, dri=0;
|
xue@1
|
469 for (int m=0; m<M; m++) e+=p[m]*h[m][t], dph+=q[m]*dih[m][t], drr+=p[m]*dh[m][t], dri+=q[m]*h[m][t];
|
xue@1
|
470 s[t]=exp(cdouble(e, tmpph));
|
xue@1
|
471 ds[t]=s[t]*cdouble(drr, dri);
|
xue@1
|
472 tmpph+=dph;
|
xue@1
|
473 }
|
xue@1
|
474 }//SinusoidExpA
|
xue@1
|
475
|
Chris@5
|
476 /**
|
xue@1
|
477 function SinusoidExpA: synthesizes complex sinusoid piece whose log amplitude is h[M]'p[M] and
|
xue@1
|
478 frequency is h[M]'q[M]. This version does not synthesize its derivative.
|
xue@1
|
479
|
xue@1
|
480 In: h[M][T], dih[M][T]: basis functions and their difference-integrals
|
xue@1
|
481 p[M], q[M]: real and imaginary parts of coefficients of h[M]
|
xue@1
|
482 tmpph: inital phase angle at 0
|
xue@1
|
483 Out: s[T]: synthesized sinusoid
|
xue@1
|
484 tmpph: phase angle at T
|
xue@1
|
485
|
xue@1
|
486 No return value.
|
xue@1
|
487 */
|
xue@1
|
488 void SinusoidExpA(int T, cdouble* s, int M, double* p, double* q, double** h, double** dih, double& tmpph)
|
xue@1
|
489 {
|
xue@1
|
490 for (int t=0; t<T; t++)
|
xue@1
|
491 {
|
xue@1
|
492 double e=0, dph=0;
|
xue@1
|
493 for (int m=0; m<M; m++) e+=p[m]*h[m][t], dph+=q[m]*dih[m][t];
|
xue@1
|
494 s[t]=exp(cdouble(e, tmpph));
|
xue@1
|
495 tmpph+=dph;
|
xue@1
|
496 }
|
xue@1
|
497 }//SinusoidExpA
|
xue@1
|
498
|
Chris@5
|
499 /**
|
xue@1
|
500 function SinusoidExpA: synthesizes complex sinusoid piece whose log amplitude is h[M]'p[M] and
|
xue@1
|
501 frequency is h[M]'q[M] with phase angle specified at both ends. This version does not synthesize its
|
xue@1
|
502 derivative.
|
xue@1
|
503
|
xue@1
|
504 In: h[M][T], dih[M][T]: basis functions and their difference-integrals
|
xue@1
|
505 p[M], q[M]: real and imaginary parts of coefficients of h[M]
|
xue@1
|
506 ph1, ph2: phase angles at 0 and T.
|
xue@1
|
507 Out: s[T]: synthesized sinusoid
|
xue@1
|
508
|
xue@1
|
509 No return value.
|
xue@1
|
510 */
|
xue@1
|
511 void SinusoidExpA(int T, cdouble* s, int M, double* p, double* q, double** h, double** dih, double ph1, double ph2)
|
xue@1
|
512 {
|
xue@1
|
513 double pend=ph1;
|
xue@1
|
514 for (int t=0; t<T; t++)
|
xue@1
|
515 {
|
xue@1
|
516 double dph=0;
|
xue@1
|
517 for (int m=0; m<M; m++) dph+=q[m]*dih[m][t];
|
xue@1
|
518 pend+=dph;
|
xue@1
|
519 }
|
xue@1
|
520
|
xue@1
|
521 int k=floor((pend-ph2)/2/M_PI+0.5);
|
xue@1
|
522 double d=ph2-pend+2*M_PI*k;
|
xue@1
|
523 double _p=-2*d/T/T/T;
|
xue@1
|
524 double _q=3*d/T/T;
|
xue@1
|
525
|
xue@1
|
526 double ph=ph1;
|
xue@1
|
527 for (int t=0; t<T; t++)
|
xue@1
|
528 {
|
xue@1
|
529 double e=0, dph=0;
|
xue@1
|
530 for (int m=0; m<M; m++) e+=p[m]*h[m][t], dph+=q[m]*dih[m][t];
|
xue@1
|
531 if (e>300) e=300;
|
xue@1
|
532 if (e<-300) e=-300;
|
xue@1
|
533 s[t]=exp(cdouble(e, ph+(t*t*(_q+t*_p))));
|
xue@1
|
534 ph+=dph;
|
xue@1
|
535 }
|
xue@1
|
536 }//SinusoidExpA
|
xue@1
|
537
|
xue@1
|
538 /*
|
xue@1
|
539 //This is not used any longer as the recursion does not seem to help saving computation with all its overheads.
|
xue@1
|
540 void SinusoidExp(cdouble* data, int CountSt, int CountEn, double a3, double a2, double a1, double a0,
|
xue@1
|
541 double omg3, double omg2, double omg1, double omg0, double &ea, double &ph, bool add)
|
xue@1
|
542 {
|
xue@1
|
543 int i;
|
xue@1
|
544 double dea, ddea, dddea, ddddea,
|
xue@1
|
545 dph, ddph, dddph, ddddph,
|
xue@1
|
546 sph, cph, sdph, cdph, sddph, cddph, sdddph, cdddph, sddddph, cddddph,
|
xue@1
|
547 e0=ea, e1=a0, e2=0.5*a1, e3=a2/3, e4=a3/4,
|
xue@1
|
548 p0=ph, p1=omg0, p2=0.5*omg1, p3=omg2/3, p4=omg3/4, tmp;
|
xue@1
|
549 if (CountSt==0)
|
xue@1
|
550 {
|
xue@1
|
551 dea=e1+e2+e3+e4; ddea=2*e2+6*e3+14*e4; dddea=6*e3+36*e4; ddddea=24*e3;
|
xue@1
|
552 dph=p1+p2+p3+p4; ddph=2*p2+6*p3+14*p4; dddph=6*p3+36*p4; ddddph=24*p4;
|
xue@1
|
553 }
|
xue@1
|
554 else
|
xue@1
|
555 {
|
xue@1
|
556 ea=e0+CountSt*(e1+CountSt*(e2+CountSt*(e3+CountSt*e4)));
|
xue@1
|
557 dea=e1+e2+e3+e4+CountSt*(2*e2+3*e3+4*e4+CountSt*(3*e3+6*e4+CountSt*4*e4));
|
xue@1
|
558 ddea=2*e2+6*e3+14*e4+CountSt*(6*e3+24*e4+CountSt*12*e4);
|
xue@1
|
559 dddea=6*e3+36*e4+CountSt*24*e4; ddddea=24*e4;
|
xue@1
|
560 ph=p0+CountSt*(p1+CountSt*(p2+CountSt*(p3+CountSt*p4)));
|
xue@1
|
561 dph=p1+p2+p3+p4+CountSt*(2*p2+3*p3+4*p4+CountSt*(3*p3+6*p4+CountSt*4*p4));
|
xue@1
|
562 ddph=2*p2+6*p3+14*p4+CountSt*(6*p3+24*p4+CountSt*12*p4);
|
xue@1
|
563 dddph=6*p3+36*p4+CountSt*24*p4; ddddph=24*p4;
|
xue@1
|
564 }
|
xue@1
|
565 sph=sin(ph), cph=cos(ph);
|
xue@1
|
566 sdph=sin(dph), cdph=cos(dph);
|
xue@1
|
567 sddph=sin(ddph), cddph=cos(ddph);
|
xue@1
|
568 sdddph=sin(dddph), cdddph=cos(dddph);
|
xue@1
|
569 sddddph=sin(ddddph), cddddph=cos(ddddph);
|
xue@1
|
570 if (add)
|
xue@1
|
571 {
|
xue@1
|
572 for (i=CountSt; i<CountEn; i++)
|
xue@1
|
573 {
|
xue@1
|
574 data[i]+=exp(ea)*cdouble(cph, sph);
|
xue@1
|
575 ea=ea+dea; dea=dea+ddea; ddea=ddea+dddea; dddea+dddea+ddddea;
|
xue@1
|
576 tmp=cph*cdph-sph*sdph; sph=sph*cdph+cph*sdph; cph=tmp;
|
xue@1
|
577 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@1
|
578 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@1
|
579 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@1
|
580 }
|
xue@1
|
581 }
|
xue@1
|
582 else
|
xue@1
|
583 {
|
xue@1
|
584 for (i=CountSt; i<CountEn; i++)
|
xue@1
|
585 {
|
xue@1
|
586 data[i]=exp(ea)*cdouble(cph, sph);
|
xue@1
|
587 ea=ea+dea; dea=dea+ddea; ddea=ddea+dddea; dddea+dddea+ddddea;
|
xue@1
|
588 tmp=cph*cdph-sph*sdph; sph=sph*cdph+cph*sdph; cph=tmp;
|
xue@1
|
589 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@1
|
590 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@1
|
591 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@1
|
592 }
|
xue@1
|
593 }
|
xue@1
|
594 ea=e0+CountEn*(e1+CountEn*(e2+CountEn*(e3+CountEn*e4)));
|
xue@1
|
595 ph=p0+CountEn*(p1+CountEn*(p2+CountEn*(p3+CountEn*p4)));
|
xue@1
|
596 } //*/
|
xue@1
|
597
|
xue@1
|
598
|
Chris@5
|
599 /**
|
xue@1
|
600 function Sinusoids: recursive harmonic multi-sinusoid generator
|
xue@1
|
601
|
xue@1
|
602 In: st, en
|
xue@1
|
603 M: number of partials
|
xue@1
|
604 a3[M], a2[M], a1[M], a0[M]: trinomial coefficients for partial amplitudes
|
xue@1
|
605 f3, f2, f1, f0: trinomial coefficients for fundamental frequency
|
xue@1
|
606 ph[M]: partial phases at 0.
|
xue@1
|
607 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
608 Out: data[st:en-1]: output buffer.
|
xue@1
|
609 ph[M]: partial phases at en.
|
xue@1
|
610
|
xue@1
|
611 No return value.
|
xue@1
|
612 */
|
xue@1
|
613 void Sinusoids(int M, double* data, int st, int en, double* a3, double* a2, double* a1, double* a0, double f3, double f2, double f1, double f0, double* ph, bool add)
|
xue@1
|
614 {
|
xue@1
|
615 double dph, ddph, dddph, ddddph;
|
xue@1
|
616 double sdph, cdph, cdph2, sddph, cddph, sdddph, cdddph, sddddph, cddddph, sdmph, cdmph, sdm_1ph, cdm_1ph;
|
xue@1
|
617 double p0, p1, p2, p3, p4, tmp, tmp2;
|
xue@1
|
618 double *a=(double*)malloc8(sizeof(double)*M*6), *da=&a[M], *dda=&a[M*2], *ddda=&a[M*3],
|
xue@1
|
619 *sph=&a[M*4], *cph=&a[M*5];
|
xue@1
|
620
|
xue@1
|
621 for (int m=0; m<M; m++)
|
xue@1
|
622 {
|
xue@1
|
623 p0=ph[m], p1=2*M_PI*f0, p2=M_PI*f1, p3=2.0*M_PI*f2/3, p4=2.0*M_PI*f3/4;
|
xue@1
|
624 if (st==0)
|
xue@1
|
625 {
|
xue@1
|
626 a[m]=a0[m]; da[m]=a1[m]+a2[m]+a3[m]; dda[m]=2*a2[m]+6*a3[m]; ddda[m]=6*a3[m];
|
xue@1
|
627 }
|
xue@1
|
628 else
|
xue@1
|
629 {
|
xue@1
|
630 a[m]=a0[m]+st*(a1[m]+st*(a2[m]+st*a3[m]));
|
xue@1
|
631 da[m]=a1[m]+a2[m]+a3[m]+st*(2*a2[m]+3*a3[m]+st*3*a3[m]);
|
xue@1
|
632 dda[m]=2*a2[m]+6*a3[m]+st*6*a3[m]; ddda[m]=6*a3[m];
|
xue@1
|
633 ph[m]=p0+st*(p1+st*(p2+st*(p3+st*p4)));
|
xue@1
|
634 }
|
xue@1
|
635 sph[m]=sin(ph[m]), cph[m]=cos(ph[m]);
|
xue@1
|
636 ph[m]=p0+(m+1)*en*(p1+en*(p2+en*(p3+en*p4)));
|
xue@1
|
637 }
|
xue@1
|
638
|
xue@1
|
639 if (st==0)
|
xue@1
|
640 {
|
xue@1
|
641 dph=p1+p2+p3+p4; ddph=2*p2+6*p3+14*p4; dddph=6*p3+36*p4; ddddph=24*p4;
|
xue@1
|
642 }
|
xue@1
|
643 else
|
xue@1
|
644 {
|
xue@1
|
645 dph=p1+p2+p3+p4+st*(2*p2+3*p3+4*p4+st*(3*p3+6*p4+st*4*p4));
|
xue@1
|
646 ddph=2*p2+6*p3+14*p4+st*(6*p3+24*p4+st*12*p4);
|
xue@1
|
647 dddph=6*p3+36*p4+st*24*p4; ddddph=24*p4;
|
xue@1
|
648 }
|
xue@1
|
649 sdph=sin(dph), cdph=cos(dph);
|
xue@1
|
650 sddph=sin(ddph), cddph=cos(ddph);
|
xue@1
|
651 sdddph=sin(dddph), cdddph=cos(dddph);
|
xue@1
|
652 sddddph=sin(ddddph), cddddph=cos(ddddph);
|
xue@1
|
653
|
xue@1
|
654 if (add)
|
xue@1
|
655 {
|
xue@1
|
656 for (int i=st; i<en; i++)
|
xue@1
|
657 {
|
xue@1
|
658 data[i]+=a[0]*cph[0]; a[0]+=da[0]; da[0]+=dda[0]; dda[0]+=ddda[0];
|
xue@1
|
659 tmp=cph[0]*cdph-sph[0]*sdph; sph[0]=sph[0]*cdph+cph[0]*sdph; cph[0]=tmp;
|
xue@1
|
660 cdm_1ph=1, sdm_1ph=0, cdmph=cdph, sdmph=sdph, cdph2=2*cdph;
|
xue@1
|
661
|
xue@1
|
662 for (int m=1; m<M; m++)
|
xue@1
|
663 {
|
xue@1
|
664 data[i]+=a[m]*cph[m]; a[m]+=da[m]; da[m]+=dda[m]; dda[m]+=ddda[m];
|
xue@1
|
665 // asm{mov ecx,m} asm{mov eax,a} asm{fld qword ptr [eax+ecx*8]} asm{mov edx,cph} asm{fld qword ptr [edx+ecx*8]} asm{fmul st(0),st(1)} asm{mov edx,data} asm{mov ebx,i} asm{fadd qword ptr [edx+ebx*8]} asm{fstp qword ptr [edx+ebx*8]} asm{mov edx,da} asm{fld qword ptr [edx+ecx*8]} asm{fadd st(1),st(0)} asm{mov ebx,dda} asm{fld qword ptr [ebx+ecx*8]} asm{fadd st(1),st(0)} asm{mov edi,ddda} asm{fadd qword ptr [edi+ecx*8]} asm{fstp qword ptr [ebx+ecx*8]} asm{fstp qword ptr [edx+ecx*8]} asm{fstp qword ptr [eax+ecx*8]}
|
xue@1
|
666 tmp=cdmph, tmp2=sdmph;
|
xue@1
|
667 cdmph=cdmph*cdph2-cdm_1ph; sdmph=sdmph*cdph2-sdm_1ph;
|
xue@1
|
668 cdm_1ph=tmp, sdm_1ph=tmp2;
|
xue@1
|
669
|
xue@1
|
670 tmp=cph[m]*cdmph-sph[m]*sdmph; sph[m]=sph[m]*cdmph+cph[m]*sdmph; cph[m]=tmp;
|
xue@1
|
671 // asm{mov ecx,m} asm{mov eax,cph} asm{fld qword ptr [eax+ecx*8]} asm{mov edx,sph} asm{fld qword ptr [edx+ecx*8]} asm{fld st(1)} asm{fmul sdmph} asm{fld st(1)} asm{fmul sdmph} asm{fld cdmph} asm{fmul st(4),st(0)} asm{fmulp st(3),st(0)} asm{fsubp st(3),st(0)} asm{faddp} asm{fstp qword ptr [edx+ecx*8]} asm{fstp qword ptr [eax+ecx*8]}
|
xue@1
|
672 }
|
xue@1
|
673
|
xue@1
|
674 tmp=cdph*cddph-sdph*sddph; sdph=sdph*cddph+cdph*sddph; cdph=tmp;
|
xue@1
|
675 tmp=cddph*cdddph-sddph*sdddph; sddph=sddph*cdddph+cddph*sdddph; cddph=tmp;
|
xue@1
|
676 tmp=cdddph*cddddph-sdddph*sddddph; sdddph=sdddph*cddddph+cdddph*sddddph; cdddph=tmp;
|
xue@1
|
677 }
|
xue@1
|
678 }
|
xue@1
|
679 else
|
xue@1
|
680 {
|
xue@1
|
681 }
|
xue@1
|
682 free8(a);
|
xue@1
|
683 }//Sinusoids*/
|
xue@1
|
684
|
Chris@5
|
685 /**
|
xue@1
|
686 function Sinusoid: synthesizes sinusoid piece from trinomial frequency and amplitude coefficients.
|
xue@1
|
687
|
xue@7
|
688 In: T
|
xue@1
|
689 aa, ab, ac, ad: trinomial coefficients of amplitude.
|
xue@1
|
690 fa, fb, fc, fd: trinomial coefficients of frequency.
|
xue@1
|
691 ph0, ph2: phase angles at 0 and CountEn.
|
xue@1
|
692 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@7
|
693 Out: data[T]: output buffer.
|
xue@1
|
694
|
xue@1
|
695 No return value.
|
xue@1
|
696 */
|
xue@7
|
697 void Sinusoid(int T, double* data, double aa, double ab, double ac, double ad,
|
xue@1
|
698 double fa, double fb, double fc, double fd, double ph0, double ph2, bool add)
|
xue@1
|
699 {
|
xue@7
|
700 double pend=ph0+2*M_PI*T*(fd+T*(fc/2+T*(fb/3+T*fa/4)));
|
xue@1
|
701 int k=floor((pend-ph2)/2/M_PI+0.5);
|
xue@1
|
702 double d=ph2-pend+2*M_PI*k;
|
xue@7
|
703 double p=-2*d/T/T/T;
|
xue@7
|
704 double q=3*d/T/T, a, ph;
|
xue@7
|
705 for (int i=0; i<T; i++)
|
xue@1
|
706 {
|
xue@1
|
707 a=ad+i*(ac+i*(ab+i*aa)); if (a<0) a=0;
|
xue@1
|
708 ph=ph0+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)))+i*i*(q+i*p);
|
xue@1
|
709 if (add) data[i]+=a*cos(ph);
|
xue@1
|
710 else data[i]=a*cos(ph);
|
xue@1
|
711 }
|
xue@1
|
712 }//Sinusoid
|
xue@1
|
713
|
Chris@5
|
714 /**
|
xue@1
|
715 function Sinusoid: synthesizes sinusoid piece from trinomial frequency and amplitude coefficients,
|
xue@1
|
716 returning sinusoid coefficients instead of waveform.
|
xue@1
|
717
|
xue@7
|
718 In: T
|
xue@1
|
719 aa, ab, ac, ad: trinomial coefficients of amplitude (or log amplitude if LogA=true)
|
xue@1
|
720 fa, fb, fc, fd: trinomial coefficients of frequency.
|
xue@1
|
721 ph0, ph2: phase angles at 0 and CountEn.
|
xue@1
|
722 LogA: specifies whether log amplitude or amplitude is a trinomial
|
xue@1
|
723 Out: f[CountSt:CountEn-1], a[CountSt:CountEn-1], ph[CountSt:CountEn-1]: synthesized sinusoid parameters
|
xue@1
|
724 da[CountSt:CountEn-1]: derivative of synthesized amplitude, optional
|
xue@1
|
725
|
xue@1
|
726 No return value.
|
xue@1
|
727 */
|
xue@7
|
728 void Sinusoid(int T, double* f, double* a, double* ph, double* da, double aa, double ab,
|
xue@1
|
729 double ac, double ad, double fa, double fb, double fc, double fd, double ph0, double ph2, bool LogA)
|
xue@1
|
730 {
|
xue@7
|
731 double pend=ph0+2*M_PI*T*(fd+T*(fc/2+T*(fb/3+T*fa/4)));
|
xue@1
|
732 int k=floor((pend-ph2)/2/M_PI+0.5);
|
xue@1
|
733 double d=ph2-pend+2*M_PI*k;
|
xue@7
|
734 double p=-2*d/T/T/T;
|
xue@7
|
735 double q=3*d/T/T;
|
xue@7
|
736 if (LogA) for (int i=0; i<T; i++)
|
xue@1
|
737 {
|
xue@1
|
738 a[i]=exp(ad+i*(ac+i*(ab+i*aa)));
|
xue@1
|
739 if (da) da[i]=a[i]*(ac+i*(2*ab+i*3*aa));
|
xue@1
|
740 f[i]=fd+i*(fc+i*(fb+i*fa))+i*(2*q+3*i*p)/(2*M_PI);
|
xue@1
|
741 ph[i]=ph0+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)))+i*i*(q+i*p);
|
xue@1
|
742 }
|
xue@7
|
743 else for (int i=0; i<T; i++)
|
xue@1
|
744 {
|
xue@1
|
745 a[i]=ad+i*(ac+i*(ab+i*aa));
|
xue@1
|
746 if (da) da[i]=ac+i*(2*ab+i*3*aa);
|
xue@1
|
747 f[i]=fd+i*(fc+i*(fb+i*fa))+i*(2*q+3*i*p)/(2*M_PI);
|
xue@1
|
748 ph[i]=ph0+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)))+i*i*(q+i*p);
|
xue@1
|
749 }
|
xue@1
|
750 }//Sinusoid
|
xue@1
|
751
|
Chris@5
|
752 /**
|
xue@1
|
753 function Sinusoid: generates trinomial frequency and phase with phase correction.
|
xue@1
|
754
|
xue@7
|
755 In: T
|
xue@1
|
756 fa, fb, fc, fd: trinomial coefficients of frequency.
|
xue@1
|
757 ph0, ph2: phase angles at 0 and CountEn.
|
xue@7
|
758 Out: f[T], ph[T]: output buffers holding frequency and phase.
|
xue@1
|
759
|
xue@1
|
760 No return value.
|
xue@1
|
761 */
|
xue@7
|
762 void Sinusoid(int T, double* f, double* ph, double fa, double fb,
|
xue@1
|
763 double fc, double fd, double ph0, double ph2)
|
xue@1
|
764 {
|
xue@7
|
765 double pend=ph0+2*M_PI*T*(fd+T*(fc/2+T*(fb/3+T*fa/4)));
|
xue@1
|
766 int k=floor((pend-ph2)/2/M_PI+0.5);
|
xue@1
|
767 double d=ph2-pend+2*M_PI*k;
|
xue@7
|
768 double p=-2*d/T/T/T;
|
xue@7
|
769 double q=3*d/T/T;
|
xue@7
|
770 for (int i=0; i<T; i++)
|
xue@1
|
771 {
|
xue@1
|
772 f[i]=fd+i*(fc+i*(fb+i*fa))+i*(2*q+3*i*p)/(2*M_PI);
|
xue@1
|
773 ph[i]=ph0+2*M_PI*i*(fd+i*((fc/2)+i*((fb/3)+i*fa/4)))+i*i*(q+i*p);
|
xue@1
|
774 }
|
xue@1
|
775 }//Sinusoid
|
xue@1
|
776
|
Chris@5
|
777 /**
|
xue@1
|
778 function SynthesizeSinusoid: synthesizes a time-varying sinusoid from a sequence of frequencies and amplitudes
|
xue@1
|
779
|
xue@1
|
780 In: xs[Fr]: measurement points, should be integers although *xs has double type.
|
xue@1
|
781 fs[Fr], as[Fr]: sequence of frequencies and amplitudes at xs[Fr]
|
xue@1
|
782 phs[0]: initial phase angle at (int)xs[0].
|
xue@1
|
783 dst, den: start and end time of synthesis, dst<=xs[0], den>=xs[Fr-1]
|
xue@1
|
784 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output buffer
|
xue@1
|
785 Out: xrec[0:den-dst-1]: output buffer hosting synthesized sinusoid from dst to den.
|
xue@1
|
786 phs[Fr]: phase angles at xs[Fr]
|
xue@1
|
787
|
xue@1
|
788 Returns pointer to xrec.
|
xue@1
|
789 */
|
xue@1
|
790 double* SynthesizeSinusoid(double* xrec, int dst, int den, double* phs, int Fr, double* xs, double* fs, double* as, bool add, bool* terminatetag)
|
xue@1
|
791 {
|
xue@1
|
792 double *f3=new double[Fr*8], *f2=&f3[Fr], *f1=&f3[Fr*2], *f0=&f3[Fr*3],
|
xue@1
|
793 *a3=&f3[Fr*4], *a2=&a3[Fr], *a1=&a3[Fr*2], *a0=&a3[Fr*3];
|
xue@1
|
794 CubicSpline(Fr-1, f3, f2, f1, f0, xs, fs, 1, 1);
|
xue@1
|
795 CubicSpline(Fr-1, a3, a2, a1, a0, xs, as, 1, 1);
|
xue@1
|
796 double ph=phs[0];
|
xue@1
|
797 for (int fr=0; fr<Fr-1; fr++)
|
xue@1
|
798 {
|
xue@1
|
799 phs[fr]=ph;
|
xue@1
|
800 ALIGN8(Sinusoid(&xrec[(int)xs[fr]-dst], 0, xs[fr+1]-xs[fr], a3[fr], a2[fr], a1[fr], a0[fr], f3[fr], f2[fr], f1[fr], f0[fr], ph, add);)
|
xue@1
|
801 if (terminatetag && *terminatetag) {delete[] f3; return 0;}
|
xue@1
|
802 }
|
xue@11
|
803 phs[Fr-1]=ph; ph=phs[Fr-2];
|
xue@1
|
804 ALIGN8(Sinusoid(&xrec[(int)xs[Fr-2]-dst], xs[Fr-1]-xs[Fr-2], den-xs[Fr-2], a3[Fr-2], a2[Fr-2], a1[Fr-2], a0[Fr-2], f3[Fr-2], f2[Fr-2], f1[Fr-2], f0[Fr-2], ph, add);
|
xue@1
|
805 Sinusoid(&xrec[(int)xs[0]-dst], dst-xs[0], 0, a3[0], a2[0], a1[0], a0[0], f3[0], f2[0], f1[0], f0[0], phs[0], add);)
|
xue@1
|
806 delete[] f3;
|
xue@1
|
807 return xrec;
|
xue@1
|
808 }//SynthesizeSinusoid
|
xue@1
|
809
|
Chris@5
|
810 /**
|
xue@1
|
811 function ShiftTrinomial: shifts the origin of a trinomial from 0 to T
|
xue@1
|
812
|
xue@1
|
813 In: a3, a2, a1, a0.
|
xue@1
|
814 Out: b3, b2, b1, b0, so that a3*x^3+a2*x^2+a1*x+a0=b3(x-T)^3+b2(x-T)^2+b1(x-T)+b0
|
xue@1
|
815
|
xue@1
|
816 No return value.
|
xue@1
|
817 */
|
xue@1
|
818 void ShiftTrinomial(double T, double& b3, double& b2, double& b1, double& b0, double a3, double a2, double a1, double a0)
|
xue@1
|
819 {
|
xue@1
|
820 b3=a3;
|
xue@1
|
821 b2=a2+T*3*b3;
|
xue@1
|
822 b1=a1+T*(2*b2-T*3*b3);
|
xue@1
|
823 b0=a0+T*(b1-T*(b2-T*b3));
|
xue@1
|
824 }//ShiftTrinomial
|
xue@1
|
825
|
Chris@5
|
826 /**
|
xue@1
|
827 function SynthesizeSinusoidP: synthesizes a time-varying sinusoid from a sequence of frequencies,
|
xue@1
|
828 amplitudes and phase angles
|
xue@1
|
829
|
xue@1
|
830 In: xs[Fr]: measurement points, should be integers although *xs has double type.
|
xue@1
|
831 fs[Fr], as[Fr], phs[Fr]: sequence of frequencies, amplitudes and phase angles at xs[Fr]
|
xue@1
|
832 dst, den: start and end time of synthesis, dst<=xs[0], den>=xs[Fr-1]
|
xue@1
|
833 add: specifies if the resynthesized sinusoid is to be added to or to replace the content of output
|
xue@1
|
834 buffer
|
xue@1
|
835 Out: xrecm[0:den-dst-1]: output buffer hosting synthesized sinusoid from dst to den.
|
xue@1
|
836
|
xue@1
|
837 Returns pointer to xrecm.
|
xue@1
|
838 */
|
xue@1
|
839 double* SynthesizeSinusoidP(double* xrecm, int dst, int den, double* phs, int Fr, double* xs, double* fs, double* as, bool add)
|
xue@1
|
840 {
|
xue@1
|
841 double *f3=new double[Fr*8], *f2=&f3[Fr], *f1=&f3[Fr*2], *f0=&f3[Fr*3],
|
xue@1
|
842 *a3=&f3[Fr*4], *a2=&a3[Fr], *a1=&a3[Fr*2], *a0=&a3[Fr*3];
|
xue@1
|
843 CubicSpline(Fr-1, f3, f2, f1, f0, xs, fs, 1, 1);
|
xue@1
|
844 CubicSpline(Fr-1, a3, a2, a1, a0, xs, as, 1, 1);
|
xue@7
|
845 for (int fr=0; fr<Fr-1; fr++) Sinusoid(xs[fr+1]-xs[fr], &xrecm[(int)xs[fr]-dst], a3[fr], a2[fr], a1[fr], a0[fr], f3[fr], f2[fr], f1[fr], f0[fr], phs[fr], phs[fr+1], add);
|
xue@1
|
846 double tmpph=phs[0]; Sinusoid(&xrecm[(int)xs[0]-dst], dst-xs[0], 0, 0, 0, 0, a0[0], f3[0], f2[0], f1[0], f0[0], tmpph, add);
|
xue@1
|
847 //extend the trinomials on [xs[Fr-2], xs[Fr-1]) based at xs[Fr-2] to beyond xs[Fr-1] based at xs[Fr-1].
|
xue@1
|
848 tmpph=phs[Fr-1];
|
xue@1
|
849 ShiftTrinomial(xs[Fr-1]-xs[Fr-2], f3[Fr-1], f2[Fr-1], f1[Fr-1], f0[Fr-1], f3[Fr-2], f2[Fr-2], f1[Fr-2], f0[Fr-2]);
|
xue@1
|
850 ShiftTrinomial(xs[Fr-1]-xs[Fr-2], a3[Fr-1], a2[Fr-1], a1[Fr-1], a0[Fr-1], a3[Fr-2], a2[Fr-2], a1[Fr-2], a0[Fr-2]);
|
xue@1
|
851 Sinusoid(&xrecm[(int)xs[Fr-1]-dst], 0, den-xs[Fr-1], 0, 0, 0, a0[Fr-1], f3[Fr-1], f2[Fr-1], f1[Fr-1], f0[Fr-1], tmpph, add);
|
xue@1
|
852 delete[] f3;
|
xue@1
|
853 return xrecm;
|
xue@1
|
854 }//SynthesizeSinusoidP
|