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 "hssf.h"
|
xue@1
|
18 #include "arrayalloc.h"
|
Chris@2
|
19 #include "matrix.h"
|
xue@1
|
20 #include "vibrato.h"
|
xue@1
|
21
|
Chris@5
|
22 /** \file hssf.h */
|
Chris@5
|
23
|
xue@1
|
24 //---------------------------------------------------------------------------
|
xue@1
|
25 //method TSF::TSF: default constructor.
|
xue@1
|
26 TSF::TSF()
|
xue@1
|
27 {
|
xue@1
|
28 memset(this, 0, sizeof(TSF));
|
xue@1
|
29 }//TSF
|
xue@1
|
30
|
xue@1
|
31 //method TSF::~TSF: default destructor.
|
xue@1
|
32 TSF::~TSF()
|
xue@1
|
33 {
|
xue@1
|
34 if (h) DeAlloc2(h);
|
xue@1
|
35 if (b) DeAlloc2(b);
|
xue@1
|
36 delete[] lp;
|
xue@1
|
37 delete[] F0;
|
xue@1
|
38 free(avgh);
|
xue@1
|
39 free(avgb);
|
xue@1
|
40 }//~TSF
|
xue@1
|
41
|
Chris@5
|
42 /**
|
xue@1
|
43 method TSF::AllocateL: allocates or reallocates storage space whose size depends on L. This uses an
|
xue@1
|
44 external L value for allocation and updates L itself.
|
xue@1
|
45 */
|
xue@1
|
46 void TSF::AllocateL(int AnL)
|
xue@1
|
47 {
|
xue@1
|
48 L=AnL;
|
xue@1
|
49 delete[] F0; F0=new double[(L+2)*6];
|
xue@1
|
50 F0C=&F0[L+2], F0D=&F0[(L+2)*2], logA0C=&F0[(L+2)*3], logA0=&F0[(L+2)*4], logA0D=&F0[(L+2)*5];
|
xue@1
|
51 }//AllocateL
|
xue@1
|
52
|
Chris@5
|
53 /**
|
xue@1
|
54 method TSF::AllocateP: allocates or reallocates storage space whose size depends on P, using the
|
xue@1
|
55 interal P.
|
xue@1
|
56 */
|
xue@1
|
57 void TSF::AllocateP()
|
xue@1
|
58 {
|
xue@1
|
59 delete[] lp;
|
xue@1
|
60 lp=new double[P+2];
|
xue@1
|
61 }//AllocateP
|
xue@1
|
62
|
Chris@5
|
63 /**
|
xue@1
|
64 method TSF::AllocateSF: allocates or reallocates storage space for source-filter coefficients.
|
xue@1
|
65 */
|
xue@1
|
66 void TSF::AllocateSF()
|
xue@1
|
67 {
|
xue@1
|
68 if (h) DeAlloc2(h); int k=1.0/F; Allocate2(double, L, (k+2), h); memset(h[0], 0, sizeof(double)*(L)*(k+2));
|
xue@1
|
69 if (b) DeAlloc2(b); Allocate2(double, L, M, b); memset(b[0], 0, sizeof(double)*(L)*M);
|
xue@1
|
70 avgh=(double*)realloc(avgh, sizeof(double)*(k+2)); avgb=(double*)realloc(avgb, sizeof(double)*M);
|
xue@1
|
71 }//AllocateSF
|
xue@1
|
72
|
Chris@5
|
73 /**
|
xue@1
|
74 method TSF::Duplicate: copies the complete contents from another SF object
|
xue@1
|
75
|
xue@1
|
76 In: SF: source object
|
xue@1
|
77 */
|
xue@1
|
78 void TSF::Duplicate(TSF& SF)
|
xue@1
|
79 {
|
Chris@13
|
80 this->TSF::~TSF();
|
xue@1
|
81 memcpy(this, &SF, sizeof(TSF)); lp=F0=avgh=avgb=0, h=b=0;
|
xue@1
|
82 AllocateL(L); memcpy(F0, SF.F0, sizeof(double)*(L+2)*6);
|
xue@1
|
83 AllocateP(); memcpy(lp, SF.lp, sizeof(double)*(P+2));
|
xue@1
|
84 AllocateSF(); int SFL=ceil(lp[P-1])-ceil(lp[0]);
|
xue@1
|
85 for (int l=0; l<SFL; l++) memcpy(h[l], SF.h[l], sizeof(double)*(K+2)), memcpy(b[l], SF.b[l], sizeof(double)*M);
|
xue@1
|
86 memcpy(avgh, SF.avgh, sizeof(double)*(K+2)); memcpy(avgb, SF.avgb, sizeof(double)*M);
|
xue@1
|
87 }//Duplicate
|
xue@1
|
88
|
Chris@5
|
89 /**
|
xue@1
|
90 method TSF::LoadFromFileHandle: reads SF object from file
|
xue@1
|
91 */
|
xue@1
|
92 void TSF::LoadFromFileHandle(FILE* f)
|
xue@1
|
93 {
|
xue@1
|
94 fread(&M, sizeof(int), 1, f);
|
xue@1
|
95 fread(&L, sizeof(int), 1, f);
|
xue@1
|
96 fread(&P, sizeof(int), 1, f);
|
xue@1
|
97 fread(&offst, sizeof(double), 1, f);
|
xue@1
|
98 AllocateL(L); AllocateP();
|
xue@1
|
99 fread(F0C, sizeof(double), L, f);
|
xue@1
|
100 fread(logA0C, sizeof(double), L, f);
|
xue@1
|
101 fread(logA0D, sizeof(double), L, f);
|
xue@1
|
102 fread(lp, sizeof(double), P, f);
|
xue@1
|
103 LoadSFFromFileHandle(f);
|
xue@1
|
104 }//LoadFromFileHandle
|
xue@1
|
105
|
Chris@5
|
106 /**
|
xue@1
|
107 method TSF::LoadSFFromFileHandle: reads SF coefficients from file
|
xue@1
|
108 */
|
xue@1
|
109 void TSF::LoadSFFromFileHandle(FILE* f)
|
xue@1
|
110 {
|
xue@1
|
111 fread(&K, sizeof(int), 1, f);
|
xue@1
|
112 fread(&FScaleMode, sizeof(int), 1, f);
|
xue@1
|
113 fread(&F, sizeof(double), 1, f);
|
xue@1
|
114 fread(&Fs, sizeof(double), 1, f);
|
xue@1
|
115 AllocateSF();
|
xue@1
|
116 for (int l=0; l<L; l++) fread(b[l], sizeof(double), M, f);
|
xue@1
|
117 for (int l=0; l<L; l++) fread(h[l], sizeof(double), K+2, f);
|
xue@1
|
118 fread(avgb, sizeof(double), M, f);
|
xue@1
|
119 fread(avgh, sizeof(double), K+2, f);
|
xue@1
|
120 }//LoadSFFromFileHandle
|
xue@1
|
121
|
Chris@5
|
122 /**
|
xue@1
|
123 method TSF::LogAF: average filter response
|
xue@1
|
124
|
xue@1
|
125 In: f: frequency
|
xue@1
|
126
|
xue@1
|
127 Returns the average response of the filter model at f
|
xue@1
|
128 */
|
xue@1
|
129 double TSF::LogAF(double f)
|
xue@1
|
130 {
|
xue@1
|
131 if (FScaleMode) f=log(1+f*Fs/700)/log(1+Fs/700);
|
xue@1
|
132 int k=floor(f/F);
|
xue@1
|
133 double f_plus=f/F-k;
|
xue@1
|
134 if (k<K+1) return avgh[k]*(1-f_plus)+avgh[k+1]*f_plus;
|
xue@1
|
135 else return avgh[K+1];
|
xue@1
|
136 }//LogAF
|
xue@1
|
137
|
Chris@5
|
138 /**
|
xue@1
|
139 method TSF::LogAF: filter response
|
xue@1
|
140
|
xue@1
|
141 In: f: frequency
|
xue@1
|
142 fr: frame index
|
xue@1
|
143
|
xue@1
|
144 Returns the response of the filter model at f for frame fr
|
xue@1
|
145 */
|
xue@1
|
146 double TSF::LogAF(double f, int fr)
|
xue@1
|
147 {
|
xue@1
|
148 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
149 int l=fr-lp0; if (l<0) l=0; else if (l>=lpp-lp0) l=lpp-lp0-1;
|
xue@1
|
150 if (FScaleMode) f=log(1+f*Fs/700)/log(1+Fs/700);
|
xue@1
|
151 int k=floor(f/F);
|
xue@1
|
152 double f_plus=f/F-k;
|
xue@1
|
153 if (k<K+1) return h[l][k]*(1-f_plus)+h[l][k+1]*f_plus;
|
xue@1
|
154 else return h[l][K+1];
|
xue@1
|
155 }//LogAF
|
xue@1
|
156
|
Chris@5
|
157 /**
|
xue@1
|
158 method TSF::LogAS: source response
|
xue@1
|
159
|
xue@1
|
160 In: m: partial index
|
xue@1
|
161 fr: frame index
|
xue@1
|
162
|
xue@1
|
163 Returns response of the source model for partial m at frame fr
|
xue@1
|
164 */
|
xue@1
|
165 double TSF::LogAS(int m, int fr)
|
xue@1
|
166 {
|
xue@1
|
167 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
168 int l=fr-lp0; if (l<0) l=0; else if (l>=lpp-lp0) l=lpp-lp0-1;
|
xue@1
|
169 return b[l][m];
|
xue@1
|
170 }//LogAS
|
xue@1
|
171
|
Chris@5
|
172 /**
|
xue@1
|
173 method TSF::ReAllocateL: reallocates storage space whose size depends on L, and transfer the contents.
|
xue@1
|
174 This uses an external L value for allocation but does not update L itself.
|
xue@1
|
175 */
|
xue@1
|
176 void TSF::ReAllocateL(int newL)
|
xue@1
|
177 {
|
xue@1
|
178 double* newF0=new double[(newL+2)*4]; F0C=&newF0[newL+2], F0D=&newF0[(newL+2)*2], logA0C=&newF0[(newL+2)*3], logA0=&newF0[(L+2)*4], logA0D=&F0[(L+2)*5];
|
xue@1
|
179 memcpy(logA0C, &F0[(L+2)*3], sizeof(double)*(L+2));
|
xue@1
|
180 memcpy(logA0D, &F0[(L+2)*5], sizeof(double)*(L+2));
|
xue@1
|
181 memcpy(F0D, &F0[(L+2)*2], sizeof(double)*(L+2));
|
xue@1
|
182 memcpy(F0C, &F0[L+2], sizeof(double)*(L+2));
|
xue@1
|
183 memcpy(newF0, F0, sizeof(double)*(L+2));
|
xue@1
|
184 delete[] F0;
|
xue@1
|
185 F0=newF0;
|
xue@1
|
186 }//ReAllocateL
|
xue@1
|
187
|
Chris@5
|
188 /**
|
xue@1
|
189 method TSF::SaveSFToFileHandle: writes SF coefficients to file
|
xue@1
|
190 */
|
xue@1
|
191 void TSF::SaveSFToFileHandle(FILE* f)
|
xue@1
|
192 {
|
xue@1
|
193 fwrite(&K, sizeof(int), 1, f);
|
xue@1
|
194 fwrite(&FScaleMode, sizeof(int), 1, f);
|
xue@1
|
195 fwrite(&F, sizeof(double), 1, f);
|
xue@1
|
196 fwrite(&Fs, sizeof(double), 1, f);
|
xue@1
|
197 for (int l=0; l<L; l++) fwrite(b[l], sizeof(double), M, f);
|
xue@1
|
198 for (int l=0; l<L; l++) fwrite(h[l], sizeof(double), K+2, f);
|
xue@1
|
199 fwrite(avgb, sizeof(double), M, f);
|
xue@1
|
200 fwrite(avgh, sizeof(double), K+2, f);
|
xue@1
|
201 }//SaveSFToFileHandle
|
xue@1
|
202
|
Chris@5
|
203 /**
|
xue@1
|
204 method TSF::SaveToFile: save SF object to file
|
xue@1
|
205
|
xue@1
|
206 In: filename: full path of destination file
|
xue@1
|
207 */
|
xue@1
|
208 void TSF::SaveToFile(char* filename)
|
xue@1
|
209 {
|
xue@1
|
210 FILE* file;
|
xue@1
|
211 if ((file=fopen(filename, "wb"))!=NULL)
|
xue@1
|
212 {
|
xue@1
|
213 SaveToFileHandle(file); fclose(file);
|
xue@1
|
214 }
|
xue@1
|
215 }//SaveToFile
|
xue@1
|
216
|
Chris@5
|
217 /**
|
xue@1
|
218 method TSF::SaveToFileHandle: writes SF object to file
|
xue@1
|
219 */
|
xue@1
|
220 void TSF::SaveToFileHandle(FILE* f)
|
xue@1
|
221 {
|
xue@1
|
222 fwrite(&M, sizeof(int), 1, f);
|
xue@1
|
223 fwrite(&L, sizeof(int), 1, f);
|
xue@1
|
224 fwrite(&P, sizeof(int), 1, f);
|
xue@1
|
225 fwrite(&offst, sizeof(double), 1, f);
|
xue@1
|
226 fwrite(F0C, sizeof(double), L, f);
|
xue@1
|
227 fwrite(logA0C, sizeof(double), L, f);
|
xue@1
|
228 fwrite(logA0D, sizeof(double), L, f);
|
xue@1
|
229 fwrite(lp, sizeof(double), P, f);
|
xue@1
|
230 SaveSFToFileHandle(f);
|
xue@1
|
231 }//SaveToFileHandle
|
xue@1
|
232
|
Chris@5
|
233 /**
|
xue@1
|
234 method TSF::ShiftFilterByDB: adds a given number of dBs to the filter model.
|
xue@1
|
235
|
xue@1
|
236 In: dB: amount to add.
|
xue@1
|
237 */
|
xue@1
|
238 void TSF::ShiftFilterByDB(double dB)
|
xue@1
|
239 {
|
xue@1
|
240 for (int l=0; l<L; l++) for (int k=0; k<K+2; k++) h[l][k]+=dB;
|
xue@1
|
241 for (int k=0; k<K+2; k++) avgh[k]+=dB;
|
xue@1
|
242 }//ShiftFilterByDB
|
xue@1
|
243
|
xue@1
|
244 //---------------------------------------------------------------------------
|
xue@1
|
245 //functions
|
xue@1
|
246
|
xue@1
|
247
|
Chris@5
|
248 /**
|
xue@1
|
249 function AnalyzeSF: wrapper function.
|
xue@1
|
250
|
xue@1
|
251 In: HS: a harmonic sinusoid
|
xue@1
|
252 sps: sampling rate ("samples per second")
|
xue@1
|
253 offst: hop size, the interval between adjacent harmonic atoms of HS
|
xue@1
|
254 SFMode: specifies source-filter estimation criterion, 0=FB (filter bank), 1=SV (slow variation)
|
xue@1
|
255 SFF: filter response sampling interval
|
xue@1
|
256 SFScale: set if filter sampling uses mel scale
|
xue@1
|
257 SFtheta: balancing factor of amplitude and frequency variations, needed for SV approach
|
xue@1
|
258 Out: SF: a TSF object estimated from HS.
|
xue@1
|
259 cyclefrcount: number of cycles
|
xue@1
|
260 cyclefrs[cyclefrcount], cyclefs[cyclefrcount]: average time (in frames) and frequency of each cycle
|
xue@1
|
261
|
xue@1
|
262 No return value.
|
xue@1
|
263 */
|
xue@1
|
264 void AnalyzeSF(THS& HS, TSF& SF, double*& cyclefrs, double*& cyclefs, double sps, double offst, int* cyclefrcount,
|
xue@1
|
265 int SFMode, double SFF, int SFFScale, double SFtheta)
|
xue@1
|
266 {
|
xue@1
|
267 AnalyzeSF_1(HS, SF, sps, offst);
|
xue@1
|
268 AnalyzeSF_2(HS, SF, cyclefrs, cyclefs, sps, cyclefrcount, SFMode, SFF, SFFScale, SFtheta);
|
xue@1
|
269 }//AnalyzeSF
|
xue@1
|
270
|
Chris@5
|
271 /**
|
xue@1
|
272 function AnalyzeSF_1: first stage of source-filter model estimation, in which the duration of a HS is
|
xue@1
|
273 segmented into what is equivalent to "cycles" in vibrato analysis.
|
xue@1
|
274
|
xue@1
|
275 In: HS: a harmonic sinusoid
|
xue@1
|
276 sps: sampling rate ("samples per second")
|
xue@1
|
277 offst: hop size, the interval between adjacent harmonic atoms of HS
|
xue@1
|
278 Out: SF: a TSF object partially updated, particularly lp[P].
|
xue@1
|
279
|
xue@1
|
280 No return value.
|
xue@1
|
281 */
|
xue@1
|
282 void AnalyzeSF_1(THS& HS, TSF& SF, double sps, double offst)
|
xue@1
|
283 {
|
xue@1
|
284 int M=HS.M, Fr=HS.Fr;
|
xue@1
|
285 if (M<=0 || Fr<=0) return;
|
xue@1
|
286 atom** Partials=HS.Partials;
|
xue@1
|
287
|
xue@1
|
288 //basic descriptor: offst
|
xue@1
|
289 SF.offst=offst;
|
xue@1
|
290
|
xue@1
|
291 //demodulating pitch
|
xue@1
|
292 //Basic descriptor: L
|
xue@1
|
293 SF.AllocateL(Fr);
|
xue@1
|
294
|
xue@1
|
295 double* A0=SF.logA0;
|
xue@1
|
296 //find the amplitude and pitch tracks
|
xue@1
|
297 SF.F0max=0, SF.F0min=1;
|
xue@1
|
298 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
299 {
|
xue@1
|
300 double suma2=0, suma2p=0;
|
xue@1
|
301 for (int m=0; m<M; m++)
|
xue@1
|
302 {
|
xue@1
|
303 double a=Partials[m][fr].a, p=Partials[m][fr].f/(m+1);
|
xue@1
|
304 if (p<=0) break;
|
xue@1
|
305 suma2+=a*a, suma2p+=a*a*p;
|
xue@1
|
306 }
|
xue@1
|
307 SF.F0[fr]=suma2p/suma2;
|
xue@1
|
308 if (SF.F0max<SF.F0[fr]) SF.F0max=SF.F0[fr];
|
xue@1
|
309 if (SF.F0min>SF.F0[fr]) SF.F0min=SF.F0[fr];
|
xue@1
|
310 A0[fr]=suma2;
|
xue@1
|
311 }
|
xue@1
|
312
|
xue@1
|
313 //Basic descriptor: M
|
xue@1
|
314 SF.M=0.45/SF.F0max;
|
xue@1
|
315 if (SF.M>M) SF.M=M;
|
xue@1
|
316
|
xue@1
|
317 //rough estimation of rate
|
xue@1
|
318 double* f0d=new double[Fr-1]; for (int i=0; i<Fr-1; i++) f0d[i]=SF.F0[i+1]-SF.F0[i];
|
xue@1
|
319 RateAndReg(SF.rate, SF.regularity, f0d, 0, Fr-2, 8, sps, offst);
|
xue@1
|
320 delete[] f0d;
|
xue@1
|
321 //find peaks of the pitch track
|
xue@1
|
322 int* peakfr=new int[Fr/2];
|
xue@1
|
323 double periodinframe=sps/(SF.rate*offst), *dummy=(double*)0xFFFFFFFF;
|
xue@1
|
324 FindPeaks(peakfr, SF.P, SF.F0, Fr, periodinframe, dummy);
|
xue@1
|
325 //Basic descriptor: lp[]
|
xue@1
|
326 SF.AllocateP();
|
xue@1
|
327 for (int p=0; p<SF.P; p++)
|
xue@1
|
328 {
|
xue@1
|
329 double startfr; QIE(&SF.F0[peakfr[p]], startfr); SF.lp[p]=startfr+peakfr[p];
|
xue@1
|
330 }
|
xue@1
|
331 delete[] peakfr;
|
xue@1
|
332 }//AnalyzeSF_1
|
xue@1
|
333
|
Chris@5
|
334 /**
|
xue@1
|
335 function AnalyzeSF_2: second stage of source-filter model estimation, in which the HS is demodulated
|
xue@1
|
336 and its source-filter model is estimated.
|
xue@1
|
337
|
xue@1
|
338 In: HS: a harmonic sinusoid
|
xue@1
|
339 SF: a TSF object with valid segmentation data (lp[P]) of HS
|
xue@1
|
340 sps: sampling rate ("samples per second")
|
xue@1
|
341 SFMode: specifies source-filter estimation criterion, 0=FB (filter bank), 1=SV (slow variation)
|
xue@1
|
342 SFF: filter response sampling interval
|
xue@1
|
343 SFScale: set if filter sampling uses mel scale
|
xue@1
|
344 SFtheta: balancing factor of amplitude and frequency variations, needed for SV approach
|
xue@1
|
345 Out: SF: the TSF object fully estimated.
|
xue@1
|
346 cyclefrcount: number of cycles
|
xue@1
|
347 cyclefrs[cyclefrcount], cyclefs[cyclefrcount]: average time (in frames) and frequency of each cycle
|
xue@1
|
348
|
xue@1
|
349 No return value.
|
xue@1
|
350 */
|
xue@1
|
351 void AnalyzeSF_2(THS& HS, TSF& SF, double*& cyclefrs, double*& cyclefs, double sps, int* cyclefrcount,
|
xue@1
|
352 int SFMode, double SFF, int SFFScale, double SFtheta)
|
xue@1
|
353 {
|
xue@1
|
354 int M=HS.M, Fr=HS.Fr;
|
xue@1
|
355 if (M<=0 || Fr<=0) return;
|
xue@1
|
356 atom** Partials=HS.Partials;
|
xue@1
|
357
|
xue@1
|
358 if (SF.P>=1) //de-modulation
|
xue@1
|
359 {
|
xue@1
|
360 //Basic descriptor: F0C[]
|
xue@1
|
361 DeFM(SF.F0C, SF.F0, SF.logA0, SF.P, SF.lp, Fr, SF.F0Overall, *cyclefrcount, cyclefrs, cyclefs);
|
xue@1
|
362 //Basic descriptor: A0C[]
|
xue@1
|
363 double *A0C=SF.logA0C, *logA0C=SF.logA0C, *logA0D=SF.logA0D, *logA0=SF.logA0;
|
xue@1
|
364 DeAM(A0C, SF.logA0, SF.P, SF.lp, Fr);
|
xue@1
|
365 for (int fr=0; fr<Fr; fr++) logA0C[fr]=log(A0C[fr]);
|
xue@1
|
366 //Basic descriptor: logA0D[]
|
xue@1
|
367 int hM=M/2;
|
xue@1
|
368 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
369 {
|
xue@1
|
370 double loga0d=0;
|
xue@1
|
371 for (int m=0; m<hM; m++) loga0d+=log(Partials[m][fr].a);
|
xue@1
|
372 logA0[fr]=loga0d/hM;
|
xue@1
|
373 logA0D[fr]=logA0[fr]-logA0C[fr];
|
xue@1
|
374 }
|
xue@1
|
375 }
|
xue@1
|
376 //Basic descriptor: F0D[]
|
xue@1
|
377 SF.F0Cmax=0; SF.F0Dmax=-1; SF.F0Cmin=1; SF.F0Dmin=1;
|
xue@1
|
378 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
379 {
|
xue@1
|
380 if (SF.F0Cmax<SF.F0C[fr]) SF.F0Cmax=SF.F0C[fr];
|
xue@1
|
381 if (SF.F0Cmin>SF.F0C[fr]) SF.F0Cmin=SF.F0C[fr];
|
xue@1
|
382 SF.F0D[fr]=SF.F0[fr]-SF.F0C[fr];
|
xue@1
|
383 }
|
xue@1
|
384
|
xue@1
|
385 //Basic descriptor: b, h
|
xue@1
|
386 //Source-filter modeling
|
xue@1
|
387 {
|
xue@1
|
388 SF.F=SFF; SF.Fs=sps; SF.AllocateSF();
|
xue@1
|
389 int M=SF.M; double **h=SF.h, **b=SF.b;// *avgh=SF.avgh, *avgb=SF.avgb;
|
xue@1
|
390
|
xue@1
|
391 double *logA0C=useA0?SF.logA0:SF.logA0C;
|
xue@1
|
392 if (SFMode==0){
|
xue@1
|
393 S_F_FB(M, Partials, logA0C, SF.lp, SF.P, SF.K, h, SF.avgh, b, SF.avgb, SFF, SFFScale, sps);}
|
xue@1
|
394 else if (SFMode==1){
|
xue@1
|
395 S_F_SV(M, Partials, logA0C, SF.lp, SF.P, SF.K, h, SF.avgh, b, SF.avgb, SFF, SFFScale, SFtheta, sps);}
|
xue@1
|
396
|
xue@1
|
397 SF.FScaleMode=SFFScale;
|
xue@1
|
398 // int K=SF.K, effL=ceil(SF.lp[SF.P-1])-ceil(SF.lp[0]);
|
xue@1
|
399 // for (int k=0; k<K+2; k++){double sumh=0; for (int l=0; l<effL; l++) sumh+=h[l][k]; avgh[k]=sumh/effL;}
|
xue@1
|
400 // for (int m=0; m<M; m++){double sumb=0; for (int l=0; l<effL; l++) sumb+=b[l][m]; avgb[m]=sumb/effL;}
|
xue@1
|
401 }
|
xue@1
|
402 }//AnalyzeSF_2
|
xue@1
|
403
|
Chris@5
|
404 /**
|
xue@1
|
405 function I3: integrates the product of 3 linear functions (0, a*)-(T, b*) (*=1, 2 or 3) over (0, T).
|
xue@1
|
406 See "further reading", pp.12 eq.(37).
|
xue@1
|
407
|
xue@1
|
408 In: T, a1, a2, a3, b1, b2, b3
|
xue@1
|
409
|
xue@1
|
410 Returns the definite integral.
|
xue@1
|
411 */
|
xue@1
|
412 double I3(double T, double a1, double a2, double a3, double b1, double b2, double b3)
|
xue@1
|
413 {
|
xue@1
|
414 return T*(a1*(a2*(3*a3+b3)+b2*(a3+b3))+b1*(a2*(a3+b3)+b2*(a3+3*b3)))/12;
|
xue@1
|
415 }//I3
|
xue@1
|
416
|
Chris@5
|
417 /**
|
xue@1
|
418 function P_Ax: calculate the 2-D vector Ax for a given x, where A is a matrix hosting the parabolic
|
xue@1
|
419 coefficient of filter coefficients x[L][K+2] towards the totoal variation. See "further reading",
|
xue@1
|
420 pp.8, (29a).
|
xue@1
|
421
|
xue@1
|
422 In: x[L][K+2]: filter coefficients
|
xue@1
|
423 f[L][M]: partial frequencies
|
xue@1
|
424 F: filter response sampling interval
|
xue@1
|
425 theta: balancing factor of amplitude and frequency variations
|
xue@1
|
426 Out: d[L][K+2]: Ax.
|
xue@1
|
427
|
xue@1
|
428 Returns inner product of x[][] and d[][].
|
xue@1
|
429 */
|
xue@1
|
430 double P_Ax(double** d, int L, int M, int K, double** x, double** f, double F, double theta)
|
xue@1
|
431 {
|
xue@1
|
432 double **dFtr=d;
|
xue@1
|
433 Alloc2(L, K+2, dSrc);
|
xue@1
|
434 double DelFtr=P2_DelFtr(dFtr, L, K, x, F);
|
xue@1
|
435 double DelSrc=P3_DelSrc(dSrc, L, M, K, x, f, F);
|
xue@1
|
436 Multiply(L, K+2, dFtr, dFtr, (1-theta)/F);
|
xue@1
|
437 MultiAdd(L, K+2, d, dFtr, dSrc, theta);
|
xue@1
|
438 DeAlloc2(dSrc);
|
xue@1
|
439 return DelFtr*(1-theta)/F+DelSrc*theta;
|
xue@1
|
440 }//P_Ax
|
xue@1
|
441
|
Chris@5
|
442 /**
|
xue@1
|
443 function P_Ax_cf: calculate the 2-D vector Ax for a given x, where A is a matrix hosting the parabolic
|
xue@1
|
444 coefficient of time-unvarying filter coefficients x[K+2] towards totoal source variation.
|
xue@1
|
445
|
xue@1
|
446 In: x[K+2]: filter coefficients
|
xue@1
|
447 f[L][M]: partial frequencies
|
xue@1
|
448 F: filter response sampling interval
|
xue@1
|
449 Out: d[K+2]: Ax.
|
xue@1
|
450
|
xue@1
|
451 Returns inner product of x[] and d[].
|
xue@1
|
452 */
|
xue@1
|
453 double P_Ax_cf(double* d, int L, int M, int K, double* x, double** f, double F)
|
xue@1
|
454 {
|
xue@1
|
455 double xAx=0;
|
xue@1
|
456 for (int l=0; l<L; l++) memset(d, 0, sizeof(double)*(K+2));
|
xue@1
|
457 for (int l=0; l<L-1; l++)
|
xue@1
|
458 for (int m=0; m<M; m++)
|
xue@1
|
459 {
|
xue@1
|
460 double f0f=f[l][m]/F, f1f=f[l+1][m]/F;
|
xue@1
|
461 if (f0f<=0 || f1f<=0) continue;
|
xue@1
|
462 int k0=floor(f0f), k1=floor(f1f);
|
xue@1
|
463 double f0=f0f-k0, f1=f1f-k1;
|
xue@1
|
464 double g0=1-f0, g1=1-f1;
|
xue@1
|
465 double A=-x[k1]*g1-x[k1+1]*f1+x[k0]*g0+x[k0+1]*f0;
|
xue@1
|
466 d[k1]-=2*A*g1;
|
xue@1
|
467 d[k1+1]-=2*A*f1;
|
xue@1
|
468 d[k0]+=2*A*g0;
|
xue@1
|
469 d[k0+1]+=2*A*f0;
|
xue@1
|
470 xAx+=A*A;
|
xue@1
|
471 }
|
xue@1
|
472 return xAx;
|
xue@1
|
473 }//P_Ax_cf
|
xue@1
|
474
|
Chris@5
|
475 /**
|
xue@1
|
476 function P1_b: internal procedure P1 of slow-variation SF estimator. See "further reading", pp.8.
|
xue@1
|
477
|
xue@1
|
478 In: a[L][M], f[L][M]: partial amplitudes and frequencies
|
xue@1
|
479 F: filter response sampling interval
|
xue@1
|
480 theta: balancing factor of amplitude and frequency variations
|
xue@1
|
481 Out: b[L][K+2]: linear coefficients of filter coefficients h[L][K+2] towards the total variation.
|
xue@1
|
482
|
xue@1
|
483 No return value.
|
xue@1
|
484 */
|
xue@1
|
485 void P1_b(double** b, int L, int M, int K, double** a, double** f, double F, double theta)
|
xue@1
|
486 {
|
xue@1
|
487 for (int l=0; l<L; l++) memset(b[l], 0, sizeof(double)*(K+2));
|
xue@1
|
488 for (int l=0; l<L-1; l++)
|
xue@1
|
489 {
|
xue@1
|
490 for (int m=0; m<M; m++)
|
xue@1
|
491 {
|
xue@1
|
492 double f0f=f[l][m]/F, f1f=f[l+1][m]/F;
|
xue@1
|
493 if (f0f<=0 || f1f<=0) continue;
|
xue@1
|
494 int k0=floor(f0f), k1=floor(f1f);
|
xue@1
|
495 double f0=f0f-k0, f1=f1f-k1;
|
xue@1
|
496 double g0=1-f0, g1=1-f1;
|
xue@1
|
497 double delta=a[l+1][m]-a[l][m];
|
xue@1
|
498 b[l+1][k1]+=g1*delta, b[l+1][k1+1]+=f1*delta;
|
xue@1
|
499 b[l][k0]-=g0*delta, b[l][k0+1]-=f0*delta;
|
xue@1
|
500 }
|
xue@1
|
501 }
|
xue@1
|
502 Multiply(L, K+2, b, b, theta);
|
xue@1
|
503 }//P1_b
|
xue@1
|
504
|
Chris@5
|
505 /**
|
xue@1
|
506 function P1_b_cf: internal procedure P1 of slow-variation SF estimator, constant-filter version.
|
xue@1
|
507
|
xue@1
|
508 In: a[L][M], f[L][M]: partial amplitudes and frequencies
|
xue@1
|
509 F: filter response sampling interval
|
xue@1
|
510 Out: b[K+2]: linear coefficients of filter coefficients h[K+2] towards total source variation.
|
xue@1
|
511
|
xue@1
|
512 No return value.
|
xue@1
|
513 */
|
xue@1
|
514 void P1_b_cf(double* b, int L, int M, int K, double** a, double** f, double F)
|
xue@1
|
515 {
|
xue@1
|
516 memset(b, 0, sizeof(double)*(K+2));
|
xue@1
|
517 for (int l=0; l<L-1; l++)
|
xue@1
|
518 {
|
xue@1
|
519 for (int m=0; m<M; m++)
|
xue@1
|
520 {
|
xue@1
|
521 double f0f=f[l][m]/F, f1f=f[l+1][m]/F;
|
xue@1
|
522 if (f0f<=0 || f1f<=0) continue;
|
xue@1
|
523 int k0=floor(f0f), k1=floor(f1f);
|
xue@1
|
524 double f0=f0f-k0, f1=f1f-k1;
|
xue@1
|
525 double g0=1-f0, g1=1-f1;
|
xue@1
|
526 double delta=a[l+1][m]-a[l][m];
|
xue@1
|
527 b[k1]+=g1*delta, b[k1+1]+=f1*delta;
|
xue@1
|
528 b[k0]-=g0*delta, b[k0+1]-=f0*delta;
|
xue@1
|
529 }
|
xue@1
|
530 }
|
xue@1
|
531 Multiply(K+2, b, b, 2);
|
xue@1
|
532 }//P1_b_cf
|
xue@1
|
533
|
Chris@5
|
534 /**
|
xue@1
|
535 function P2_DelFtr: internal procedure P2 of slow-variation SF estimator. See "further reading", pp.8.
|
xue@1
|
536
|
xue@1
|
537 In: x[L][K+2]: filter coefficients
|
xue@1
|
538 F: filter response sampling interval
|
xue@1
|
539 Out: d[L][K+2]: derivative of total filter variation against filter coefficients.
|
xue@1
|
540
|
xue@1
|
541 Returns the inner product of x[][] and d[][].
|
xue@1
|
542 */
|
xue@1
|
543 double P2_DelFtr(double** d, int L, int K, double** x, double F)
|
xue@1
|
544 {
|
xue@1
|
545 double xAx=0;
|
xue@1
|
546 for (int l=0; l<L; l++) memset(d[l], 0, sizeof(double)*(K+2));
|
xue@1
|
547 for (int l=0; l<L-1; l++)
|
xue@1
|
548 for (int k=0; k<K+1; k++)
|
xue@1
|
549 {
|
xue@1
|
550 try{
|
xue@1
|
551 double A0=x[l+1][k]-x[l][k], A1=x[l+1][k+1]-x[l][k+1];
|
xue@1
|
552 d[l+1][k]+=(2*A0+A1);
|
xue@1
|
553 d[l][k]-=(2*A0+A1);
|
xue@1
|
554 d[l+1][k+1]+=(2*A1+A0);
|
xue@1
|
555 d[l][k+1]-=(2*A1+A0);
|
xue@1
|
556 xAx+=A0*A0+A1*A1+A0*A1;
|
xue@1
|
557 }
|
xue@1
|
558 catch(...){}
|
xue@1
|
559 }
|
xue@1
|
560 Multiply(L, K+2, d, d, F/3);
|
xue@1
|
561 return xAx*F/3;
|
xue@1
|
562 }//P2_DelFtr
|
xue@1
|
563
|
Chris@5
|
564 /**
|
xue@1
|
565 function P3_DelSec: internal procedure P3 of slow-variation SF estimator. See "further reading", pp.9.
|
xue@1
|
566
|
xue@1
|
567 In: x[L][K+2]: filter coefficients
|
xue@1
|
568 f[L][M]: partial frequencies
|
xue@1
|
569 F: filter response sampling interval
|
xue@1
|
570 Out: d[L][K+2]: derivative of total source variation against filter coefficients.
|
xue@1
|
571
|
xue@1
|
572 Returns the inner product of x[][] and d[][].
|
xue@1
|
573 */
|
xue@1
|
574 double P3_DelSrc(double** d, int L, int M, int K, double** x, double** f, double F)
|
xue@1
|
575 {
|
xue@1
|
576 double xAx=0;
|
xue@1
|
577 for (int l=0; l<L; l++) memset(d[l], 0, sizeof(double)*(K+2));
|
xue@1
|
578 for (int l=0; l<L-1; l++)
|
xue@1
|
579 for (int m=0; m<M; m++)
|
xue@1
|
580 {
|
xue@1
|
581 double f0f=f[l][m]/F, f1f=f[l+1][m]/F;
|
xue@1
|
582 if (f0f<=0 || f1f<=0) continue;
|
xue@1
|
583 int k0=floor(f0f), k1=floor(f1f);
|
xue@1
|
584 double f0=f0f-k0, f1=f1f-k1;
|
xue@1
|
585 double g0=1-f0, g1=1-f1;
|
xue@1
|
586 double A=-x[l+1][k1]*g1-x[l+1][k1+1]*f1+x[l][k0]*g0+x[l][k0+1]*f0;
|
xue@1
|
587 d[l+1][k1]-=2*A*g1;
|
xue@1
|
588 d[l+1][k1+1]-=2*A*f1;
|
xue@1
|
589 d[l][k0]+=2*A*g0;
|
xue@1
|
590 d[l][k0+1]+=2*A*f0;
|
xue@1
|
591 xAx+=A*A;
|
xue@1
|
592 }
|
xue@1
|
593 return xAx;
|
xue@1
|
594 }//P3_DelSec
|
xue@1
|
595
|
Chris@5
|
596 /**
|
xue@1
|
597 function S_F_b: computes source coefficients given amplitudes and filter coefficients
|
xue@1
|
598
|
xue@1
|
599 In: Partials[M][Fr]: HS partials. Fr is not specified but is assumed no less then lp[P-1].
|
xue@1
|
600 lp[P]: temporal segmentation points, in frames.
|
xue@1
|
601 logA0C[Fr]: amplitude carrier
|
xue@1
|
602 h[L][K+2]: filter coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]).
|
xue@1
|
603 F: filter response sampling interval
|
xue@1
|
604 FScaleMode: set if mel scale is used as frequency scale
|
xue@1
|
605 Fs: sampling frequency, effective only when FScaleMode is set.
|
xue@1
|
606 Out: b[L][M]: source coefficients for L frames starting from ceil(lp[0]).
|
xue@1
|
607 avgb[L]: average source coefficents for these L frames
|
xue@1
|
608
|
xue@1
|
609 No return value.
|
xue@1
|
610 */
|
xue@1
|
611 void S_F_b(int M, atom** Partials, double* logA0C, double* lp, int P, int K, double** h, double** b, double* avgb, double F, int FScaleMode, double Fs)
|
xue@1
|
612 {
|
xue@1
|
613 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
614 int L=lpp-lp0;
|
xue@1
|
615 for (int l=0; l<L; l++)
|
xue@1
|
616 {
|
xue@1
|
617 int fr=lp0+l;
|
xue@1
|
618 double loga0=logA0C[fr];
|
xue@1
|
619 for (int m=0; m<M; m++)
|
xue@1
|
620 {
|
xue@1
|
621 double f=Partials[m][fr].f;
|
xue@1
|
622 if (FScaleMode) f=log(1+f*Fs/700)/log(1+Fs/700);
|
xue@1
|
623 if (f>0)
|
xue@1
|
624 {
|
xue@1
|
625 double loga=log(Partials[m][fr].a);
|
xue@1
|
626 loga-=loga0;
|
xue@1
|
627 double ff=f/F;
|
xue@1
|
628 int klm=floor(ff);
|
xue@1
|
629 double f0=ff-klm;
|
xue@1
|
630 double hlm=h[l][klm]*(1-f0)+h[l][klm+1]*f0;
|
xue@1
|
631 b[l][m]=loga-hlm;
|
xue@1
|
632 }
|
xue@1
|
633 else b[l][m]=-100;
|
xue@1
|
634 }
|
xue@1
|
635 }
|
xue@1
|
636 // for (int k=0; k<K+2; k++){avgh[k]=0; for (int l=0; l<L; l++) avgh[k]+=h[l][k]; avgh[k]/=L;}
|
xue@1
|
637 for (int m=0; m<M; m++){avgb[m]=0; for (int l=0; l<L; l++) avgb[m]+=b[l][m]; avgb[m]/=L;}
|
xue@1
|
638 }//S_F_b
|
xue@1
|
639
|
Chris@5
|
640 /**
|
xue@1
|
641 function S_F_b: wrapper function
|
xue@1
|
642
|
xue@1
|
643 In: Partials: HS partials
|
xue@1
|
644 SF: TSF object containing valid filter coefficients
|
xue@1
|
645 Out: SF: TSF object with source coefficients updated
|
xue@1
|
646
|
xue@1
|
647 No return value.
|
xue@1
|
648 */
|
xue@1
|
649 void S_F_b(TSF& SF, atom** Partials)
|
xue@1
|
650 {
|
xue@1
|
651 S_F_b(SF.M, Partials, useA0?SF.logA0:SF.logA0C, SF.lp, SF.P, SF.K, SF.h, SF.b, SF.avgb, SF.F, SF.FScaleMode, SF.Fs);
|
xue@1
|
652 }//S_F_b
|
xue@1
|
653
|
Chris@5
|
654 /**
|
xue@1
|
655 function S_F_b: filter-bank method for estimating source-filter model. This is a wrapper function of
|
xue@1
|
656 SF_FB() that transfers and scales values, etc.
|
xue@1
|
657
|
xue@1
|
658 In: Partials[M][Fr]: HS partials. Fr is not specified but is assumed no less then lp[P-1].
|
xue@1
|
659 lp[P]: temporal segmentation points, in frames.
|
xue@1
|
660 logA0C[Fr]: amplitude carrier
|
xue@1
|
661 F: filter response sampling interval
|
xue@1
|
662 FScaleMode: set if mel scale is used as frequency scale
|
xue@1
|
663 Fs: sampling frequency, effective only when FScaleMode is set.
|
xue@1
|
664 Out: K
|
xue@1
|
665 h[L][K+2], aveh[K+2]: filter coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
666 b[L][M], avgb[M]: source coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
667
|
xue@1
|
668 Returns 0.
|
xue@1
|
669 */
|
xue@1
|
670 double S_F_FB(int M, atom** Partials, double* logA0C, double* lp, int P, int& K, double** h, double* avgh, double** b, double* avgb, double F, int FScaleMode, double Fs)
|
xue@1
|
671 {
|
xue@1
|
672 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
673 int L=lpp-lp0;
|
xue@1
|
674 Alloc2(L, M, a); Alloc2(L, M, f);
|
xue@1
|
675 double fmax=0;
|
xue@1
|
676 for (int l=0; l<L; l++)
|
xue@1
|
677 {
|
xue@1
|
678 int fr=lp0+l;
|
xue@1
|
679 double ia0c=exp(-logA0C[fr]);
|
xue@1
|
680 for (int m=0; m<M; m++)
|
xue@1
|
681 {
|
xue@1
|
682 f[l][m]=Partials[m][fr].f;
|
xue@1
|
683 if (FScaleMode) f[l][m]=log(1+f[l][m]*Fs/700)/log(1+Fs/700);
|
xue@1
|
684 if (f[l][m]>0) a[l][m]=Partials[m][fr].a*ia0c; //log(Partials[m][fr].a);
|
xue@1
|
685 else a[l][m]=0;
|
xue@1
|
686 if (fmax<f[l][m]) fmax=f[l][m];
|
xue@1
|
687 }
|
xue@1
|
688 }
|
xue@1
|
689 K=floor(fmax/F);
|
xue@1
|
690
|
xue@1
|
691
|
xue@1
|
692 SF_FB(h[0], M, K, &a[0], &f[0], F, 1);
|
xue@1
|
693 for (int l=1; l<L-1; l++) SF_FB(h[l], M, K, &a[l], &f[l], F, 0);
|
xue@1
|
694 SF_FB(h[L-1], M, K, &a[L-1], &f[L-1], F, -1);
|
xue@1
|
695
|
xue@1
|
696 for (int l=0; l<L; l++)
|
xue@1
|
697 for (int m=0; m<M; m++)
|
xue@1
|
698 {
|
xue@1
|
699 double ff=f[l][m]/F;
|
xue@1
|
700 if (ff<=0) b[l][m]=-100;
|
xue@1
|
701 else
|
xue@1
|
702 {
|
xue@1
|
703 int klm=floor(ff);
|
xue@1
|
704 double f0=ff-klm;
|
xue@1
|
705 double hlm=h[l][klm]*(1-f0)+h[l][klm+1]*f0;
|
xue@1
|
706 b[l][m]=log(a[l][m])-hlm;
|
xue@1
|
707 }
|
xue@1
|
708 }
|
xue@1
|
709
|
xue@1
|
710 for (int k=0; k<K+2; k++){avgh[k]=0; for (int l=0; l<L; l++) avgh[k]+=h[l][k]; avgh[k]/=L;}
|
xue@1
|
711 for (int m=0; m<M; m++){avgb[m]=0; for (int l=0; l<L; l++) avgb[m]+=b[l][m]; avgb[m]/=L;}
|
xue@1
|
712
|
xue@1
|
713 DeAlloc2(a); DeAlloc2(f);
|
xue@1
|
714 return 0;
|
xue@1
|
715 }//S_F_b
|
xue@1
|
716
|
Chris@5
|
717 /**
|
xue@1
|
718 function S_F_SV: slow-variation method for estimating source-filter model. This is a wrapper function
|
xue@1
|
719 of SF_SV() that transfers and scales values, etc.
|
xue@1
|
720
|
xue@1
|
721 In: Partials[M][Fr]: HS partials. Fr is not specified but is assumed no less then lp[P-1].
|
xue@1
|
722 lp[P]: temporal segmentation points, in frames.
|
xue@1
|
723 logA0C[Fr]: amplitude carrier
|
xue@1
|
724 theta: balancing factor of amplitude and frequency variations
|
xue@1
|
725 F: filter response sampling interval
|
xue@1
|
726 FScaleMode: set if mel scale is used as frequency scale
|
xue@1
|
727 Fs: sampling frequency, effective only when FScaleMode is set.
|
xue@1
|
728 Out: K
|
xue@1
|
729 h[L][K+2], aveh[K+2]: filter coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
730 b[L][M], avgb[M]: source coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
731 Returns 0.
|
xue@1
|
732 */
|
xue@1
|
733 double S_F_SV(int M, atom** Partials, double* logA0C, double* lp, int P, int& K, double** h, double* avgh, double** b, double* avgb, double F, int FScaleMode, double theta, double Fs)
|
xue@1
|
734 {
|
xue@1
|
735 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
736 int L=lpp-lp0;
|
xue@1
|
737 Alloc2(L, M, loga); Alloc2(L, M, f);
|
xue@1
|
738 double fmax=0;
|
xue@1
|
739 for (int l=0; l<L; l++)
|
xue@1
|
740 {
|
xue@1
|
741 int fr=lp0+l;
|
xue@1
|
742 for (int m=0; m<M; m++)
|
xue@1
|
743 {
|
xue@1
|
744 f[l][m]=Partials[m][fr].f;
|
xue@1
|
745 if (FScaleMode) f[l][m]=log(1+f[l][m]*Fs/700)/log(1+Fs/700);
|
xue@1
|
746 if (f[l][m]>0) loga[l][m]=log(Partials[m][fr].a);
|
xue@1
|
747 else loga[l][m]=-100;
|
xue@1
|
748 if (fmax<f[l][m]) fmax=f[l][m];
|
xue@1
|
749 }
|
xue@1
|
750 }
|
xue@1
|
751 K=floor(fmax/F);
|
xue@1
|
752
|
xue@1
|
753 for (int l=0; l<L; l++){double loga0=logA0C[lp0+l]; for (int m=0; m<M; m++) loga[l][m]-=loga0;}
|
xue@1
|
754
|
xue@1
|
755 SF_SV(h, L, M, K, loga, f, F, theta, 1e-6, L*(K+2));
|
xue@1
|
756
|
xue@1
|
757 for (int l=0; l<L; l++)
|
xue@1
|
758 for (int m=0; m<M; m++)
|
xue@1
|
759 {
|
xue@1
|
760 double ff=f[l][m]/F;
|
xue@1
|
761 if (ff<=0) continue;
|
xue@1
|
762 int klm=floor(ff);
|
xue@1
|
763 double f0=ff-klm;
|
xue@1
|
764 double hlm=h[l][klm]*(1-f0)+h[l][klm+1]*f0;
|
xue@1
|
765 b[l][m]=loga[l][m]-hlm;
|
xue@1
|
766 }
|
xue@1
|
767
|
xue@1
|
768 for (int k=0; k<K+2; k++){avgh[k]=0; for (int l=0; l<L; l++) avgh[k]+=h[l][k]; avgh[k]/=L;}
|
xue@1
|
769 for (int m=0; m<M; m++){avgb[m]=0; for (int l=0; l<L; l++) avgb[m]+=b[l][m]; avgb[m]/=L;}
|
xue@1
|
770
|
xue@1
|
771 DeAlloc2(loga); DeAlloc2(f);
|
xue@1
|
772 return 0;
|
xue@1
|
773 }//S_F_SV
|
xue@1
|
774
|
Chris@5
|
775 /**
|
xue@1
|
776 function S_F_SV_cf: slow-variation method for estimating source-(constant)filter model. This is a
|
xue@1
|
777 wrapper function of SF_SV_cf() that transfers and scales values, as well as converting results to
|
xue@1
|
778 source filter format used by the vibrato class TVo.
|
xue@1
|
779
|
xue@1
|
780 In: Partials[M][Fr]: HS partials. Fr is not specified but is assumed no less then lp[P-1].
|
xue@1
|
781 lp[P]: temporal segmentation points, in frames.
|
xue@1
|
782 A0C[Fr]: amplitude carrier (linear, not dB)
|
xue@1
|
783 F: filter response sampling interval
|
xue@1
|
784 FScaleMode: set if mel scale is used as frequency scale
|
xue@1
|
785 Fs: sampling frequency, effective only when FScaleMode is set.
|
xue@1
|
786 Out: K
|
xue@1
|
787 h[L][K+2], aveh[K+2]: filter coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
788 b[L][M], avgb[M]: source coefficients for L frames from ceil(lp[0]) to ceil(lp[P-1]), and their averages
|
xue@1
|
789 LogAF[afres/2]: TVo-format filter response
|
xue@1
|
790 LogAS[M]: TVo-format source response
|
xue@1
|
791
|
xue@1
|
792 Returns 0.
|
xue@1
|
793 */
|
xue@1
|
794 double S_F_SV_cf(int afres, double* LogAF, double* LogAS, int Fr, int M, atom** Partials, double* A0C, double* lp, int P, int& K, double** h, double** b, double F, int FScaleMode, double Fs)
|
xue@1
|
795 {
|
xue@1
|
796 int lp0=ceil(lp[0]), lpp=ceil(lp[P-1]);
|
xue@1
|
797 int L=lpp-lp0;
|
xue@1
|
798 Alloc2(L, M, loga); Alloc2(L, M, f);
|
xue@1
|
799 double fmax=0;
|
xue@1
|
800 for (int l=0; l<L; l++)
|
xue@1
|
801 {
|
xue@1
|
802 int fr=lp0+l;
|
xue@1
|
803 for (int m=0; m<M; m++)
|
xue@1
|
804 {
|
xue@1
|
805 try{
|
xue@1
|
806 f[l][m]=Partials[m][fr].f;
|
xue@1
|
807 }
|
xue@1
|
808 catch(...)
|
xue@1
|
809 {
|
xue@1
|
810 m=m;
|
xue@1
|
811 }
|
xue@1
|
812 if (FScaleMode) f[l][m]=log(1+f[l][m]*Fs/700)/log(1+Fs/700);
|
xue@1
|
813 if (f[l][m]>0) loga[l][m]=log(Partials[m][fr].a);
|
xue@1
|
814 else loga[l][m]=-100;
|
xue@1
|
815 if (fmax<f[l][m]) fmax=f[l][m];
|
xue@1
|
816 }
|
xue@1
|
817 }
|
xue@1
|
818 K=floor(fmax/F);
|
xue@1
|
819
|
xue@1
|
820 SF_SV_cf(h[0], b, L, M, K, loga, f, F, 1e-6, K+2);
|
xue@1
|
821 for (int l=0; l<L; l++)
|
xue@1
|
822 {
|
xue@1
|
823 if (l>0) memcpy(h[l], h[0], sizeof(double)*(K+2));
|
xue@1
|
824 double loga0=log(A0C[l]);
|
xue@1
|
825 for (int m=0; m<M; m++) b[l][m]-=loga0;
|
xue@1
|
826 }
|
xue@1
|
827
|
xue@1
|
828 double* lh=new double[K+2]; memset(lh, 0, sizeof(double)*(K+2));
|
xue@1
|
829 for (int k=0; k<K+2; k++)
|
xue@1
|
830 {
|
xue@1
|
831 for (int l=0; l<L; l++) lh[k]+=h[l][k];
|
xue@1
|
832 lh[k]/=L;
|
xue@1
|
833 }
|
xue@1
|
834 for (int i=0; i<afres/2; i++)
|
xue@1
|
835 {
|
xue@1
|
836 double freq=i*1.0/afres;
|
xue@1
|
837 if (FScaleMode) freq=log(1+freq*Fs/700)/log(1+Fs/700);
|
xue@1
|
838 int k=floor(freq/F);
|
xue@1
|
839 double f_plus=freq/F-k;
|
xue@1
|
840 if (k<K+1) LogAF[i]=lh[k]*(1-f_plus)+lh[k+1]*f_plus;
|
xue@1
|
841 else LogAF[i]=lh[K+1];
|
xue@1
|
842 }
|
xue@1
|
843 delete[] lh;
|
xue@1
|
844
|
xue@1
|
845 for (int m=0; m<M; m++)
|
xue@1
|
846 {
|
xue@1
|
847 int ccount=0;
|
xue@1
|
848 for (int fr=lp0; fr<lpp; fr++)
|
xue@1
|
849 {
|
xue@1
|
850 double f=Partials[m][fr].f*afres;
|
xue@1
|
851 if (f<=0) continue;
|
xue@1
|
852 int intf=floor(f);
|
xue@1
|
853 LogAS[m]=LogAS[m]+log(Partials[m][fr].a/A0C[fr])-(LogAF[intf]*(intf+1-f)+LogAF[intf+1]*(f-intf));
|
xue@1
|
854 ccount++;
|
xue@1
|
855 }
|
xue@1
|
856 if (ccount>0) LogAS[m]/=ccount;
|
xue@1
|
857 else LogAS[m]=0;
|
xue@1
|
858 }
|
xue@1
|
859
|
xue@1
|
860 DeAlloc2(loga); DeAlloc2(f);
|
xue@1
|
861 return 0;
|
xue@1
|
862 }//S_F_SV_cf
|
xue@1
|
863
|
Chris@5
|
864 /**
|
xue@1
|
865 function SF_FB: computes filter coefficients with filter-bank method: single frame. See "further
|
xue@1
|
866 reading", pp.12, P5.
|
xue@1
|
867
|
xue@1
|
868 In: al[][M], fl[][M]: partial amplitudes and frequencies, al[0] and fl[0] are of current frame
|
xue@1
|
869 F: filter response sampling interval
|
xue@1
|
870 LMode: 1: current frame is the first frame; -1: the last frame; 0: neither first nor last frame
|
xue@1
|
871 Out: hl[K+2]: filter coefficients integrated at current frame
|
xue@1
|
872
|
xue@1
|
873 Returns K.
|
xue@1
|
874 */
|
xue@1
|
875 int SF_FB(double* hl, int M, int K, double** al, double** fl, double F, int LMode)
|
xue@1
|
876 {
|
xue@1
|
877 memset(hl, 0, sizeof(double)*(K+2));
|
xue@1
|
878 double* norm=new double[K+2]; memset(norm, 0, sizeof(double)*(K+2));
|
xue@1
|
879 for (int m=0; m<M; m++)
|
xue@1
|
880 {
|
xue@1
|
881 int dfsgn, k, K1;
|
xue@1
|
882 if (LMode!=1)
|
xue@1
|
883 {
|
xue@1
|
884 if (fl[0][m]-fl[-1][m]==0)
|
xue@1
|
885 {
|
xue@1
|
886 double a0, wk, wk_, a1;
|
xue@1
|
887 int k=floor(fl[0][m]/F);
|
xue@1
|
888 a0=al[-1][m], a1=al[0][m];
|
xue@1
|
889 wk=1-(fl[0][m]/F-k), wk_=1-wk;
|
xue@1
|
890 double dh=(a0+2*a1)/6.0;
|
xue@1
|
891 hl[k]+=wk*dh; //I3(1, wk, 0, a0, wk, 1, a1);
|
xue@1
|
892 hl[k+1]+=wk_*dh;//I3(1, wk_, 0, a0, wk_, 1, a1);
|
xue@1
|
893 norm[k]+=wk*0.5;//I3(1, wk, 0, 1, wk, 1, 1);
|
xue@1
|
894 norm[k+1]+=wk_*0.5;//I3(1, wk_, 0, 1, wk_, 1, 1);
|
xue@1
|
895 }
|
xue@1
|
896 else
|
xue@1
|
897 {
|
xue@1
|
898 double t0, t1, a0, u0, w0k, w0k_, a1, u1, w1k, w1k_;
|
xue@1
|
899 dfsgn=Sign(fl[0][m]-fl[-1][m]);
|
xue@1
|
900 if (dfsgn>0) K1=ceil(fl[-1][m]/F); else K1=floor(fl[-1][m]/F);
|
xue@1
|
901 t0=-1; k=K1;
|
xue@1
|
902 if (fl[-1][m]>0 && fl[0][m]>0) do
|
xue@1
|
903 {
|
xue@1
|
904 t1=-1+(k*F-fl[-1][m])/(fl[0][m]-fl[-1][m]);
|
xue@1
|
905 if (t1>0) t1=0;
|
xue@1
|
906
|
xue@1
|
907 if (t0==-1){a0=al[-1][m], u0=0, w0k=1-fabs(fl[-1][m]/F-k); w0k_=1-w0k;}
|
xue@1
|
908 else{a0=al[0][m]+t0*(al[0][m]-al[-1][m]), u0=1+t0, w0k=0, w0k_=1;}
|
xue@1
|
909 if (t1==0){a1=al[0][m], u1=1, w1k=1-fabs(fl[0][m]/F-k); w1k_=1-w1k;}
|
xue@1
|
910 else{a1=al[0][m]+t1*(al[0][m]-al[-1][m]), u1=1+t1, w1k=1, w1k_=0;}
|
xue@1
|
911
|
xue@1
|
912 hl[k]+=I3(t1-t0, w0k, u0, a0, w1k, u1, a1);
|
xue@1
|
913 hl[k-dfsgn]+=I3(t1-t0, w0k_, u0, a0, w1k_, u1, a1);
|
xue@1
|
914 norm[k]+=I3(t1-t0, w0k, u0, 1, w1k, u1, 1);
|
xue@1
|
915 norm[k-dfsgn]+=I3(t1-t0, w0k_, u0, 1, w1k_, u1, 1);
|
xue@1
|
916
|
xue@1
|
917 t0=t1;
|
xue@1
|
918 k+=dfsgn;
|
xue@1
|
919 }
|
xue@1
|
920 while (t1<0);
|
xue@1
|
921 }
|
xue@1
|
922 }
|
xue@1
|
923
|
xue@1
|
924 if (LMode!=-1)
|
xue@1
|
925 {
|
xue@1
|
926 double a0, wk, wk_, a1;
|
xue@1
|
927 if (fl[1][m]-fl[0][m]==0)
|
xue@1
|
928 {
|
xue@1
|
929 int k=floor(fl[0][m]/F);
|
xue@1
|
930 a0=al[0][m], a1=al[1][m];
|
xue@1
|
931 wk=1-fabs(fl[0][m]/F-k), wk_=1-wk;
|
xue@1
|
932 double dh=(2*a0+a1)/6.0;
|
xue@1
|
933 hl[k]+=wk*dh; //I3(1, wk, 1, a0, wk, 0, a1);
|
xue@1
|
934 hl[k+1]+=wk_*dh;//I3(1, wk_, 1, a0, wk_, 0, a1);
|
xue@1
|
935 norm[k]+=wk*0.5;//I3(1, wk, 1, 1, wk, 0, 1);
|
xue@1
|
936 norm[k+1]+=wk_*0.5;//I3(1, wk_, 1, 1, wk_, 0, 1);
|
xue@1
|
937 }
|
xue@1
|
938 else
|
xue@1
|
939 {
|
xue@1
|
940 double t0, t1, a0, u0, w0k, w0k_, a1, u1, w1k, w1k_;
|
xue@1
|
941 dfsgn=Sign(fl[1][m]-fl[0][m]);
|
xue@1
|
942 if (dfsgn>0) K1=ceil(fl[0][m]/F); else K1=floor(fl[0][m]/F);
|
xue@1
|
943 t0=0; k=K1;
|
xue@1
|
944 if (fl[0][m]>0 && fl[1][m]>0) do
|
xue@1
|
945 {
|
xue@1
|
946 try{
|
xue@1
|
947 t1=(k*F-fl[0][m])/(fl[1][m]-fl[0][m]);}
|
xue@1
|
948 catch(...){}
|
xue@1
|
949 if (t1>1) t1=1;
|
xue@1
|
950
|
xue@1
|
951 if (t0==0){a0=al[0][m], u0=1, w0k=1-fabs(fl[0][m]/F-k); w0k_=1-w0k;}
|
xue@1
|
952 else{a0=al[0][m]+t0*(al[1][m]-al[0][m]), u0=1-t0, w0k=1, w0k_=0;}
|
xue@1
|
953 if (t1==1){a1=al[1][m], u1=0, w1k=1-fabs(fl[1][m]/F-k); w1k_=1-w1k;}
|
xue@1
|
954 else{a1=al[0][m]+t1*(al[1][m]-al[0][m]), u1=1-t1, w1k=0, w1k_=1;}
|
xue@1
|
955
|
xue@1
|
956 hl[k]+=I3(t1-t0, w0k, u0, a0, w1k, u1, a1);
|
xue@1
|
957 hl[k-dfsgn]+=I3(t1-t0, w0k_, u0, a0, w1k_, u1, a1);
|
xue@1
|
958 norm[k]+=I3(t1-t0, w0k, u0, 1, w1k, u1, 1);
|
xue@1
|
959 norm[k-dfsgn]+=I3(t1-t0, w0k_, u0, 1, w1k_, u1, 1);
|
xue@1
|
960
|
xue@1
|
961 t0=t1;
|
xue@1
|
962 k+=dfsgn;
|
xue@1
|
963 }
|
xue@1
|
964 while (t1<1);
|
xue@1
|
965 }
|
xue@1
|
966 }
|
xue@1
|
967 }
|
xue@1
|
968
|
xue@1
|
969 int mink=0; while (mink<=K+1 && norm[mink]==0) mink++;
|
xue@1
|
970 int maxk=K+1; while (maxk>=0 && norm[maxk]==0) maxk--;
|
xue@1
|
971 int lastk=mink, nextk=-1;
|
xue@1
|
972 for (int k=mink; k<=maxk; k++)
|
xue@1
|
973 {
|
xue@1
|
974 if (k==nextk) lastk=k;
|
xue@1
|
975 else if (norm[k]!=0) hl[k]=log(hl[k]/norm[k]), lastk=k;
|
xue@1
|
976 else
|
xue@1
|
977 {
|
xue@1
|
978 if (k>nextk){nextk=k+1; while (norm[nextk]==0) nextk++; hl[nextk]=log(hl[nextk]/norm[nextk]);}
|
xue@1
|
979 hl[k]=(hl[lastk]*(nextk-k)+hl[nextk]*(k-lastk))/(nextk-lastk);
|
xue@1
|
980 }
|
xue@1
|
981 }
|
xue@1
|
982 for (int k=0; k<mink; k++) hl[k]=hl[mink];
|
xue@1
|
983 for (int k=maxk+1; k<K+2; k++) hl[k]=hl[maxk];
|
xue@1
|
984
|
xue@1
|
985 delete[] norm;
|
xue@1
|
986 return K;
|
xue@1
|
987 }//SF_FB
|
xue@1
|
988
|
Chris@5
|
989 /**
|
xue@1
|
990 function SF_SV: CG method for estimation source-filter model using slow-variation criterion. See
|
xue@1
|
991 "further reading", pp.9, boxed algorithm P4.
|
xue@1
|
992
|
xue@1
|
993 In: a[L][M], f[L][M]: partial amplitudes and frequencies
|
xue@1
|
994 F: filter response sampling interval
|
xue@1
|
995 theta: balancing factor of amplitude and frequency variations
|
xue@1
|
996 ep: convergence test threshold
|
xue@1
|
997 maxiter: maximal number of iterates
|
xue@1
|
998 Out: h[L][K+2]: filter coefficients
|
xue@1
|
999
|
xue@1
|
1000 Returns K.
|
xue@1
|
1001 */
|
xue@1
|
1002 int SF_SV(double** h, int L, int M, int K, double** a, double** f, double F, double theta, double ep, int maxiter)
|
xue@1
|
1003 {
|
xue@1
|
1004 Alloc2(L*7, K+2, b);
|
xue@1
|
1005 double **Ax=&b[L], **d=&Ax[L], **r=&d[L], **q=&r[L];
|
xue@1
|
1006 for (int l=0; l<L; l++) memset(h[l], 0, sizeof(double)*(K+2));
|
xue@1
|
1007 //calcualte b
|
xue@1
|
1008 P1_b(b, L, M, K, a, f, F, theta);
|
xue@1
|
1009 //calculate Ah
|
xue@1
|
1010 //double hAh=
|
xue@1
|
1011 P_Ax(Ax, L, M, K, h, f, F, theta);
|
xue@1
|
1012 //double **t_Ax=&b[L*5], **t_h=&b[L*6], epdel=1e-10, t_err=0;
|
xue@1
|
1013
|
xue@1
|
1014 //double bh=Inner(L, K+2, b, h); //debug
|
xue@1
|
1015 //double Del=0.5*hAh-bh; //debug
|
xue@1
|
1016
|
xue@1
|
1017 MultiAdd(L, K+2, r, b, Ax, -1);
|
xue@1
|
1018 Copy(L, K+2, d, r);
|
xue@1
|
1019 double delta=Inner(L, K+2, r, r);
|
xue@1
|
1020 ep=ep*delta;
|
xue@1
|
1021
|
xue@1
|
1022 int iter=0;
|
xue@1
|
1023 while(iter<maxiter && delta>ep)
|
xue@1
|
1024 {
|
xue@1
|
1025 P_Ax(q, L, M, K, d, f, F, theta);
|
xue@1
|
1026 /*debug point: watch if hAh-bh keeps decreasing
|
xue@1
|
1027 double lastdel=Del;
|
xue@1
|
1028 hAh=P_Ax(t_Ax, L, M, K, h, f, F, theta);
|
xue@1
|
1029 bh=Inner(L, K+2, b, h);
|
xue@1
|
1030 Del=hAh-bh;
|
xue@1
|
1031 if (Del>lastdel)
|
xue@1
|
1032 {lastdel=Del;} //set breakpoint here*/
|
xue@1
|
1033 double alpha=delta/Inner(L, K+2, d, q);
|
xue@1
|
1034 MultiAdd(L, K+2, h, h, d, alpha);
|
xue@1
|
1035 if (iter%50==0 && false){P_Ax(Ax, L, M, K, h, f, F, theta); MultiAdd(L, K+2, r, b, Ax, -1);}
|
xue@1
|
1036 else MultiAdd(L, K+2, r, r, q, -alpha);
|
xue@1
|
1037 double deltanew=Inner(L, K+2, r, r);
|
xue@1
|
1038 MultiAdd(L, K+2, d, r, d, deltanew/delta);
|
xue@1
|
1039 delta=deltanew;
|
xue@1
|
1040 iter++;
|
xue@1
|
1041 }
|
xue@1
|
1042
|
xue@1
|
1043 DeAlloc2(b);
|
xue@1
|
1044 return K;
|
xue@1
|
1045 }//SF_SV
|
xue@1
|
1046
|
Chris@5
|
1047 /**
|
xue@1
|
1048 function SF_SV_cf: CG method for estimation source-(constant)filter model by slow-variation criterion.
|
xue@1
|
1049
|
xue@1
|
1050 In: a[L][M], f[L][M]: partial amplitudes and frequencies
|
xue@1
|
1051 F: filter response sampling interval
|
xue@1
|
1052 ep: convergence test threshold
|
xue@1
|
1053 maxiter: maximal number of iterates
|
xue@1
|
1054 Out: h[K+2]: filter coefficients
|
xue@1
|
1055
|
xue@1
|
1056 Returns K.
|
xue@1
|
1057 */
|
xue@1
|
1058 int SF_SV_cf(double* h, int L, int M, int K, double** a, double** f, double F, double ep, int maxiter)
|
xue@1
|
1059 {
|
xue@1
|
1060 double* b=new double[(K+2)*7];
|
xue@1
|
1061 double *Ax=&b[K+2], *d=&Ax[K+2], *r=&d[K+2], *q=&r[K+2];
|
xue@1
|
1062
|
xue@1
|
1063 //calcualte b
|
xue@1
|
1064 P1_b_cf(b, L, M, K, a, f, F);
|
xue@1
|
1065 //calculate Ah
|
xue@1
|
1066 //double hAh=
|
xue@1
|
1067 P_Ax_cf(Ax, L, M, K, h, f, F);
|
xue@1
|
1068
|
xue@1
|
1069 MultiAdd(K+2, r, b, Ax, -1);
|
xue@1
|
1070 Copy(K+2, d, r);
|
xue@1
|
1071 double delta=Inner(K+2, r, r);
|
xue@1
|
1072 ep=ep*delta;
|
xue@1
|
1073
|
xue@1
|
1074 int iter=0;
|
xue@1
|
1075 while(iter<maxiter && delta>ep)
|
xue@1
|
1076 {
|
xue@1
|
1077 P_Ax_cf(q, L, M, K, d, f, F);
|
xue@1
|
1078 double alpha=delta/Inner(K+2, d, q);
|
xue@1
|
1079 MultiAdd(K+2, h, h, d, alpha);
|
xue@1
|
1080 if (iter%50==0 && false){P_Ax_cf(Ax, L, M, K, h, f, F); MultiAdd(K+2, r, b, Ax, -1);}
|
xue@1
|
1081 else MultiAdd(K+2, r, r, q, -alpha);
|
xue@1
|
1082 double deltanew=Inner(K+2, r, r);
|
xue@1
|
1083 MultiAdd(K+2, d, r, d, deltanew/delta);
|
xue@1
|
1084 delta=deltanew;
|
xue@1
|
1085 iter++;
|
xue@1
|
1086 }
|
xue@1
|
1087
|
xue@1
|
1088 delete[] b;
|
xue@1
|
1089 return K;
|
xue@1
|
1090 }//SF_SV_cf
|
xue@1
|
1091
|
Chris@5
|
1092 /**
|
xue@1
|
1093 function SF_SV_cf: CG method for estimation source-(constant)filter model by slow-variation criterion.
|
xue@1
|
1094
|
xue@1
|
1095 In: a[L][M], f[L][M]: partial amplitudes and frequencies
|
xue@1
|
1096 F: filter response sampling interval
|
xue@1
|
1097 ep: convergence test threshold
|
xue@1
|
1098 maxiter: maximal number of iterates
|
xue@1
|
1099 Out: h[K+2]: filter coefficients
|
xue@1
|
1100 b[L][M]: source coefficients
|
xue@1
|
1101
|
xue@1
|
1102 No reutrn value.
|
xue@1
|
1103 */
|
xue@1
|
1104 void SF_SV_cf(double* h, double** b, int L, int M, int K, double** a, double** f, double F, double ep, int maxiter)
|
xue@1
|
1105 {
|
xue@1
|
1106 memset(h, 0, sizeof(double)*(K+2));
|
xue@1
|
1107 SF_SV_cf(h, L, M, K, a, f, F, ep, maxiter);
|
xue@1
|
1108 for (int l=0; l<L; l++)
|
xue@1
|
1109 for (int m=0; m<M; m++)
|
xue@1
|
1110 {
|
xue@1
|
1111 double ff=f[l][m]/F;
|
xue@1
|
1112 if (ff<=0) continue;
|
xue@1
|
1113 int klm=floor(ff);
|
xue@1
|
1114 double f0=ff-klm;
|
xue@1
|
1115 double hlm=h[klm]*(1-f0)+h[klm+1]*f0;
|
xue@1
|
1116 b[l][m]=a[l][m]-hlm;
|
xue@1
|
1117 }
|
xue@1
|
1118 }//SF_SV_cf
|
xue@1
|
1119
|
Chris@5
|
1120 /**
|
xue@1
|
1121 function Sign: sign function
|
xue@1
|
1122
|
xue@1
|
1123 In: x: a floating-point number
|
xue@1
|
1124
|
xue@1
|
1125 Returns 0 if x=0, 1 if x>0, -1 if x<0.
|
xue@1
|
1126 */
|
xue@1
|
1127 int Sign(double x)
|
xue@1
|
1128 {
|
xue@1
|
1129 if (x==0) return 0;
|
xue@1
|
1130 else if (x>0) return 1;
|
xue@1
|
1131 else return -1;
|
xue@1
|
1132 }//Sign
|
xue@1
|
1133
|
Chris@5
|
1134 /**
|
xue@1
|
1135 function SynthesizeSF: synthesizes a harmonic sinusoid representation from a TSF object.
|
xue@1
|
1136
|
xue@1
|
1137 In: SF: a TSF object
|
xue@1
|
1138 sps: sampling rate ("samples per second")
|
xue@1
|
1139 Out: HS: teh synthesized HS.
|
xue@1
|
1140
|
xue@1
|
1141 No return value.
|
xue@1
|
1142 */
|
xue@1
|
1143 void SynthesizeSF(THS* HS, TSF* SF, double sps)
|
xue@1
|
1144 {
|
xue@1
|
1145 int t0=HS->Partials[0][0].t, s0=HS->Partials[0][0].s, L=SF->L, M=SF->M;
|
xue@1
|
1146 double *F0C=SF->F0C, *F0D=SF->F0D, *F0=SF->F0, offst=SF->offst;
|
xue@1
|
1147 double *logA0C=useA0?SF->logA0:SF->logA0C;
|
xue@1
|
1148 HS->Resize(M, L);
|
xue@1
|
1149
|
xue@1
|
1150 atom** Partials=HS->Partials;
|
xue@1
|
1151
|
xue@1
|
1152 for (int l=0; l<L; l++)
|
xue@1
|
1153 {
|
xue@1
|
1154 double tl=t0+offst*l;
|
xue@1
|
1155 F0[l]=F0C[l]+F0D[l];
|
xue@1
|
1156 for (int m=0; m<M; m++)
|
xue@1
|
1157 {
|
xue@1
|
1158 Partials[m][l].s=s0;
|
xue@1
|
1159 Partials[m][l].t=tl;
|
xue@1
|
1160 Partials[m][l].f=(m+1)*F0[l];
|
xue@1
|
1161
|
xue@1
|
1162 if (Partials[m][l].f>0.5 || Partials[m][l].f<0) Partials[m][l].a=0;
|
xue@1
|
1163 else Partials[m][l].a=exp(logA0C[l]+SF->LogAS(m,l)+SF->LogAF(Partials[m][l].f,l));
|
xue@1
|
1164 }
|
xue@1
|
1165 }
|
xue@1
|
1166 }//SynthesizeSF
|
xue@1
|
1167
|
xue@1
|
1168
|
xue@1
|
1169
|
xue@1
|
1170
|