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