annotate hssf.cpp @ 13:de3961f74f30 tip

Add Linux/gcc Makefile; build fix
author Chris Cannam
date Mon, 05 Sep 2011 15:22:35 +0100
parents 977f541d6683
children
rev   line source
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