xue@1
|
1 //---------------------------------------------------------------------------
|
xue@1
|
2
|
xue@1
|
3 #include <math.h>
|
Chris@2
|
4 #include <string.h>
|
xue@1
|
5 #include "vibrato.h"
|
xue@1
|
6 #include "arrayalloc.h"
|
xue@1
|
7 #include "fft.h"
|
xue@1
|
8 #include "hssf.h"
|
Chris@2
|
9 #include "matrix.h"
|
xue@1
|
10 #include "splines.h"
|
xue@1
|
11 #include "xcomplex.h"
|
Chris@5
|
12
|
Chris@5
|
13 /** \file vibrato.h */
|
Chris@5
|
14
|
xue@1
|
15 //---------------------------------------------------------------------------
|
xue@1
|
16 //method TVo::TVo: default constructor
|
xue@1
|
17 TVo::TVo()
|
xue@1
|
18 {
|
xue@1
|
19 memset(this, 0, sizeof(TVo));
|
xue@1
|
20 afres=8192;
|
xue@1
|
21 }//TVo
|
xue@1
|
22
|
xue@1
|
23 //method TVo::~TVo: default destructor
|
xue@1
|
24 TVo::~TVo()
|
xue@1
|
25 {
|
xue@1
|
26 free(peakfr);
|
xue@1
|
27 delete[] lp;
|
xue@1
|
28 delete[] F0;
|
xue@1
|
29 if (fxr) DeAlloc2(fxr);
|
xue@1
|
30 if (fres) DeAlloc2(fres);
|
xue@1
|
31 if (LogASp) DeAlloc2(LogASp);
|
xue@1
|
32 }//~TVo
|
xue@1
|
33
|
Chris@5
|
34 /**
|
xue@1
|
35 method TVo::AllocateL: allocates or reallocates storage space whose size depends on L. This uses an
|
xue@1
|
36 external L value for allocation and updates L itself.
|
xue@1
|
37 */
|
xue@1
|
38 void TVo::AllocateL(int AnL)
|
xue@1
|
39 {
|
xue@1
|
40 L=AnL;
|
xue@1
|
41 delete[] F0;
|
xue@1
|
42 F0=new double[(L+2)*4];
|
xue@1
|
43 F0C=&F0[L+2], F0D=&F0[(L+2)*2], A0C=&F0[(L+2)*3];
|
xue@1
|
44 }//AllocateL
|
xue@1
|
45
|
Chris@5
|
46 /**
|
xue@1
|
47 method TVo::AllocateP: allocates or reallocates storage space whose size depends on P, using the
|
xue@1
|
48 interal P.
|
xue@1
|
49 */
|
xue@1
|
50 void TVo::AllocateP()
|
xue@1
|
51 {
|
xue@1
|
52 peakfr=(int*)realloc(peakfr, sizeof(int)*P);
|
xue@1
|
53 delete[] lp; lp=new double[(P+2)*3];
|
xue@1
|
54 Dp=&lp[P+2];
|
xue@1
|
55 Kp=(int*)&lp[(P+2)*2];
|
xue@1
|
56 if (LogASp) DeAlloc2(LogASp); Allocate2(double, P, M, LogASp);
|
xue@1
|
57 }//AllocateP
|
xue@1
|
58
|
Chris@5
|
59 /**
|
xue@1
|
60 method TVo::AllocatePK: allocates or reallocates storage space whose size depends on both P and K.
|
xue@1
|
61 */
|
xue@1
|
62 void TVo::AllocatePK()
|
xue@1
|
63 {
|
xue@1
|
64 if (fxr) DeAlloc2(fxr);
|
xue@1
|
65 Allocate2(double, P, 2*K+1, fxr);
|
xue@1
|
66 memset(fxr[0], 0, sizeof(double)*P*(2*K+1));
|
xue@1
|
67 if (fres) DeAlloc2(fres);
|
xue@1
|
68 Allocate2(double, P, K, fres);
|
xue@1
|
69 }//AllocatePK
|
xue@1
|
70
|
Chris@5
|
71 /**
|
xue@1
|
72 method TVo::GetOldP: returns the number of "equivalent" cycles of the whole duration. Although P-1
|
xue@1
|
73 cycles are delineated by lp[P], the parts before lp[0] and after lp[P-1] are also a part of the
|
xue@1
|
74 harmonic sinusoid being modeled and therefore should be taken into account when necessary.
|
xue@1
|
75 */
|
xue@1
|
76 double TVo::GetOldP()
|
xue@1
|
77 {
|
xue@1
|
78 return P-1+lp[0]/(lp[1]-lp[0])+(L-lp[P-1])/(lp[P-1]-lp[P-2]);
|
xue@1
|
79 }//GetOldP
|
xue@1
|
80
|
Chris@5
|
81 /**
|
xue@1
|
82 methodTVo::LoadFromFileHandle: reads TVo object from a file stream.
|
xue@1
|
83 */
|
xue@1
|
84 void TVo::LoadFromFileHandle(FILE* file)
|
xue@1
|
85 {
|
xue@1
|
86 fread(&M, sizeof(int), 1, file);
|
xue@1
|
87 fread(&L, sizeof(int), 1, file);
|
xue@1
|
88 fread(&P, sizeof(int), 1, file);
|
xue@1
|
89 fread(&K, sizeof(int), 1, file);
|
xue@1
|
90 fread(&h, sizeof(double), 1, file);
|
xue@1
|
91 fread(&afres, sizeof(int), 1, file);
|
xue@1
|
92 AllocateL(L); AllocateP(); AllocatePK();
|
xue@1
|
93 fread(F0C, sizeof(double), L, file);
|
xue@1
|
94 fread(A0C, sizeof(double), L, file);
|
xue@1
|
95 fread(LogAF, sizeof(double), 4096, file);
|
xue@1
|
96 fread(peakfr, sizeof(int), P, file);
|
xue@1
|
97 fread(lp, sizeof(double), P, file);
|
xue@1
|
98 fread(Dp, sizeof(double), P, file);
|
xue@1
|
99 fread(Kp, sizeof(int), P, file);
|
xue@1
|
100 fread(fxr[0], sizeof(double), P*(2*K+1), file);
|
xue@1
|
101 fread(LogASp[0], sizeof(double), P*M, file);
|
xue@1
|
102 }//LoadFromFileHandle
|
xue@1
|
103
|
Chris@5
|
104 /**
|
xue@1
|
105 method TVo::ReAllocateL: reallocates storage space whose size depends on L, and transfer the contents.
|
xue@1
|
106 This uses an external L value for allocation but does not update L itself.
|
xue@1
|
107 */
|
xue@1
|
108 void TVo::ReAllocateL(int newL)
|
xue@1
|
109 {
|
xue@1
|
110 double* newF0=new double[(newL+2)*4];
|
xue@1
|
111 F0C=&newF0[newL+2], F0D=&newF0[(newL+2)*2], A0C=&newF0[(newL+2)*3];
|
xue@1
|
112 memcpy(A0C, &F0[(L+2)*3], sizeof(double)*(L+2));
|
xue@1
|
113 memcpy(F0D, &F0[(L+2)*2], sizeof(double)*(L+2));
|
xue@1
|
114 memcpy(F0C, &F0[L+2], sizeof(double)*(L+2));
|
xue@1
|
115 memcpy(newF0, F0, sizeof(double)*(L+2));
|
xue@1
|
116 delete[] F0;
|
xue@1
|
117 F0=newF0;
|
xue@1
|
118 }//ReAllocateL
|
xue@1
|
119
|
Chris@5
|
120 /**
|
xue@1
|
121 method TVo::SaveToFile: saves a TVo object to a file.
|
xue@1
|
122
|
xue@1
|
123 In: filename: path to the destination file.
|
xue@1
|
124 */
|
xue@1
|
125 void TVo::SaveToFile(char* filename)
|
xue@1
|
126 {
|
xue@1
|
127 FILE* file=fopen(filename, "wb");
|
xue@1
|
128 if (file)
|
xue@1
|
129 {
|
xue@1
|
130 SaveToFileHandle(file);
|
xue@1
|
131 fclose(file);
|
xue@1
|
132 }
|
xue@1
|
133 else
|
xue@1
|
134 {
|
xue@1
|
135 throw(strcat((char*)"Cannot open file ", filename));
|
xue@1
|
136 }
|
xue@1
|
137 }//SaveToFile
|
xue@1
|
138
|
Chris@5
|
139 /**
|
xue@1
|
140 method TVo::SaveToFileHandle: saves a TVo object to an open file stream.
|
xue@1
|
141 */
|
xue@1
|
142 void TVo::SaveToFileHandle(FILE* file)
|
xue@1
|
143 {
|
xue@1
|
144 fwrite(&M, sizeof(int), 1, file);
|
xue@1
|
145 fwrite(&L, sizeof(int), 1, file);
|
xue@1
|
146 fwrite(&P, sizeof(int), 1, file);
|
xue@1
|
147 fwrite(&K, sizeof(int), 1, file);
|
xue@1
|
148 fwrite(&h, sizeof(double), 1, file);
|
xue@1
|
149 fwrite(&afres, sizeof(int), 1, file);
|
xue@1
|
150 fwrite(F0C, sizeof(double), L, file);
|
xue@1
|
151 fwrite(A0C, sizeof(double), L, file);
|
xue@1
|
152 fwrite(LogAF, sizeof(double), 4096, file);
|
xue@1
|
153 fwrite(peakfr, sizeof(int), P, file);
|
xue@1
|
154 fwrite(lp, sizeof(double), P, file);
|
xue@1
|
155 fwrite(Dp, sizeof(double), P, file);
|
xue@1
|
156 fwrite(Kp, sizeof(int), P, file);
|
xue@1
|
157 fwrite(fxr[0], sizeof(double), P*(2*K+1), file);
|
xue@1
|
158 fwrite(LogASp[0], sizeof(double), P*M, file);
|
xue@1
|
159 }//SaveToFileHandle
|
xue@1
|
160
|
xue@1
|
161 //---------------------------------------------------------------------------
|
xue@1
|
162 //functions
|
xue@1
|
163
|
xue@1
|
164
|
Chris@5
|
165 /**
|
xue@1
|
166 function AnalyzeV: calculates all basic and non-basic descriptors of a vibrato from a harmonic
|
xue@1
|
167 sinusoid
|
xue@1
|
168
|
xue@1
|
169 In: HS: harmonic sinusoid to compute vibrato representation from
|
xue@1
|
170 sps: sampling rate
|
xue@1
|
171 h: hop size
|
xue@1
|
172 SFMode: specifies source-filter estimation criterion, 0=FB (filter bank), 1=SV (slow variation)
|
xue@1
|
173 SFF: filter response sampling interval
|
xue@1
|
174 SFScale: set if filter sampling uses mel scale
|
xue@1
|
175 SFtheta: balancing factor of amplitude and frequency variations, needed for SV approach
|
xue@1
|
176 Out: V: a TVo object hosting vibrato descriptors (vibrato representation) of HS
|
xue@1
|
177 cyclefrcount: number of cycles between cycle boundaries, equals V.P-1.
|
xue@1
|
178 cyclefrs[cyclefrcount], cyclefs[cyclefrcount]: time (in frames) and F0 centroid of cycles. These are
|
xue@1
|
179 knots from which V.F0C[] is interpolated.
|
xue@1
|
180 peaky[V.P]: shape score of cycle peaks
|
xue@1
|
181
|
xue@1
|
182 No return value.
|
xue@1
|
183 */
|
xue@1
|
184 void AnalyzeV(THS& HS, TVo& V, double*& peaky, double*& cyclefrs, double*& cyclefs, double sps, double h, int* cyclefrcount,
|
xue@1
|
185 int SFMode, double SFF, int SFFScale, double SFtheta)
|
xue@1
|
186 {
|
xue@1
|
187 int M=HS.M, Fr=HS.Fr;
|
xue@1
|
188 if (M<=0 || Fr<=0) return;
|
xue@1
|
189 atom** Partials=HS.Partials;
|
xue@1
|
190
|
xue@1
|
191 //basic descriptor: h
|
xue@1
|
192 V.h=h;
|
xue@1
|
193
|
xue@1
|
194 //demodulating pitch
|
xue@1
|
195 //Basic descriptor: L
|
xue@1
|
196 V.AllocateL(Fr);
|
xue@1
|
197
|
xue@1
|
198 double* AA=new double[Fr];
|
xue@1
|
199 //find the pitch track
|
xue@1
|
200 V.F0max=0, V.F0min=1;
|
xue@1
|
201 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
202 {
|
xue@1
|
203 double suma2=0, suma2p=0;
|
xue@1
|
204 for (int m=0; m<M; m++)
|
xue@1
|
205 {
|
xue@1
|
206 double a=Partials[m][fr].a, p=Partials[m][fr].f/(m+1);
|
xue@1
|
207 if (p<=0) break;
|
xue@1
|
208 suma2+=a*a, suma2p+=a*a*p;
|
xue@1
|
209 }
|
xue@1
|
210 V.F0[fr]=suma2p/suma2;
|
xue@1
|
211 if (V.F0max<V.F0[fr]) V.F0max=V.F0[fr];
|
xue@1
|
212 if (V.F0min>V.F0[fr]) V.F0min=V.F0[fr];
|
xue@1
|
213 AA[fr]=suma2;
|
xue@1
|
214 }
|
xue@1
|
215
|
xue@1
|
216 //Basic descriptor: M
|
xue@1
|
217 V.M=0.45/V.F0max;
|
xue@1
|
218 if (V.M>M) V.M=M;
|
xue@1
|
219
|
xue@1
|
220 //rough estimation of rate
|
xue@1
|
221 double* f0d=new double[Fr-1]; for (int i=0; i<Fr-1; i++) f0d[i]=V.F0[i+1]-V.F0[i];
|
xue@1
|
222 RateAndReg(V.rate, V.regularity, f0d, 0, Fr-2, 8, sps, h);
|
xue@1
|
223 delete[] f0d;
|
xue@1
|
224
|
xue@1
|
225 //find peaks of the pitch track
|
xue@1
|
226 free(V.peakfr); V.peakfr=(int*)malloc(sizeof(int)*Fr/2);
|
xue@1
|
227 double periodinframe=sps/(V.rate*h);
|
xue@1
|
228 FindPeaks(V.peakfr, V.P, V.F0, Fr, periodinframe, peaky);
|
xue@1
|
229 if (V.P>=1) //de-modulation
|
xue@1
|
230 {
|
xue@1
|
231 //Basic descriptor: F0C[]
|
xue@1
|
232 DeFM(V.F0C, V.F0, AA, V.P, V.peakfr, Fr, V.F0Overall, *cyclefrcount, cyclefrs, cyclefs, true);
|
xue@1
|
233 //Basic descriptor: A0C[]
|
xue@1
|
234 DeAM(V.A0C, AA, V.P, V.peakfr, Fr);
|
xue@1
|
235 }
|
xue@1
|
236
|
xue@1
|
237 V.F0Cmax=0; V.F0Dmax=-1; V.F0Cmin=1; V.F0Dmin=1;
|
xue@1
|
238 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
239 {
|
xue@1
|
240 if (V.F0Cmax<V.F0C[fr]) V.F0Cmax=V.F0C[fr];
|
xue@1
|
241 if (V.F0Cmin>V.F0C[fr]) V.F0Cmin=V.F0C[fr];
|
xue@1
|
242 V.F0D[fr]=V.F0[fr]-V.F0C[fr];
|
xue@1
|
243 }
|
xue@1
|
244
|
xue@1
|
245 V.D=0; int cyclestart=(V.P>=2)?V.peakfr[0]:0, cycleend=(V.P>=2)?V.peakfr[V.P-1]:Fr;
|
xue@1
|
246 for (int fr=cyclestart; fr<cycleend; fr++)
|
xue@1
|
247 {
|
xue@1
|
248 double lf0d=V.F0D[fr];
|
xue@1
|
249 if (V.F0Dmax<lf0d) V.F0Dmax=lf0d;
|
xue@1
|
250 if (V.F0Dmin>lf0d) V.F0Dmin=lf0d;
|
xue@1
|
251 V.D+=lf0d*lf0d;
|
xue@1
|
252 }
|
xue@1
|
253 V.D=sqrt(V.D/(cycleend-cyclestart));
|
xue@1
|
254 delete[] AA;
|
xue@1
|
255
|
xue@1
|
256 //Calculate rate and regularity
|
xue@1
|
257 //find the section used for calculating regularity and rate
|
xue@1
|
258 {
|
xue@1
|
259 int frst=0, fren=Fr-1;
|
xue@1
|
260 while (frst<fren && V.F0D[frst]*V.F0D[frst+1]>0) frst++;
|
xue@1
|
261 while (fren>frst && V.F0D[fren]*V.F0D[fren-1]>0) fren--;
|
xue@1
|
262
|
xue@1
|
263 RateAndReg(V.rate, V.regularity, V.F0D, frst, fren, 8, sps, h);
|
xue@1
|
264 }
|
xue@1
|
265
|
xue@1
|
266 //Basic descriptor: P
|
xue@1
|
267 //Basic descriptor: peakfr[]
|
xue@1
|
268 periodinframe=sps/(V.rate*h);
|
xue@1
|
269 FindPeaks(V.peakfr, V.P, V.F0D, Fr, periodinframe, peaky);
|
xue@1
|
270
|
xue@1
|
271 //Basic descriptor: lp[]
|
xue@1
|
272 V.AllocateP();
|
xue@1
|
273 for (int p=0; p<V.P; p++)
|
xue@1
|
274 {
|
xue@1
|
275 double startfr; QIE(&V.F0D[V.peakfr[p]], startfr); V.lp[p]=startfr+V.peakfr[p];
|
xue@1
|
276 }
|
xue@1
|
277
|
xue@1
|
278 //Basic descriptor: LogAF[]
|
xue@1
|
279 //Source-filter modeling
|
xue@1
|
280 if (SFMode==0)
|
xue@1
|
281 S_F(V.afres, V.LogAF, V.LogAS, Fr, M, Partials, V.A0C, V.lp, V.P, V.F0Overall);
|
xue@1
|
282 else
|
xue@1
|
283 S_F_SV(V.afres, V.LogAF, V.LogAS, Fr, M, Partials, V.A0C, V.lp, V.P, SFF, SFFScale, SFtheta, sps);
|
xue@1
|
284
|
xue@1
|
285
|
xue@1
|
286 //the alternative: find K only
|
xue@1
|
287 V.K=50;
|
xue@1
|
288 if (V.K>periodinframe/2) V.K=periodinframe/2;
|
xue@1
|
289
|
xue@1
|
290 //single-cycle analyses
|
xue@1
|
291 //Basic descriptor: Dp[]
|
xue@1
|
292 V.AllocatePK();
|
xue@1
|
293 for (int p=1; p<V.P; p++)
|
xue@1
|
294 {
|
xue@1
|
295 //int frst=ceil(V.lp[p-1]), freninc=floor(V.lp[p]);
|
xue@1
|
296 int frst=V.peakfr[p-1], freninc=V.peakfr[p];
|
xue@1
|
297 V.Dp[p]=0; for (int fr=frst; fr<=freninc; fr++) V.Dp[p]+=V.F0D[fr]*V.F0D[fr]; V.Dp[p]=sqrt(V.Dp[p]/(freninc-frst+1));
|
xue@1
|
298 double* f0e=new double[freninc-frst+1];
|
xue@1
|
299 for (int fr=0; fr<=freninc-frst; fr++) f0e[fr]=V.F0D[frst+fr]/V.Dp[p];
|
xue@1
|
300 V.Kp[p]=V.K; FS_QR(V.Kp[p], V.fxr[p], &f0e[0], freninc-frst, V.lp[p]-V.lp[p-1], V.lp[p-1]-frst, V.fres[p]);
|
xue@1
|
301 delete[] f0e;
|
xue@1
|
302
|
xue@1
|
303 memset(V.LogASp[p], 0, sizeof(double)*V.M);
|
xue@1
|
304 for (int m=0; m<V.M; m++)
|
xue@1
|
305 {
|
xue@1
|
306 int ccount=0;
|
xue@1
|
307 for (int fr=frst; fr<=freninc; fr++)
|
xue@1
|
308 {
|
xue@1
|
309 double f=Partials[m][fr].f*V.afres;
|
xue@1
|
310 if (f<=0) continue;
|
xue@1
|
311 int intf=floor(f);
|
xue@1
|
312 V.LogASp[p][m]=V.LogASp[p][m]+log(Partials[m][fr].a/V.A0C[fr])-(V.LogAF[intf]*(intf+1-f)+V.LogAF[intf+1]*(f-intf));
|
xue@1
|
313 ccount++;
|
xue@1
|
314 }
|
xue@1
|
315 if (ccount>0) V.LogASp[p][m]/=ccount;
|
xue@1
|
316 else V.LogASp[p][m]=0;
|
xue@1
|
317 }
|
xue@1
|
318 }
|
xue@1
|
319 memset(V.FXR, 0, sizeof(double)*2*V.K); memset(V.FRes, 0, sizeof(double)*V.K);
|
xue@1
|
320 double sumdp=0; for (int p=1; p<V.P; p++) sumdp+=V.Dp[p], V.FXR[0]+=V.fxr[p][0]*V.Dp[p], V.FRes[0]+=V.fres[p][0]*V.Dp[p]; V.FXR[0]/=sumdp, V.FRes[0]/=sumdp;
|
xue@1
|
321 for (int k=1; k<V.K; k++)
|
xue@1
|
322 {
|
xue@1
|
323 double sumdp=0;
|
xue@1
|
324 for (int p=1; p<V.P; p++)
|
xue@1
|
325 {
|
xue@1
|
326 if (k<V.Kp[p])
|
xue@1
|
327 {
|
xue@1
|
328 V.FXR[2*k-1]+=V.fxr[p][2*k-1]*V.Dp[p];
|
xue@1
|
329 V.FXR[2*k]+=V.fxr[p][2*k]*V.Dp[p];
|
xue@1
|
330 V.FRes[k]+=V.fres[p][k]*V.Dp[p];
|
xue@1
|
331 sumdp+=V.Dp[p];
|
xue@1
|
332 }
|
xue@1
|
333 }
|
xue@1
|
334 V.FXR[2*k-1]/=sumdp, V.FXR[2*k]/=sumdp, V.FRes[k]/=sumdp;
|
xue@1
|
335 }
|
xue@1
|
336 }//AnalyzeV
|
xue@1
|
337
|
Chris@5
|
338 /**
|
xue@1
|
339 function copeak: measures the similarity of F0 between frst and fren to a cosine cycle 0~2pi.
|
xue@1
|
340
|
xue@1
|
341 In: F0[peakfr[frst]:peakfr[fren]]
|
xue@1
|
342 periodinframe: period of the cosine reference, in frames
|
xue@1
|
343
|
xue@1
|
344 Returns the correlation coefficient.
|
xue@1
|
345 */
|
xue@1
|
346 double copeak(double* F0, int* peakfr, int frst, int fren, double periodinframe)
|
xue@1
|
347 {
|
xue@1
|
348 double ef0=0, rfs=0, rff=0, rss=0; int frcount=0;
|
xue@1
|
349 for (int fr=peakfr[frst]; fr<=peakfr[fren]; fr++) ef0+=F0[fr], frcount++; ef0/=frcount;
|
xue@1
|
350 for (int fr=peakfr[frst]; fr<=peakfr[fren]; fr++)
|
xue@1
|
351 {
|
xue@1
|
352 double s=cos(2*M_PI*(fr-peakfr[frst])/periodinframe), f=F0[fr];
|
xue@1
|
353 rfs+=(f-ef0)*s; rff+=(f-ef0)*(f-ef0); rss+=s*s;
|
xue@1
|
354 }
|
xue@1
|
355 return rfs/sqrt(rff*rss);
|
xue@1
|
356 }//copeak
|
xue@1
|
357
|
Chris@5
|
358 /**
|
xue@1
|
359 function CorrectFS: time-shifts Fourier series so that maximum is reached at 0. This is done by
|
xue@1
|
360 finding the actual peak numerically then shifting it to 0.
|
xue@1
|
361
|
xue@1
|
362 In: c[2K-1]: Fourier series coefficients, in the order of 0r, 1i, 1r, 2i, 2r, ..., so that the series
|
xue@1
|
363 is expanded as c[0]+c[1]sinx+c[2]cosx+c[3]sin2x+c[4]cos2x+...c[2K-2]cos(K-1)x
|
xue@1
|
364 epx: a small positive value for convergence test for finding the peak
|
xue@1
|
365 maxiter: maximal number of iterates for finding the peak
|
xue@1
|
366 Out: c[2K-1]: updated Fourier series coefficients.
|
xue@1
|
367
|
xue@1
|
368 No return value.
|
xue@1
|
369 */
|
xue@1
|
370 void CorrectFS(int K, double* c, double epx=1e-8, int maxiter=10)
|
xue@1
|
371 {
|
xue@1
|
372 double y=0, kb=0, kka=0, th2pi=0, dth2pi=0, my, mth2pi;
|
xue@1
|
373 epx=2*M_PI*epx;
|
xue@1
|
374 int iter=0;
|
xue@1
|
375 for (int k=1; k<K; k++) y+=c[2*k], kb+=k*c[2*k-1], kka+=k*k*c[2*k]; my=y;
|
xue@1
|
376 dth2pi=(kka>0)?(kb/kka):(kb*0.1);
|
xue@1
|
377 while (iter<maxiter && fabs(dth2pi)>epx)
|
xue@1
|
378 {
|
xue@1
|
379 iter++;
|
xue@1
|
380 th2pi+=dth2pi;
|
xue@1
|
381 kb=kka=y=0;
|
xue@1
|
382 for (int k=1; k<K; k++)
|
xue@1
|
383 {
|
xue@1
|
384 double cc=cos(k*th2pi), ss=sin(k*th2pi);
|
xue@1
|
385 y+=(c[2*k]*cc+c[2*k-1]*ss);
|
xue@1
|
386 kb+=k*(-c[2*k]*ss+c[2*k-1]*cc);
|
xue@1
|
387 kka+=k*k*(c[2*k]*cc+c[2*k-1]*ss);
|
xue@1
|
388 }
|
xue@1
|
389 if (y>my) my=y, mth2pi=th2pi;
|
xue@1
|
390 dth2pi=(kka>0)?(kb/kka):(kb*0.1);
|
xue@1
|
391 }
|
xue@1
|
392 if (iter>=maxiter || th2pi!=mth2pi)
|
xue@1
|
393 {
|
xue@1
|
394 th2pi=mth2pi;
|
xue@1
|
395 }
|
xue@1
|
396 for (int k=1; k<K; k++)
|
xue@1
|
397 {
|
xue@1
|
398 double cc=cos(k*th2pi), ss=sin(k*th2pi);
|
xue@1
|
399 double tmp=c[2*k]*cc+c[2*k-1]*ss;
|
xue@1
|
400 c[2*k-1]=-c[2*k]*ss+c[2*k-1]*cc; c[2*k]=tmp;
|
xue@1
|
401 }
|
xue@1
|
402 }//CorrectFS
|
xue@1
|
403
|
Chris@5
|
404 /**
|
xue@1
|
405 function DeAM: amplitude demodulation based on given segmentation into cycles
|
xue@1
|
406
|
xue@1
|
407 In: A1[Fr]: original amplitude
|
xue@1
|
408 peakfr[npfr]: cycle boundaries (literally, "frame indices of frequency modulation peaks")
|
xue@1
|
409 Out: A2[Fr]: demodulated amplitude
|
xue@1
|
410
|
xue@1
|
411 No return value.
|
xue@1
|
412 */
|
xue@1
|
413 void DeAM(double* A2, double* A1, int npfr, int* peakfr, int Fr)
|
xue@1
|
414 {
|
xue@1
|
415 if (npfr==1) {memcpy(A2, A1, sizeof(double)*Fr); return;}
|
xue@1
|
416 double *frs=new double[npfr*2], *a=&frs[npfr];
|
xue@1
|
417 for (int i=0; i<npfr-1; i++)
|
xue@1
|
418 {
|
xue@1
|
419 int frst=peakfr[i], fren=peakfr[i+1];
|
xue@1
|
420 a[i]=(A1[frst]+A1[fren])*0.5;
|
xue@1
|
421 frs[i]=(frst*A1[frst]+fren*A1[fren])*0.5;
|
xue@1
|
422 for (int fr=frst+1; fr<fren; fr++) a[i]+=A1[fr], frs[i]+=fr*A1[fr];
|
xue@1
|
423 frs[i]/=a[i]; a[i]=log(sqrt(a[i]/(fren-frst)));
|
xue@1
|
424 }
|
xue@1
|
425 if (npfr==2)
|
xue@1
|
426 {
|
xue@1
|
427 A2[0]=exp(a[0]);
|
xue@1
|
428 for (int fr=1; fr<Fr; fr++) A2[fr]=A2[0];
|
xue@1
|
429 }
|
xue@1
|
430 else if (npfr==3)
|
xue@1
|
431 {
|
xue@1
|
432 double alp=(a[1]-a[0])/(frs[1]-frs[0]);
|
xue@1
|
433 for (int fr=0; fr<Fr; fr++) A2[fr]=exp(a[0]+(fr-frs[0])*alp);
|
xue@1
|
434 }
|
xue@1
|
435 else if (npfr==4)
|
xue@1
|
436 {
|
xue@1
|
437 double x0=frs[0], x1=frs[1], x2=frs[2], y0=log(a[0]), y1=log(a[1]), y2=log(a[2]);
|
xue@1
|
438 double ix0_12=y0/((x0-x1)*(x0-x2)), ix1_02=y1/((x1-x0)*(x1-x2)), ix2_01=y2/((x2-x0)*(x2-x1));
|
xue@1
|
439 double aa=ix0_12+ix1_02+ix2_01,
|
xue@1
|
440 b=-(x1+x2)*ix0_12-(x0+x2)*ix1_02-(x0+x1)*ix2_01,
|
xue@1
|
441 c=x1*x2*ix0_12+x0*x2*ix1_02+x0*x1*ix2_01;
|
xue@1
|
442 for (int fr=0; fr<Fr; fr++) A2[fr]=exp(c+fr*(b+fr*aa));
|
xue@1
|
443 }
|
xue@1
|
444 else
|
xue@1
|
445 {
|
xue@1
|
446 double *fa=new double[npfr*4], *fb=&fa[npfr], *fc=&fa[npfr*2], *fd=&fa[npfr*3];
|
xue@1
|
447 CubicSpline(npfr-2, fa, fb, fc, fd, frs, a, 0, 1, A2, 1, 0, Fr-1);
|
xue@1
|
448 for (int fr=0; fr<Fr; fr++) A2[fr]=exp(A2[fr]);
|
xue@1
|
449 delete[] fa;
|
xue@1
|
450 }
|
xue@1
|
451 delete[] frs;
|
xue@1
|
452 }//DeAM
|
xue@1
|
453
|
Chris@5
|
454 /**
|
xue@1
|
455 function DeAM: wrapper function using floating-point cycle boundaries
|
xue@1
|
456
|
xue@1
|
457 In: A1[Fr]: original amplitude
|
xue@1
|
458 lp[npfr]: cycle boundaries
|
xue@1
|
459 Out: A2[Fr]: demodulated amplitude
|
xue@1
|
460
|
xue@1
|
461 No return value.
|
xue@1
|
462 */
|
xue@1
|
463 void DeAM(double* A2, double* A1, int npfr, double* lp, int Fr)
|
xue@1
|
464 {
|
xue@1
|
465 int* peakfr=new int[npfr];
|
xue@1
|
466 for (int i=0; i<npfr; i++) peakfr[i]=ceil(lp[i]);
|
xue@1
|
467 DeAM(A2, A1, npfr, peakfr, Fr);
|
xue@1
|
468 delete[] peakfr;
|
xue@1
|
469 }//DeAM
|
xue@1
|
470
|
Chris@5
|
471 /**
|
xue@1
|
472 function DeFM: frequency demodulation based on given segmentation into cycles
|
xue@1
|
473
|
xue@1
|
474 In: f1[Fr], AA[Fr]: original frequency and partial-independent amplitude
|
xue@1
|
475 peakfr[npfr]: cycle boundaries (literally, "frame indices of frequency modulation peaks")
|
xue@1
|
476 furthursmoothing: specifies if a second round demodulation is to be performed for more smooth
|
xue@1
|
477 carrier
|
xue@1
|
478 Out: f2[Fr]: demodulated frequency
|
xue@1
|
479 f[fcount], frs[fcount]: frequency and time (in frames) of carrier knots, optional
|
xue@1
|
480 fct: frequency centroid
|
xue@1
|
481
|
xue@1
|
482 No return value.
|
xue@1
|
483 */
|
xue@1
|
484 void DeFM(double* f2, double* f1, double* AA, int npfr, int* peakfr, int Fr, double& fct, int& fcount, double* &frs, double* &f, bool furthersmoothing)
|
xue@1
|
485 {
|
xue@1
|
486 double ac=0;
|
xue@1
|
487 fct=0;
|
xue@1
|
488
|
xue@1
|
489 if (npfr==1)
|
xue@1
|
490 {
|
xue@1
|
491 memcpy(f2, f1, sizeof(double)*Fr);
|
xue@1
|
492 for (int fr=0; fr<Fr; fr++) ac+=AA[fr], fct+=f1[fr]*AA[fr]; fct/=ac;
|
xue@1
|
493 return;
|
xue@1
|
494 }
|
xue@1
|
495
|
xue@1
|
496 bool localfrs=(frs==(double*)0xFFFFFFFF), localf=(f==(double*)0xFFFFFFFF);
|
xue@1
|
497 if (!localfrs) delete[] frs;
|
xue@1
|
498 if (!localf) delete[] f;
|
xue@1
|
499 frs=new double[npfr]; f=new double[npfr];
|
xue@1
|
500 for (int i=0; i<npfr-1; i++)
|
xue@1
|
501 {
|
xue@1
|
502 int frst=peakfr[i], fren=peakfr[i+1];
|
xue@1
|
503 f[i]=(f1[frst]*AA[frst]+f1[fren]*AA[fren])*0.5;
|
xue@1
|
504 frs[i]=(frst*AA[frst]+fren*AA[fren])*0.5;
|
xue@1
|
505 double lrec=(AA[frst]+AA[fren])*0.5;
|
xue@1
|
506 for (int fr=frst+1; fr<fren; fr++) f[i]+=f1[fr]*AA[fr], frs[i]+=fr*AA[fr], lrec+=AA[fr];
|
xue@1
|
507 ac+=lrec;
|
xue@1
|
508 fct+=f[i];
|
xue@1
|
509 f[i]/=lrec, frs[i]/=lrec;
|
xue@1
|
510 }
|
xue@1
|
511 fct/=ac;
|
xue@1
|
512
|
xue@1
|
513 if (furthersmoothing)
|
xue@1
|
514 {
|
xue@1
|
515 //further smoothing
|
xue@1
|
516 int newnpfr=1;
|
xue@1
|
517 for (int pfr=1; pfr<npfr-2; pfr++)
|
xue@1
|
518 {
|
xue@1
|
519 if ((f[pfr]>f[pfr-1] && f[pfr]>f[pfr+1]) || (f[pfr]<f[pfr-1] && f[pfr]<f[pfr+1]))
|
xue@1
|
520 {
|
xue@1
|
521 //this is a peak or valley
|
xue@1
|
522 if ((pfr+1<npfr-2 && f[pfr+1]>f[pfr] && f[pfr+1]>f[pfr+2]) || (f[pfr+1]<f[pfr] && f[pfr+1]<f[pfr+2]))
|
xue@1
|
523 {
|
xue@1
|
524 frs[newnpfr]=0.5*(frs[pfr]+frs[pfr+1]), f[newnpfr]=0.5*(f[pfr]+f[pfr+1]);
|
xue@1
|
525 newnpfr++;
|
xue@1
|
526 }
|
xue@1
|
527 }
|
xue@1
|
528 else
|
xue@1
|
529 {
|
xue@1
|
530 frs[newnpfr]=frs[pfr], f[newnpfr]=f[pfr];
|
xue@1
|
531 newnpfr++;
|
xue@1
|
532 }
|
xue@1
|
533 }
|
xue@1
|
534 frs[newnpfr]=frs[npfr-2], f[newnpfr]=f[npfr-2]; newnpfr++; newnpfr++;
|
xue@1
|
535 npfr=newnpfr;
|
xue@1
|
536 }
|
xue@1
|
537
|
xue@1
|
538 Smooth_Interpolate(f2, Fr, npfr, f, frs);
|
xue@1
|
539 fcount=npfr-1;
|
xue@1
|
540
|
xue@1
|
541 if (localfrs) delete[] frs;
|
xue@1
|
542 if (localf) delete[] f;
|
xue@1
|
543 }//DeFM
|
xue@1
|
544
|
Chris@5
|
545 /**
|
xue@1
|
546 function DeFM: wrapper function using floating-point cycle boundaries
|
xue@1
|
547
|
xue@1
|
548 In: f1[Fr], AA[Fr]: original frequency and partial-independent amplitude
|
xue@1
|
549 lp[npfr]: cycle boundaries
|
xue@1
|
550 furthursmoothing: specifies if a second round demodulation is to be performed for more smooth
|
xue@1
|
551 carrier
|
xue@1
|
552 Out: f2[Fr]: demodulated frequency
|
xue@1
|
553 f[fcount], frs[fcount]: frequency and time (in frames) of carrier knots, optional
|
xue@1
|
554 fct: frequency centroid
|
xue@1
|
555
|
xue@1
|
556 No return value.
|
xue@1
|
557 */
|
xue@1
|
558 void DeFM(double* f2, double* f1, double* AA, int npfr, double* lp, int Fr, double& fct, int& fcount, double* &frs, double* &f, bool furthersmoothing)
|
xue@1
|
559 {
|
xue@1
|
560 int* peakfr=new int[npfr];
|
xue@1
|
561 for (int i=0; i<npfr; i++) peakfr[i]=ceil(lp[i]);
|
xue@1
|
562 DeFM(f2, f1, AA, npfr, peakfr, Fr, fct, fcount, frs, f, furthersmoothing);
|
xue@1
|
563 delete[] peakfr;
|
xue@1
|
564 }//DeFM
|
xue@1
|
565
|
Chris@5
|
566 /**
|
xue@1
|
567 function FindPeaks: find modulation peaks of signal F0[] roughly periodical at $periodinframe
|
xue@1
|
568
|
xue@1
|
569 In: F0[Fr]: modulated signal
|
xue@1
|
570 periodinframe: reference modulation period
|
xue@1
|
571 Out: npfr, peakfr[npfr]: modulation peaks
|
xue@1
|
572 peaky[npfr]: shape score for the peaks measuring their similarity to cosine peak, optional
|
xue@1
|
573
|
xue@1
|
574 No return value.
|
xue@1
|
575 */
|
xue@1
|
576 void FindPeaks(int* peakfr, int& npfr, double* F0, int Fr, double periodinframe, double*& peaky)
|
xue@1
|
577 {
|
xue@1
|
578 npfr=0;
|
xue@1
|
579 for (int fr=1; fr<Fr-1; fr++)
|
xue@1
|
580 {
|
xue@1
|
581 if (F0[fr]>F0[fr-1] && F0[fr]>F0[fr+1])
|
xue@1
|
582 {
|
xue@1
|
583 peakfr[npfr++]=fr;
|
xue@1
|
584 }
|
xue@1
|
585 }
|
xue@1
|
586
|
xue@1
|
587 bool localpeaky=(peaky==(double*)0xFFFFFFFF); if (!localpeaky) delete[] peaky;
|
xue@1
|
588
|
xue@1
|
589 peaky=new double[npfr];
|
xue@1
|
590 for (int pfr=0; pfr<npfr; pfr++)
|
xue@1
|
591 {
|
xue@1
|
592 double rfs=0, rff=0, rss=0;
|
xue@1
|
593 if (peakfr[pfr]>periodinframe/2)
|
xue@1
|
594 {
|
xue@1
|
595 double ef0=0; int frcount=0; for (int fr=peakfr[pfr]-periodinframe/2; fr<peakfr[pfr]; fr++) ef0+=F0[fr], frcount++; ef0/=frcount;
|
xue@1
|
596 for (int fr=peakfr[pfr]-periodinframe/2; fr<peakfr[pfr]; fr++)
|
xue@1
|
597 {
|
xue@1
|
598 double s=cos(2*M_PI*(fr-peakfr[pfr])/periodinframe), f=F0[fr];
|
xue@1
|
599 rfs+=(f-ef0)*s; rff+=(f-ef0)*(f-ef0); rss+=s*s;
|
xue@1
|
600 }
|
xue@1
|
601 }
|
xue@1
|
602 if (peakfr[pfr]<Fr-periodinframe/2)
|
xue@1
|
603 {
|
xue@1
|
604 double ef0=0; int frcount=0; for (int fr=peakfr[pfr]; fr<peakfr[pfr]+periodinframe/2; fr++) ef0+=F0[fr], frcount++; ef0/=frcount;
|
xue@1
|
605 for (int fr=peakfr[pfr]; fr<peakfr[pfr]+periodinframe/2; fr++)
|
xue@1
|
606 {
|
xue@1
|
607 double s=cos(2*M_PI*(fr-peakfr[pfr])/periodinframe), f=F0[fr];
|
xue@1
|
608 rfs+=(f-ef0)*s; rff+=(f-ef0)*(f-ef0); rss+=s*s;
|
xue@1
|
609 }
|
xue@1
|
610 }
|
xue@1
|
611 peaky[pfr]=rfs/sqrt(rff*rss);
|
xue@1
|
612 }
|
xue@1
|
613 int pst=0; for (int pfr=1; pfr<npfr; pfr++) if (peaky[pst]<peaky[pfr]) pst=pfr;
|
xue@1
|
614 // return;
|
xue@1
|
615 //*
|
xue@1
|
616 int pen=pst+1, pfr=pst+1;
|
xue@1
|
617 while (pfr<npfr)
|
xue@1
|
618 {
|
xue@1
|
619 int impfr=-1;
|
xue@1
|
620 while (pfr<npfr && peakfr[pfr]<peakfr[pen-1]+periodinframe*0.5) pfr++;
|
xue@1
|
621 if (pfr<npfr && peakfr[pfr]<peakfr[pen-1]+periodinframe*1.5)
|
xue@1
|
622 {
|
xue@1
|
623 double mpfr=peaky[pfr]+copeak(F0, peakfr, pen-1, pfr, periodinframe);
|
xue@1
|
624 impfr=pfr; pfr++;
|
xue@1
|
625 while (pfr<npfr && peakfr[pfr]<peakfr[pen-1]+periodinframe*1.5)
|
xue@1
|
626 {
|
xue@1
|
627 double mp=peaky[pfr]+copeak(F0, peakfr, pen-1, pfr, periodinframe);
|
xue@1
|
628 if (mp>mpfr) impfr=pfr, mpfr=mp;
|
xue@1
|
629 pfr++;
|
xue@1
|
630 }
|
xue@1
|
631 }
|
xue@1
|
632 else
|
xue@1
|
633 {
|
xue@1
|
634 while (pfr<npfr)
|
xue@1
|
635 {
|
xue@1
|
636 if (peaky[pfr]>0) {impfr=pfr; break;}
|
xue@1
|
637 pfr++;
|
xue@1
|
638 }
|
xue@1
|
639 }
|
xue@1
|
640 if (impfr>=0) peakfr[pen++]=peakfr[impfr];
|
xue@1
|
641 }
|
xue@1
|
642 pst--; pfr=pst;
|
xue@1
|
643 while (pfr>=0)
|
xue@1
|
644 {
|
xue@1
|
645 int impfr=-1;
|
xue@1
|
646 while (pfr>=0 && peakfr[pfr]>peakfr[pst+1]-periodinframe*0.5) pfr--;
|
xue@1
|
647 if (pfr>=0 && peakfr[pfr]>=peakfr[pst+1]-periodinframe*1.5)
|
xue@1
|
648 {
|
xue@1
|
649 double mpfr=peaky[pfr]+copeak(F0, peakfr, pfr, pst+1, periodinframe);
|
xue@1
|
650 impfr=pfr; pfr--;
|
xue@1
|
651 while (pfr>=0 && peakfr[pfr]>=peakfr[pst+1]-periodinframe*1.5)
|
xue@1
|
652 {
|
xue@1
|
653 double mp=peaky[pfr]+copeak(F0, peakfr, pfr, pst+1, periodinframe);
|
xue@1
|
654 if (mp>mpfr) impfr=pfr, mpfr=mp;
|
xue@1
|
655 pfr--;
|
xue@1
|
656 }
|
xue@1
|
657 }
|
xue@1
|
658 else
|
xue@1
|
659 {
|
xue@1
|
660 while (pfr>=0)
|
xue@1
|
661 {
|
xue@1
|
662 if (peaky[pfr]>0) {impfr=pfr; break;}
|
xue@1
|
663 pfr--;
|
xue@1
|
664 }
|
xue@1
|
665 }
|
xue@1
|
666 if (impfr>=0) peakfr[pst--]=peakfr[impfr];
|
xue@1
|
667 }
|
xue@1
|
668 pst++;
|
xue@1
|
669 npfr=pen-pst;
|
xue@1
|
670 memmove(peakfr, &peakfr[pst], sizeof(int)*npfr); //*/
|
xue@1
|
671 if (localpeaky) delete[] peaky;
|
xue@1
|
672 }//FindPeaks
|
xue@1
|
673
|
Chris@5
|
674 /**
|
xue@1
|
675 function FS: Fourier series decomposition
|
xue@1
|
676
|
xue@1
|
677 In: data[frst:fren]: signal to decompose
|
xue@1
|
678 period: period of Fourier series decomposition
|
xue@1
|
679 shift: amount of original shift of Fourier components (from frst to frst-shift)
|
xue@1
|
680 K: number of Fourier components requested
|
xue@1
|
681 Out: K: number of Fourier components returned
|
xue@1
|
682 FXR[K], FXI[K]: real and imaginary parts of Fourier series coefficients
|
xue@1
|
683 FRES[K]: decomposition residues
|
xue@1
|
684
|
xue@1
|
685 No return value.
|
xue@1
|
686 */
|
xue@1
|
687 void FS(int& K, double* FXR, double* FXI, double* FRES, double* data, int frst, int fren, double period, double shift)
|
xue@1
|
688 {
|
xue@1
|
689 if (K>period/2) K=period/2;
|
xue@1
|
690 int len=fren-frst+1;
|
xue@1
|
691 double omg0=2*M_PI/period, ilen=1.0/len;
|
xue@1
|
692
|
xue@1
|
693 //for (int fr=frst; fr<=fren; fr++) data[fr]=cos(2*M_PI*fr/period+1);
|
xue@1
|
694
|
xue@1
|
695 double* res=new double[len]; memcpy(res, &data[frst], sizeof(double)*len);
|
xue@1
|
696 double* rec=new double[len];
|
xue@1
|
697 double resene=0; for (int i=0; i<len; i++) resene+=res[i]*res[i]; double ene=resene;
|
xue@1
|
698
|
xue@1
|
699 for (int k=0; k<K; k++)
|
xue@1
|
700 {
|
xue@1
|
701 // double eer=0, eei=0;
|
xue@1
|
702 double xr=0, xi=0, omg=k*omg0;
|
xue@1
|
703 for (int fr=frst; fr<=fren; fr++)
|
xue@1
|
704 {
|
xue@1
|
705 double ph=omg*(fr-shift);
|
xue@1
|
706 double c=cos(ph), s=sin(ph);
|
xue@1
|
707 xr+=data[fr]*c, xi+=data[fr]*s;
|
xue@1
|
708 // eer+=c*c, eei+=s*s;
|
xue@1
|
709 }
|
xue@1
|
710 xr*=ilen, xi*=ilen;
|
xue@1
|
711 // if (eer>0) xr/=eer;
|
xue@1
|
712 // if (eei>0) xi/=eei;
|
xue@1
|
713 FXR[k]=xr, FXI[k]=xi;
|
xue@1
|
714 double lresene=0;
|
xue@1
|
715 for (int fr=frst; fr<=fren; fr++)
|
xue@1
|
716 {
|
xue@1
|
717 double ph=omg*(fr-shift);
|
xue@1
|
718 // rec[fr-frst]=xr*cos(ph)+xi*sin(ph);
|
xue@1
|
719 if (k==0) rec[fr-frst]=xr*cos(ph)+xi*sin(ph);
|
xue@1
|
720 else rec[fr-frst]=2*(xr*cos(ph)+xi*sin(ph));
|
xue@1
|
721 res[fr-frst]-=rec[fr-frst];
|
xue@1
|
722 lresene+=res[fr-frst]*res[fr-frst];
|
xue@1
|
723 }
|
xue@1
|
724 resene=lresene;
|
xue@1
|
725 FRES[k]=resene/ene;
|
xue@1
|
726 }
|
xue@1
|
727 delete[] rec;
|
xue@1
|
728 delete[] res;
|
xue@1
|
729 }//FS
|
xue@1
|
730
|
Chris@5
|
731 /**
|
xue@1
|
732 function FS_QR: Fourier series decomposition with QR orthogonalization. Since the Fourier series is
|
xue@1
|
733 applied on finite-length discrate signal, the Fourier components are no longer orthogonal to each
|
xue@1
|
734 other. A decreasing residue can be guaranteed by applying QR (or any other) orthogonalization process
|
xue@1
|
735 to the Fourier components before decomposition.
|
xue@1
|
736
|
xue@1
|
737 In: data[0:Fr]: signal to decompose
|
xue@1
|
738 period: period of Fourier series decomposition
|
xue@1
|
739 shift: amount of original shift of Fourier components (from 0 to -shift)
|
xue@1
|
740 K: number of Fourier components requested
|
xue@1
|
741 Out: K: number of Fourier components returned
|
xue@1
|
742 FXR[2K-1]: Fourier series coefficients, in the order of 0r, 1i, 1r, 2i, 2r, ....
|
xue@1
|
743 FRES[K]: decomposition residues, optional
|
xue@1
|
744
|
xue@1
|
745 No return value.
|
xue@1
|
746 */
|
xue@1
|
747 void FS_QR(int& K, double* FXR, double* data, int Fr, double period, double shift, double* FRES)
|
xue@1
|
748 {
|
xue@1
|
749 int len=Fr+1;
|
xue@1
|
750 if (K>period/2) K=period/2;
|
xue@1
|
751 if (K>Fr/2) K=Fr/2;
|
xue@1
|
752 if (K>len/2) K=len/2;
|
xue@1
|
753 if (K<=0) return;
|
xue@1
|
754 memset(FXR, 0, sizeof(double)*(2*K-1));
|
xue@1
|
755
|
xue@1
|
756 double omg0=2*M_PI/period, ene, resene;
|
xue@1
|
757
|
xue@1
|
758 if (FRES)
|
xue@1
|
759 {
|
xue@1
|
760 ene=0; for (int i=0; i<len; i++) ene+=data[i]*data[i]; resene=ene;
|
xue@1
|
761 }
|
xue@1
|
762
|
xue@1
|
763 /*debug only
|
xue@1
|
764 double *res=new double[len*4], *rec=&res[len];
|
xue@1
|
765 memcpy(res, data, sizeof(double)*len); memset(rec, 0, sizeof(double)*len);
|
xue@1
|
766 double resene2=resene;//*/
|
xue@1
|
767
|
xue@1
|
768 int NK=K*2-1;
|
xue@1
|
769
|
xue@1
|
770 Alloc2(len, NK, A); Alloc2(len, len, Q); Alloc2(len, NK, R);
|
xue@1
|
771 for (int fr=0; fr<=Fr; fr++) A[fr][0]=1;
|
xue@1
|
772 for (int k=1; k<(NK+1)/2; k++)
|
xue@1
|
773 {
|
xue@1
|
774 double omg=k*omg0;
|
xue@1
|
775 for (int fr=0; fr<=Fr; fr++){double ph=omg*(fr-shift); A[fr][2*k-1]=2*sin(ph), A[fr][2*k]=2*cos(ph);}
|
xue@1
|
776 }
|
xue@1
|
777 QR_householder(len, NK, A, Q, R);///////////////////
|
xue@1
|
778 GIUT(NK, R);
|
xue@1
|
779 for (int k=0; k<NK; k++)
|
xue@1
|
780 {
|
xue@1
|
781 double xr=0;
|
xue@1
|
782 for (int fr=0; fr<=Fr; fr++)
|
xue@1
|
783 {
|
xue@1
|
784 double c=Q[fr][k];
|
xue@1
|
785 xr+=data[fr]*c;
|
xue@1
|
786 }
|
xue@1
|
787 for (int kk=0; kk<=k; kk++) FXR[kk]+=xr*R[kk][k];
|
xue@1
|
788 /*debug only
|
xue@1
|
789 double lresene=0;
|
xue@1
|
790 for (int fr=0; fr<=Fr; fr++)
|
xue@1
|
791 {
|
xue@1
|
792 rec[fr]=0; for (int kk=0; kk<=k; kk++) rec[fr]+=FXR[kk]*A[fr][kk];
|
xue@1
|
793 res[fr]=data[fr]-rec[fr];
|
xue@1
|
794 lresene+=res[fr]*res[fr];
|
xue@1
|
795 }
|
xue@1
|
796 resene2=lresene; */
|
xue@1
|
797
|
xue@1
|
798 if (FRES)
|
xue@1
|
799 {
|
xue@1
|
800 resene-=xr*xr;
|
xue@1
|
801 if (k%2==0) FRES[k/2]=resene/ene;
|
xue@1
|
802 }
|
xue@1
|
803 }
|
xue@1
|
804 /* debug only
|
xue@1
|
805 delete[] res; //*/
|
xue@1
|
806 DeAlloc2(A); DeAlloc2(Q); DeAlloc2(R);
|
xue@1
|
807 }//FS_QR
|
xue@1
|
808
|
Chris@5
|
809 /**
|
xue@1
|
810 function InterpolateV: adjusts modulation rate to $rate times the current value. Since TVo is based on
|
xue@1
|
811 individual cycles, this operation involves finding new cycle boundaries and recomputing other single-
|
xue@1
|
812 cycle descriptors by interpolation. This is used for time stretching and cycle rate adjustment.
|
xue@1
|
813
|
xue@1
|
814 In: V: a TVo object to adjust
|
xue@1
|
815 newP: number of total cycles after adjustment.
|
xue@1
|
816 rate: amount of adjustment.
|
xue@1
|
817 Out: another TVo object with new cycle boundaries and single-cycle descriptors interpoated from V
|
xue@1
|
818
|
xue@1
|
819 Returns pointer to the output TVo. This function does not affect the content in V.
|
xue@1
|
820 */
|
xue@1
|
821 TVo* InterpolateV(double newP, double rate, TVo& V)
|
xue@1
|
822 {
|
xue@1
|
823 double Pst=-V.lp[0]/(V.lp[1]-V.lp[0]);
|
xue@1
|
824 double oldP=V.P-1+(V.L-V.lp[V.P-1])/(V.lp[V.P-1]-V.lp[V.P-2])-Pst;
|
xue@1
|
825
|
xue@1
|
826 TVo* newV=new TVo;
|
xue@1
|
827 memcpy(newV, &V, sizeof(TVo));
|
xue@1
|
828
|
xue@1
|
829 newV->F0C=0; newV->A0C=0; newV->peakfr=0; newV->Dp=0; newV->lp=0, newV->Kp=0;
|
xue@1
|
830 newV->fxr=0; newV->LogASp=0; newV->F0=0; newV->F0D=0; newV->fres=0;
|
xue@1
|
831
|
xue@1
|
832 int inewP=ceil(newP+Pst);
|
xue@1
|
833 newV->P=inewP;
|
xue@1
|
834
|
xue@1
|
835 newV->peakfr=new int[inewP];
|
xue@1
|
836 newV->AllocateP(); newV->AllocatePK();
|
xue@1
|
837
|
xue@1
|
838 newV->lp[0]=V.lp[0]/rate;
|
xue@1
|
839 newV->peakfr[0]=floor(newV->lp[0]+0.5);
|
xue@1
|
840 for (int p=1; p<inewP; p++)
|
xue@1
|
841 {
|
xue@1
|
842 double rp=1+(p-1)*(oldP-2+Pst)/(newP-2+Pst);
|
xue@1
|
843 int ip=floor(rp); rp=rp-ip;
|
xue@1
|
844 if (ip+1>=V.P) ip=V.P-1, rp=0;
|
xue@1
|
845 if (fabs(rp)<1e-16)
|
xue@1
|
846 {
|
xue@1
|
847 newV->lp[p]=newV->lp[p-1]+(V.lp[ip]-V.lp[ip-1])/rate;
|
xue@1
|
848 newV->Dp[p]=V.Dp[ip];
|
xue@1
|
849 newV->Kp[p]=V.Kp[ip];
|
xue@1
|
850 memcpy(newV->fxr[p], V.fxr[ip], sizeof(double)*2*newV->Kp[p]);
|
xue@1
|
851 memcpy(newV->LogASp[p], V.LogASp[ip], sizeof(double)*V.M);
|
xue@1
|
852 }
|
xue@1
|
853 else
|
xue@1
|
854 {
|
xue@1
|
855 double fv1=1.0/(V.lp[ip]-V.lp[ip-1]), fv2=1.0/(V.lp[ip+1]-V.lp[ip]);
|
xue@1
|
856 double fv=rate*(fv1*(1-rp)+fv2*rp);
|
xue@1
|
857 newV->lp[p]=newV->lp[p-1]+1.0/fv;
|
xue@1
|
858 newV->Dp[p]=V.Dp[ip]*(1-rp)+V.Dp[ip+1]*rp;
|
xue@1
|
859 int minK=V.Kp[ip]; if (minK>V.Kp[ip+1]) minK=V.Kp[ip+1];
|
xue@1
|
860 for (int k=0; k<2*minK-1; k++) newV->fxr[p][k]=V.fxr[ip][k]*(1-rp)+V.fxr[ip+1][k]*rp;
|
xue@1
|
861 for (int m=0; m<V.M; m++) newV->LogASp[p][m]=V.LogASp[ip][m]*(1-rp)+V.LogASp[ip+1][m]*rp;
|
xue@1
|
862 newV->Kp[p]=minK;
|
xue@1
|
863 }
|
xue@1
|
864 newV->peakfr[p]=floor(newV->lp[p]+0.5);
|
xue@1
|
865 memset(newV->fres[0], 0, sizeof(double)*newV->P*V.K);
|
xue@1
|
866 }
|
xue@1
|
867 int newL=newV->lp[inewP-1]+(newP+Pst-(inewP-1))*(V.lp[V.P-1]-V.lp[V.P-2])/rate+0.5;
|
xue@1
|
868 newV->AllocateL(newL);
|
xue@1
|
869
|
xue@1
|
870 //F0C and A0C
|
xue@1
|
871 if (V.L!=newL)
|
xue@1
|
872 {
|
xue@1
|
873 for (int l=0; l<newL; l++)
|
xue@1
|
874 {
|
xue@1
|
875 double rl=1.0*l*(V.L-1)/(newL-1);
|
xue@1
|
876 int il=floor(rl); rl-=il;
|
xue@1
|
877 newV->F0C[l]=V.F0C[il]*(1-rl)+V.F0C[il+1]*rl;
|
xue@1
|
878 newV->A0C[l]=V.A0C[il]*(1-rl)+V.A0C[il+1]*rl;
|
xue@1
|
879 }
|
xue@1
|
880 }
|
xue@1
|
881 else
|
xue@1
|
882 {
|
xue@1
|
883 memcpy(newV->F0C, V.F0C, sizeof(double)*V.L);
|
xue@1
|
884 memcpy(newV->A0C, V.A0C, sizeof(double)*V.L);
|
xue@1
|
885 // memcpy(newV->F0, V.F0, sizeof(double)*V.L);
|
xue@1
|
886 // memcpy(newV->F0D, V.F0D, sizeof(double)*V.L);
|
xue@1
|
887 }
|
xue@1
|
888 return newV;
|
xue@1
|
889 }//InterpoalteV
|
xue@1
|
890
|
xue@1
|
891 //vibrato rate boundaries, in Hz
|
xue@1
|
892 #define MAXMOD 15.0
|
xue@1
|
893 #define MINMOD 3.0
|
xue@1
|
894
|
Chris@5
|
895 /**
|
xue@1
|
896 function RateAndReg: evaluates modulation rate and regularity
|
xue@1
|
897
|
xue@1
|
898 In: data[frst:fren]: modulated signal, time measured in frames
|
xue@1
|
899 padrate: padding rate used for inverse FFT
|
xue@1
|
900 sps: sampling frequency
|
xue@1
|
901 offst: hop size
|
xue@1
|
902 Out: rate, regularity: rate and regularity
|
xue@1
|
903
|
xue@1
|
904 No return value.
|
xue@1
|
905 */
|
xue@1
|
906 void RateAndReg(double& rate, double& regularity, double* data, int frst, int fren, int padrate, double sps, double offst)
|
xue@1
|
907 {
|
xue@1
|
908 rate=0; regularity=0;
|
xue@1
|
909 //find the section used for calculating regularity and rate
|
xue@1
|
910 int frlen=fren-frst+1, frlenp=1<<(int(log2(fren))+2), frlenpp=frlenp*padrate;
|
xue@1
|
911 double *lf=new double[frlenpp*4];
|
xue@1
|
912 cdouble *w=(cdouble*)&lf[frlenpp];
|
xue@1
|
913 cdouble *x=(cdouble*)&lf[frlenpp*2];
|
xue@1
|
914 SetTwiddleFactors(frlenp, w);
|
xue@1
|
915
|
xue@1
|
916 memset(lf, 0, sizeof(double)*frlenp);
|
xue@1
|
917 memcpy(lf, &data[frst], sizeof(double)*frlen);
|
xue@1
|
918 // for (int i=0; i<frlen; i++) lf[i]=data[frst+i]-edata;
|
xue@1
|
919
|
xue@1
|
920 double* rdata=new double[50];
|
xue@1
|
921 for (int i=0; i<50; i++)
|
xue@1
|
922 {
|
xue@1
|
923 rdata[i]=0; for (int j=0; j<fren-i; j++) rdata[i]+=data[j]*data[j+i];
|
xue@1
|
924 }
|
xue@1
|
925
|
xue@1
|
926
|
xue@1
|
927 RFFTC(lf, NULL, NULL, log2(frlenp), w, x, 0);
|
xue@1
|
928 // xr[0]=0;
|
xue@1
|
929 for (int i=0; i<frlenp/2; i++) {x[i].x=x[i].x*x[i].x+x[i].y*x[i].y; x[i].y=0;}
|
xue@1
|
930 memset(&x[frlenp/2], 0, sizeof(cdouble)*(frlenpp-frlenp/2));
|
xue@1
|
931
|
xue@1
|
932 SetTwiddleFactors(frlenpp, w);
|
xue@1
|
933 CIFFTR(x, log2(frlenpp), w, lf);
|
xue@1
|
934
|
xue@1
|
935 delete[] rdata;
|
xue@1
|
936
|
xue@1
|
937 double minpeak=sps/(offst*MAXMOD), maxpeak=sps/(offst*MINMOD);
|
xue@1
|
938
|
xue@1
|
939 //find 2nd highest peak at interval padrate
|
xue@1
|
940 int imaxlf=padrate*minpeak;
|
xue@1
|
941 while (imaxlf<frlenpp && imaxlf<padrate*maxpeak && lf[imaxlf]<=lf[imaxlf-padrate]) imaxlf+=padrate;
|
xue@1
|
942 double maxlf=lf[imaxlf];
|
xue@1
|
943 for (int i=imaxlf/padrate; i<frlen/2; i++) if (maxlf<lf[i*padrate]) maxlf=lf[i*padrate], imaxlf=i*padrate;
|
xue@1
|
944 //locate the peak at interval 1
|
xue@1
|
945 int ii=imaxlf; for (int i=ii-padrate+1; i<ii+padrate; i++) if (maxlf<lf[i]) maxlf=lf[i], imaxlf=i;
|
xue@1
|
946
|
xue@1
|
947 double a_=0.5*(lf[imaxlf-1]+lf[imaxlf+1])-maxlf, b_=0.5*(lf[imaxlf+1]-lf[imaxlf-1]);
|
xue@1
|
948 double period=imaxlf-0.5*b_/a_;
|
xue@1
|
949 period=period/padrate; //period in frames
|
xue@1
|
950 rate=sps/(period*offst); //rate in hz
|
xue@1
|
951 regularity=(maxlf-0.25*b_*b_/a_)/lf[0]*(fren-frst)/(fren-frst-period);
|
xue@1
|
952
|
xue@1
|
953 delete[] lf;
|
xue@1
|
954 }//RateAndReg
|
xue@1
|
955
|
Chris@5
|
956 /**
|
xue@1
|
957 function RegularizeV: synthesize a regular vibrato from the basic descriptors.
|
xue@1
|
958
|
xue@1
|
959 In: V: a TVo object hosting vibrato descriptors
|
xue@1
|
960 sps: sampling rate
|
xue@1
|
961 h: hop size
|
xue@1
|
962 Out: HS: a harmonic sinusoid
|
xue@1
|
963
|
xue@1
|
964 No return value.
|
xue@1
|
965 */
|
xue@1
|
966 void RegularizeV(THS& HS, TVo& V, double sps, double h)
|
xue@1
|
967 {
|
xue@1
|
968 int K=V.Kp[1]; for (int p=2; p<V.P; p++) if (K>V.Kp[p]) K=V.Kp[p];
|
xue@1
|
969 double D=0, *fxr=new double[2*K-1];
|
xue@1
|
970 memset(fxr, 0, sizeof(double)*(2*K-1));
|
xue@1
|
971 for (int p=1; p<V.P; p++)
|
xue@1
|
972 {
|
xue@1
|
973 D+=V.Dp[p]; for (int k=0; k<2*K-1; k++) fxr[k]+=V.fxr[p][k]*V.Dp[p];
|
xue@1
|
974 }
|
xue@1
|
975 //uncomment the following line if re-normalization needed
|
xue@1
|
976 //double alfa=fxr[0]*fxr[0]; for (int k=1; k<2*K-1; k++) alfa+=2*fxr[k]*fxr[k]; alfa=sqrt(alfa); D=alfa;
|
xue@1
|
977 for (int k=0; k<2*K-1; k++) fxr[k]/=D;
|
xue@1
|
978 D/=(V.P-1);
|
xue@1
|
979 V.D=D;
|
xue@1
|
980
|
xue@1
|
981 atom** Partials=HS.Partials;
|
xue@1
|
982 for (int l=0; l<V.L; l++)
|
xue@1
|
983 {
|
xue@1
|
984 double theta=V.rate*l*V.h/sps;//-0.25;
|
xue@1
|
985 //f0(theta)
|
xue@1
|
986 double f0=fxr[0]; for (int k=1; k<K; k++) f0=f0+2*(fxr[2*k-1]*sin(2*M_PI*k*theta)+fxr[2*k]*cos(2*M_PI*k*theta));
|
xue@1
|
987 V.F0D[l]=D*f0; V.F0[l]=V.F0C[l]+V.F0D[l];
|
xue@1
|
988 for (int m=0; m<V.M; m++)
|
xue@1
|
989 {
|
xue@1
|
990 if (Partials[m][l].t<0) Partials[m][l].t=Partials[0][l].t;
|
xue@1
|
991 Partials[m][l].f=(m+1)*V.F0[l];
|
xue@1
|
992 if (Partials[m][l].f>0.5 || Partials[m][l].f<0) Partials[m][l].f=-1, Partials[m][l].a=0;
|
xue@1
|
993 else Partials[m][l].a=V.A0C[l]*exp(V.LogAS[m]+V.LogAF[int(Partials[m][l].f*V.afres)]);
|
xue@1
|
994 }
|
xue@1
|
995 }
|
xue@1
|
996
|
xue@1
|
997 delete[] fxr;
|
xue@1
|
998 }//RegularizeV
|
xue@1
|
999
|
Chris@5
|
1000 /**
|
xue@1
|
1001 function QIE: computes extremum using quadratic interpolation
|
xue@1
|
1002
|
xue@1
|
1003 In: y[-1:1]: three points to interpolate from. It is assumed y[0] is larger (or smaller) than both
|
xue@1
|
1004 y[-1] and y[1].
|
xue@1
|
1005
|
xue@1
|
1006 Returns the extremum of y.
|
xue@1
|
1007 */
|
xue@1
|
1008 double QIE(double* y)
|
xue@1
|
1009 {
|
xue@1
|
1010 double a=0.5*(y[1]+y[-1])-y[0], b=0.5*(y[1]-y[-1]);
|
xue@1
|
1011 return y[0]-0.25*b*b/a;
|
xue@1
|
1012 }//QIE
|
xue@1
|
1013
|
Chris@5
|
1014 /**
|
xue@1
|
1015 function QIE: computes extremum using quadratic interpolation
|
xue@1
|
1016
|
xue@1
|
1017 In: y[-1:1]: three points to interpolate from. It is assumed y[0] is larger (or smaller) than both
|
xue@1
|
1018 y[-1] and y[1].
|
xue@1
|
1019 Out: x: the argument value that yields extremum of y(x)
|
xue@1
|
1020
|
xue@1
|
1021 Returns the extremum of y.
|
xue@1
|
1022 */
|
xue@1
|
1023 double QIE(double* y, double& x)
|
xue@1
|
1024 {
|
xue@1
|
1025 double a=0.5*(y[1]+y[-1])-y[0], b=0.5*(y[1]-y[-1]);
|
xue@1
|
1026 x=-0.5*b/a;
|
xue@1
|
1027 return y[0]-0.25*b*b/a;
|
xue@1
|
1028 }//QIE
|
xue@1
|
1029
|
Chris@5
|
1030 /**
|
xue@1
|
1031 function S_F: original source-filter estimation used in AES124.
|
xue@1
|
1032
|
xue@1
|
1033 In: afres: filter response resolution
|
xue@1
|
1034 Partials[M][Fr]: HS partials
|
xue@1
|
1035 A0C[Fr]: partial-independent amplitude carrier
|
xue@1
|
1036 lp[P]: cycle boundaries
|
xue@1
|
1037 F0Overall: average fundamental frequency
|
xue@1
|
1038 Out: LogAF[afres/2]: filter response
|
xue@1
|
1039 LogAS[M]: source amplitudes
|
xue@1
|
1040
|
xue@1
|
1041 Returns 0.
|
xue@1
|
1042 */
|
xue@1
|
1043 double S_F(int afres, double* LogAF, double* LogAS, int Fr, int M, atom** Partials, double* A0C, double* lp, int P, double F0Overall)
|
xue@1
|
1044 {
|
xue@1
|
1045 //SOURCE-FILTER estimation routines
|
xue@1
|
1046 //derivative of log A(f), f is sampled at 1/8192 (5hz), averaged over (-15hz, 15hz)
|
xue@1
|
1047 double *DAF=new double[afres], *NAF=&DAF[afres/2];
|
xue@1
|
1048 memset(DAF, 0, sizeof(double)*afres);
|
xue@1
|
1049 double avgwidth1, avgwidth2;
|
xue@1
|
1050 for (int fr=lp[1]; fr<lp[P-1]; fr++) for (int m=0; m<M; m++)
|
xue@1
|
1051 {
|
xue@1
|
1052 if (Partials[m][fr].f>0 && Partials[m][fr-1].f>0 && Partials[m][fr+1].f>0)
|
xue@1
|
1053 {
|
xue@1
|
1054 double f_1=Partials[m][fr-1].f, f0=Partials[m][fr].f, f1=Partials[m][fr+1].f, a_1=Partials[m][fr-1].a/A0C[fr-1], a1=Partials[m][fr+1].a/A0C[fr+1];
|
xue@1
|
1055 if ((f0-f_1)*(f0-f1)<0)
|
xue@1
|
1056 {
|
xue@1
|
1057 double dlogaf_df=(log(a1)-log(a_1))/(f1-f_1); //calculate derivative of log
|
xue@1
|
1058
|
xue@1
|
1059 //this derivative contributes within a frequency interval of |f1-f_1|
|
xue@1
|
1060 if (f1<f_1) {double tmp=f1; f1=f_1; f_1=tmp;}
|
xue@1
|
1061 int startbin=ceil(f_1*afres), endbin=floor(f1*afres);
|
xue@1
|
1062
|
xue@1
|
1063 if (startbin<0) startbin=0;
|
xue@1
|
1064 avgwidth1=(f0-f_1)*afres, avgwidth2=(f1-f0)*afres;
|
xue@1
|
1065 for (int i=startbin; i<=endbin; i++)
|
xue@1
|
1066 {
|
xue@1
|
1067 double fi=i-f0*afres, w;
|
xue@1
|
1068 if (fi<0) w=1-fabs(fi)/avgwidth1; else w=1-fabs(fi)/avgwidth2;
|
xue@1
|
1069 DAF[i]+=dlogaf_df*w, NAF[i]+=w;
|
xue@1
|
1070 }
|
xue@1
|
1071 }
|
xue@1
|
1072 }
|
xue@1
|
1073 }
|
xue@1
|
1074 for (int i=0; i<afres/2; i++) if (NAF[i]>0) DAF[i]=DAF[i]/NAF[i]; //else NAF[i]=0;
|
xue@1
|
1075 int i=0, nbands=0, bandsstart[100], bandsendinc[100]; double mininaf=3;
|
xue@1
|
1076 while (i<afres/2)
|
xue@1
|
1077 {
|
xue@1
|
1078 while (i<afres/2 && NAF[i]<mininaf) i++; if (i>=afres/2) break;
|
xue@1
|
1079 bandsstart[nbands]=i;
|
xue@1
|
1080 while (i<afres/2 && NAF[i]>0) i++; if (i>=afres/2) {bandsendinc[nbands++]=i-1; break;}
|
xue@1
|
1081 if (NAF[i]<=0) while (NAF[i]<mininaf) i--;
|
xue@1
|
1082 bandsendinc[nbands++]=i++;
|
xue@1
|
1083 }
|
xue@1
|
1084
|
xue@1
|
1085 //integrate DAF over the fundamental band, with AF(F0Overall)=1
|
xue@1
|
1086 i=F0Overall*afres;
|
xue@1
|
1087 double theta=F0Overall*afres-i;
|
xue@1
|
1088 LogAF[i]=-0.5*theta*(DAF[i]+DAF[i]*(1-theta)+DAF[i+1]*theta)/afres; i--;
|
xue@1
|
1089 while (i>=bandsstart[0]){LogAF[i]=LogAF[i+1]-0.5*(DAF[i]+DAF[i+1])/afres; i--;}
|
xue@1
|
1090 i=F0Overall*afres+1;
|
xue@1
|
1091 LogAF[i]=0.5*(1-theta)*(DAF[i]+DAF[i-1]*(1-theta)+DAF[i]*theta)/afres; i++;
|
xue@1
|
1092 while (i<=bandsendinc[0]){LogAF[i]=LogAF[i-1]+0.5*(DAF[i]+DAF[i-1])/afres; i++;}
|
xue@1
|
1093
|
xue@1
|
1094 int band=1;
|
xue@1
|
1095 while (band<nbands)
|
xue@1
|
1096 {
|
xue@1
|
1097 //integrate DAF over band-th band, first ignore the blank band
|
xue@1
|
1098 LogAF[bandsstart[band]]=LogAF[bandsendinc[band-1]];
|
xue@1
|
1099 for (int i=bandsstart[band]+1; i<=bandsendinc[band]; i++) LogAF[i]=LogAF[i-1]+0.5*(DAF[i]+DAF[i-1])/afres;
|
xue@1
|
1100 //then look for the shift required between bands
|
xue@1
|
1101 double cshift=0; int ccount=0;
|
xue@1
|
1102 for (int fr=lp[1]; fr<lp[P-1]; fr++)
|
xue@1
|
1103 {
|
xue@1
|
1104 double f=Partials[band-1][fr].f*afres;
|
xue@1
|
1105 if (bandsendinc[band-1]>bandsstart[band-1] && (f<bandsstart[band-1] || f>bandsendinc[band-1])) continue;
|
xue@1
|
1106 int intf=floor(f);
|
xue@1
|
1107 double logaflast=LogAF[intf]+(DAF[intf]+0.5*(DAF[intf+1]-DAF[intf])*(f-intf))*(f-intf)/afres;
|
xue@1
|
1108 f=Partials[band][fr].f*afres;
|
xue@1
|
1109 if (bandsendinc[band]>bandsstart[band] && (f<bandsstart[band] || f>bandsendinc[band])) continue;
|
xue@1
|
1110 intf=floor(f);
|
xue@1
|
1111 double logafthis=LogAF[intf]+(DAF[intf]+0.5*(DAF[intf+1]-DAF[intf])*(f-intf))*(f-intf)/afres;
|
xue@1
|
1112 cshift=cshift+log(Partials[band][fr].a*(band+1)/(Partials[band-1][fr].a*band))+logaflast-logafthis;
|
xue@1
|
1113 ccount++;
|
xue@1
|
1114 }
|
xue@1
|
1115 cshift/=ccount;
|
xue@1
|
1116 //apply the shift
|
xue@1
|
1117 for (int i=bandsstart[band]; i<=bandsendinc[band]; i++) LogAF[i]+=cshift;
|
xue@1
|
1118 //make up the blank band
|
xue@1
|
1119 int lastend=bandsendinc[band-1], thisstart=bandsstart[band];
|
xue@1
|
1120 for (int i=lastend+1; i<thisstart; i++) LogAF[i]=LogAF[lastend]+cshift*(i-lastend)/(thisstart-lastend);
|
xue@1
|
1121 band++;
|
xue@1
|
1122 }
|
xue@1
|
1123 delete[] DAF;
|
xue@1
|
1124
|
xue@1
|
1125 int tmpband=bandsstart[0]; for (int i=0; i<tmpband; i++) LogAF[i]=LogAF[tmpband];
|
xue@1
|
1126 tmpband=bandsendinc[nbands-1]; for (int i=tmpband; i<afres/2; i++) LogAF[i]=LogAF[tmpband];
|
xue@1
|
1127
|
xue@1
|
1128 //Here LogAF contains the filter model, new get the source model
|
xue@1
|
1129 memset(LogAS, 0, sizeof(double)*100);
|
xue@1
|
1130 for (int m=0; m<M; m++)
|
xue@1
|
1131 {
|
xue@1
|
1132 int ccount=0;
|
xue@1
|
1133 for (int fr=lp[1]; fr<lp[P-1]; fr++)
|
xue@1
|
1134 {
|
xue@1
|
1135 double f=Partials[m][fr].f*afres;
|
xue@1
|
1136 if (f<=0) continue;
|
xue@1
|
1137 int intf=floor(f);
|
xue@1
|
1138 LogAS[m]=LogAS[m]+log(Partials[m][fr].a/A0C[fr])-(LogAF[intf]*(intf+1-f)+LogAF[intf+1]*(f-intf));
|
xue@1
|
1139 ccount++;
|
xue@1
|
1140 }
|
xue@1
|
1141 if (ccount>0) LogAS[m]/=ccount;
|
xue@1
|
1142 else LogAS[m]=0;
|
xue@1
|
1143 }
|
xue@1
|
1144 return 0;
|
xue@1
|
1145 }//S_F
|
xue@1
|
1146
|
Chris@5
|
1147 /**
|
xue@1
|
1148 function S_F_SV: slow-variation source-filter estimation used in AES126, adapted from TSF to TVo.
|
xue@1
|
1149
|
xue@1
|
1150 In: afres: filter response resolution
|
xue@1
|
1151 Partials[M][Fr]: HS partials
|
xue@1
|
1152 A0C[Fr]: partial-independent amplitude carrier
|
xue@1
|
1153 lp[P]: cycle boundaries
|
xue@1
|
1154 F: filter response sampling interval
|
xue@1
|
1155 FScaleMode: set if filter sampling uses mel scale
|
xue@1
|
1156 theta: balancing factor of amplitude and frequency variations, needed for SV approach
|
xue@1
|
1157 Out: LogAF[afres/2]: filter response
|
xue@1
|
1158 LogAS[M]: source amplitudes
|
xue@1
|
1159
|
xue@1
|
1160 Returns 0.
|
xue@1
|
1161 */
|
xue@1
|
1162 double S_F_SV(int afres, double* LogAF, double* LogAS, int Fr, int M, atom** Partials, double* A0C, double* lp, int P, double F, int FScaleMode, double theta, double Fs)
|
xue@1
|
1163 {
|
xue@1
|
1164 int lp0=lp[1], lpp=lp[P-1];
|
xue@1
|
1165 int L=lpp-lp0;
|
xue@1
|
1166 Alloc2(L, M, loga); Alloc2(L, M, f);
|
xue@1
|
1167 double fmax=0;
|
xue@1
|
1168 for (int l=0; l<L; l++)
|
xue@1
|
1169 {
|
xue@1
|
1170 int fr=lp0+l;
|
xue@1
|
1171 for (int m=0; m<M; m++)
|
xue@1
|
1172 {
|
xue@1
|
1173 f[l][m]=Partials[m][fr].f;
|
xue@1
|
1174 if (FScaleMode) f[l][m]=log(1+f[l][m]*Fs/700)/log(1+Fs/700);
|
xue@1
|
1175 if (f[l][m]>0) loga[l][m]=log(Partials[m][fr].a);
|
xue@1
|
1176 else loga[l][m]=-100;
|
xue@1
|
1177 if (fmax<f[l][m]) fmax=f[l][m];
|
xue@1
|
1178 }
|
xue@1
|
1179 }
|
xue@1
|
1180 int K=floor(fmax/F);
|
xue@1
|
1181
|
xue@1
|
1182 Alloc2(L, K+2, h); memset(h[0], 0, sizeof(double)*L*(K+2));
|
xue@1
|
1183
|
xue@1
|
1184 SF_SV(h, L, M, K, loga, f, F, theta, 1e-6, L*(K+2));
|
xue@1
|
1185
|
xue@1
|
1186 for (int k=0; k<K+2; k++)
|
xue@1
|
1187 {
|
xue@1
|
1188 for (int l=1; l<L; l++) h[0][k]+=h[l][k];
|
xue@1
|
1189 h[0][k]/=L;
|
xue@1
|
1190 }
|
xue@1
|
1191
|
xue@1
|
1192 for (int i=0; i<afres/2; i++)
|
xue@1
|
1193 {
|
xue@1
|
1194 double freq=i*1.0/afres;
|
xue@1
|
1195 int k=floor(freq/F);
|
xue@1
|
1196 double f_plus=freq/F-k;
|
xue@1
|
1197 if (k<K+1) LogAF[i]=h[0][k]*(1-f_plus)+h[0][k+1]*f_plus;
|
xue@1
|
1198 else LogAF[i]=h[0][K+1];
|
xue@1
|
1199 }
|
xue@1
|
1200
|
xue@1
|
1201 memset(LogAS, 0, sizeof(double)*100);
|
xue@1
|
1202 for (int m=0; m<M; m++)
|
xue@1
|
1203 {
|
xue@1
|
1204 int ccount=0;
|
xue@1
|
1205 for (int fr=lp[1]; fr<lp[P-1]; fr++)
|
xue@1
|
1206 {
|
xue@1
|
1207 double f=Partials[m][fr].f*afres;
|
xue@1
|
1208 if (f<=0) continue;
|
xue@1
|
1209 int intf=floor(f);
|
xue@1
|
1210 LogAS[m]=LogAS[m]+log(Partials[m][fr].a/A0C[fr])-(LogAF[intf]*(intf+1-f)+LogAF[intf+1]*(f-intf));
|
xue@1
|
1211 ccount++;
|
xue@1
|
1212 }
|
xue@1
|
1213 if (ccount>0) LogAS[m]/=ccount;
|
xue@1
|
1214 else LogAS[m]=0;
|
xue@1
|
1215 }
|
xue@1
|
1216
|
xue@1
|
1217 DeAlloc2(loga); DeAlloc2(f); DeAlloc2(h);
|
xue@1
|
1218 return 0;
|
xue@1
|
1219 }//S_F_SV
|
xue@1
|
1220
|
Chris@5
|
1221 /**
|
xue@1
|
1222 function SynthesizeV: synthesizes a harmonic sinusoid from vibrato descriptors
|
xue@1
|
1223
|
xue@1
|
1224 In: V: a TVo object hosting vibrato descriptors
|
xue@1
|
1225 sps: sampling rate
|
xue@1
|
1226 UseK: maximal number of Fourier series components to use to construct frequency modulator
|
xue@1
|
1227 Out: HS: a harmonic sinusoid
|
xue@1
|
1228
|
xue@1
|
1229 No return value.
|
xue@1
|
1230 */
|
xue@1
|
1231 void SynthesizeV(THS* HS, TVo* V, double sps, int UseK)
|
xue@1
|
1232 {
|
xue@1
|
1233 int HSt0=HS->Partials[0][0].t, HSs0=HS->Partials[0][0].s, L=V->L, M=V->M,
|
xue@1
|
1234 P=V->P, *Kp=V->Kp, K=V->K, afres=V->afres;
|
xue@1
|
1235 double **fxr=V->fxr, *lp=V->lp, **LogASp=V->LogASp, *LogAF=V->LogAF, *Dp=V->Dp,
|
xue@1
|
1236 *F0C=V->F0C, *F0D=V->F0D, *F0=V->F0, *A0C=V->A0C, h=V->h;
|
xue@1
|
1237 HS->Resize(M, L);
|
xue@1
|
1238 double *gamp=new double[4*P], *gamm=&gamp[P];
|
xue@1
|
1239
|
xue@1
|
1240 Alloc2(P, K*2, newfxr);
|
xue@1
|
1241 int* newKp=new int[P];
|
xue@1
|
1242 for (int p=1; p<P; p++)
|
xue@1
|
1243 {
|
xue@1
|
1244 memcpy(newfxr[p], fxr[p], sizeof(double)*2*K);
|
xue@1
|
1245 newKp[p]=Kp[p]; if (UseK>=2 && newKp[p]>UseK) newKp[p]=UseK;
|
xue@1
|
1246 CorrectFS(newKp[p], newfxr[p]);
|
xue@1
|
1247 }
|
xue@1
|
1248
|
xue@1
|
1249 double f0, f1;
|
xue@1
|
1250 for (int p=1; p<P-1; p++)
|
xue@1
|
1251 {
|
xue@1
|
1252 if (p==1)
|
xue@1
|
1253 {
|
xue@1
|
1254 f0=newfxr[p][0]; for (int k=1; k<newKp[p]; k++) f0=f0+2*newfxr[p][2*k];
|
xue@1
|
1255 }
|
xue@1
|
1256 else f0=f1;
|
xue@1
|
1257 f1=newfxr[p+1][0]; for (int k=1; k<newKp[p+1]; k++) f1=f1+2*newfxr[p+1][2*k];
|
xue@1
|
1258 gamp[p]=(Dp[p+1]*f1-Dp[p]*f0)/2; gamm[p+1]=-gamp[p]; //additive correction
|
xue@1
|
1259 }
|
xue@1
|
1260 gamm[1]=-gamp[1], gamp[P-1]=-gamm[P-1]; //additive correction
|
xue@1
|
1261 atom** Partials=HS->Partials;
|
xue@1
|
1262 for (int p=0; p<P; p++)
|
xue@1
|
1263 {
|
xue@1
|
1264 double l0, lrange;
|
xue@1
|
1265 int lst, len, ilp;
|
xue@1
|
1266 if (p==0) lst=0, len=ceil(lp[0]), ilp=1;
|
xue@1
|
1267 else if (p==P-1) lst=ceil(lp[p-1]), len=L, ilp=p-1;
|
xue@1
|
1268 else lst=ceil(lp[p-1]), len=ceil(lp[p]), ilp=p;
|
xue@1
|
1269 l0=lp[ilp-1], lrange=lp[ilp]-l0;
|
xue@1
|
1270 for (int l=lst; l<len; l++)
|
xue@1
|
1271 {
|
xue@1
|
1272 Partials[0][l].s=HSs0;
|
xue@1
|
1273 Partials[0][l].t=HSt0+h*l;
|
xue@1
|
1274 double theta=(l-l0)/lrange;
|
xue@1
|
1275 double f0=newfxr[ilp][0]; for (int k=1; k<newKp[ilp]-1; k++) f0=f0+2*(newfxr[ilp][2*k-1]*sin(2*M_PI*k*theta)+newfxr[ilp][2*k]*cos(2*M_PI*k*theta));
|
xue@1
|
1276 F0D[l]=f0*Dp[ilp]+gamm[ilp]*(1-theta)+gamp[ilp]*theta; //additive correction
|
xue@1
|
1277 // V.F0D[l]=f0*V.Dp[lp]; //no correction
|
xue@1
|
1278 F0[l]=F0C[l]+F0D[l];
|
xue@1
|
1279 for (int m=0; m<M; m++)
|
xue@1
|
1280 {
|
xue@1
|
1281 Partials[m][l].s=HSs0;
|
xue@1
|
1282 Partials[m][l].t=Partials[0][l].t;
|
xue@1
|
1283 Partials[m][l].f=(m+1)*F0[l];
|
xue@1
|
1284 if (Partials[m][l].f>0.5 || Partials[m][l].f<0) Partials[m][l].a=0;
|
xue@1
|
1285 else if (ilp==1) Partials[m][l].a=A0C[l]*exp(LogASp[1][m]*(1-0.5*theta)+LogASp[2][m]*0.5*theta+LogAF[int(Partials[m][l].f*afres)]);
|
xue@1
|
1286 else if (ilp==P-1) Partials[m][l].a=A0C[l]*exp(LogASp[ilp][m]*0.5*(1+theta)+LogASp[ilp-1][m]*0.5*(1-theta)+LogAF[int(Partials[m][l].f*afres)]);
|
xue@1
|
1287 else
|
xue@1
|
1288 // Partials[m][l].a=A0C[l]*exp(LogASp[ilp][m]*0.5+LogASp[ilp-1][m]*0.5*(1-theta)+LogASp[ilp+1][m]*0.5*theta+LogAF[int(Partials[m][l].f*afres)]);
|
xue@1
|
1289 Partials[m][l].a=A0C[l]*exp(LogASp[p][m]+LogAF[int(Partials[m][l].f*afres)]);
|
xue@1
|
1290 }
|
xue@1
|
1291 }
|
xue@1
|
1292 }
|
xue@1
|
1293 delete[] gamp;
|
xue@1
|
1294 DeAlloc2(newfxr);
|
xue@1
|
1295 delete[] newKp;
|
xue@1
|
1296 // VibratoDemoForm->Label13->Caption=L;
|
xue@1
|
1297 }//SynthesizeV
|
xue@1
|
1298
|
xue@1
|
1299
|
xue@1
|
1300
|
xue@1
|
1301
|
xue@1
|
1302
|
xue@1
|
1303
|