annotate procedures.cpp @ 3:42c078b19e9a

* Replace null-pointer hack with use of standard macro offsetof(struct,member)
author Chris Cannam
date Tue, 05 Oct 2010 16:18:52 +0100
parents fc19d45615d1
children 5f3c32dc6e17
rev   line source
xue@1 1 //---------------------------------------------------------------------------
xue@1 2
xue@1 3 #include <math.h>
Chris@2 4 #include <string.h>
Chris@3 5 #include <stddef.h>
xue@1 6 #include "procedures.h"
xue@1 7 #include "matrix.h"
xue@1 8 #include "opt.h"
Chris@2 9 #include "sinest.h"
xue@1 10
xue@1 11 //---------------------------------------------------------------------------
xue@1 12 //TGMM methods
xue@1 13
xue@1 14 //method TGMM::TGMM: default constructor
xue@1 15 TGMM::TGMM()
xue@1 16 {
xue@1 17 p=0, m=dev=0;
xue@1 18 }//TGMM
xue@1 19
xue@1 20 //method GMM:~TGMM: default destructor
xue@1 21 TGMM::~TGMM()
xue@1 22 {
xue@1 23 ReleaseGMM(p, m, dev)
xue@1 24 };
xue@1 25
xue@1 26 //---------------------------------------------------------------------------
xue@1 27 //TFSpans methods
xue@1 28
xue@1 29 //method TTFSpans: default constructor
xue@1 30 TTFSpans::TTFSpans()
xue@1 31 {
xue@1 32 Count=0;
xue@1 33 Capacity=100;
xue@1 34 Items=new TTFSpan[Capacity];
xue@1 35 }//TTFSpans
xue@1 36
xue@1 37 //method ~TTFSpans: default destructor
xue@1 38 TTFSpans::~TTFSpans()
xue@1 39 {
xue@1 40 delete[] Items;
xue@1 41 }//~TTFSpans
xue@1 42
xue@1 43 /*
xue@1 44 method Add: add a new span to the list
xue@1 45
xue@1 46 In: ATFSpan: the new span to add
xue@1 47 */
xue@1 48 void TTFSpans::Add(TTFSpan& ATFSpan)
xue@1 49 {
xue@1 50 if (Count==Capacity)
xue@1 51 {
xue@1 52 int OldCapacity=Capacity;
xue@1 53 Capacity+=50;
xue@1 54 TTFSpan* NewItems=new TTFSpan[Capacity];
xue@1 55 memcpy(NewItems, Items, sizeof(TTFSpan)*OldCapacity);
xue@1 56 delete[] Items;
xue@1 57 Items=NewItems;
xue@1 58 }
xue@1 59 Items[Count]=ATFSpan;
xue@1 60 Count++;
xue@1 61 }//Add
xue@1 62
xue@1 63 /*
xue@1 64 method Clear: discard the current content without freeing memory.
xue@1 65 */
xue@1 66 void TTFSpans::Clear()
xue@1 67 {
xue@1 68 Count=0;
xue@1 69 }//Clear
xue@1 70
xue@1 71 /*
xue@1 72 method Delete: delete a span from current list
xue@1 73
xue@1 74 In: Index: index to the span to delete
xue@1 75 */
xue@1 76 int TTFSpans::Delete(int Index)
xue@1 77 {
xue@1 78 if (Index<0 || Index>=Count)
xue@1 79 return 0;
xue@1 80 memmove(&Items[Index], &Items[Index+1], sizeof(TTFSpan)*(Count-1-Index));
xue@1 81 Count--;
xue@1 82 return 1;
xue@1 83 }//Delete
xue@1 84
xue@1 85 //---------------------------------------------------------------------------
xue@1 86 //SpecTrack methods
xue@1 87
xue@1 88 /*
xue@1 89 method TSpecTrack::Add: adds a SpecPeak to the track.
xue@1 90
xue@1 91 In: APeak: the SpecPeak to add.
xue@1 92 */
xue@1 93 int TSpecTrack::Add(TSpecPeak& APeak)
xue@1 94 {
xue@1 95 if (Count>=Capacity)
xue@1 96 {
xue@1 97 Peaks=(TSpecPeak*)realloc(Peaks, sizeof(TSpecPeak)*(Capacity*2));
xue@1 98 Capacity*=2;
xue@1 99 }
xue@1 100 int ind=LocatePeak(APeak);
xue@1 101 if (ind<0)
xue@1 102 {
xue@1 103 InsertPeak(APeak, -ind-1);
xue@1 104 ind=-ind-1;
xue@1 105 }
xue@1 106
xue@1 107 int t=APeak.t;
xue@1 108 double f=APeak.f;
xue@1 109 if (Count==1) t1=t2=t, fmin=fmax=f;
xue@1 110 else
xue@1 111 {
xue@1 112 if (t<t1) t1=t;
xue@1 113 else if (t>t2) t2=t;
xue@1 114 if (f<fmin) fmin=f;
xue@1 115 else if (f>fmax) fmax=f;
xue@1 116 }
xue@1 117 return ind;
xue@1 118 }//Add
xue@1 119
xue@1 120 /*
xue@1 121 method TSpecTrack::TSpecTrack: creates a SpecTrack with an inital capacity.
xue@1 122
xue@1 123 In: ACapacity: initial capacity, i.e. the number SpecPeak's to allocate storage space for.
xue@1 124 */
xue@1 125 TSpecTrack::TSpecTrack(int ACapacity)
xue@1 126 {
xue@1 127 Count=0;
xue@1 128 Capacity=ACapacity;
xue@1 129 Peaks=new TSpecPeak[Capacity];
xue@1 130 }//TSpecTrack
xue@1 131
xue@1 132 //method TSpecTrack::~TSpecTrack: default destructor.
xue@1 133 TSpecTrack::~TSpecTrack()
xue@1 134 {
xue@1 135 delete[] Peaks;
xue@1 136 }//TSpecTrack
xue@1 137
xue@1 138 /*
xue@1 139 method InsertPeak: inserts a new SpecPeak into the track at a given index. Internal use only.
xue@1 140
xue@1 141 In: APeak: the SpecPeak to insert.
xue@1 142 index: the position in the list to place the new SpecPeak. Original SpecPeak's at and after this
xue@1 143 position are shifted by 1 posiiton.
xue@1 144 */
xue@1 145 void TSpecTrack::InsertPeak(TSpecPeak& APeak, int index)
xue@1 146 {
xue@1 147 memmove(&Peaks[index+1], &Peaks[index], sizeof(TSpecPeak)*(Count-index));
xue@1 148 Peaks[index]=APeak;
xue@1 149 Count++;
xue@1 150 }//InsertPeak
xue@1 151
xue@1 152 /*
xue@1 153 method TSpecTrack::LocatePeak: looks for a SpecPeak in the track that has the same time (t) as APeak.
xue@1 154
xue@1 155 In: APeak: a SpecPeak
xue@1 156
xue@1 157 Returns the index in this track of the first SpecPeak that has the same time stamp as APeak. However,
xue@1 158 if there is no peak with that time stamp, the method returns -1 if APeaks comes before the first
xue@1 159 SpecPeak, -2 if between 1st and 2nd SpecPeak's, -3 if between 2nd and 3rd SpecPeak's, etc.
xue@1 160 */
xue@1 161 int TSpecTrack::LocatePeak(TSpecPeak& APeak)
xue@1 162 {
xue@1 163 if (APeak.t<Peaks[0].t) return -1;
xue@1 164 if (APeak.t>Peaks[Count-1].t) return -Count-1;
xue@1 165
xue@1 166 if (APeak.t==Peaks[0].t) return 0;
xue@1 167 else if (APeak.t==Peaks[Count-1].t) return Count-1;
xue@1 168
xue@1 169 int a=0, b=Count-1, c=(a+b)/2;
xue@1 170 while (a<c)
xue@1 171 {
xue@1 172 if (APeak.t==Peaks[c].t) return c;
xue@1 173 else if (APeak.t<Peaks[c].t) {b=c; c=(a+b)/2;}
xue@1 174 else {a=c; c=(a+b)/2;}
xue@1 175 }
xue@1 176 return -a-2;
xue@1 177 }//LocatePeak
xue@1 178
xue@1 179 //---------------------------------------------------------------------------
xue@1 180 /*
xue@1 181 function: ACPower: AC power
xue@1 182
xue@1 183 In: data[Count]: a signal
xue@1 184
xue@1 185 Returns the power of its AC content.
xue@1 186 */
xue@1 187 double ACPower(double* data, int Count, void*)
xue@1 188 {
xue@1 189 if (Count<=0) return 0;
xue@1 190 double power=0, avg=0, tmp;
xue@1 191 for (int i=0; i<Count; i++)
xue@1 192 {
xue@1 193 tmp=*(data++);
xue@1 194 power+=tmp*tmp;
xue@1 195 avg+=tmp;
xue@1 196 }
xue@1 197 power=(power-avg*avg)/Count;
xue@1 198 return power;
xue@1 199 }//ACPower
xue@1 200
xue@1 201 //---------------------------------------------------------------------------
xue@1 202 /*
xue@1 203 function Add: vector addition
xue@1 204
xue@1 205 In: dest[Count], source[Count]: two vectors
xue@1 206 Out: dest[Count]: their sum
xue@1 207
xue@1 208 No return value.
xue@1 209 */
xue@1 210 void Add(double* dest, double* source, int Count)
xue@1 211 {
xue@1 212 for (int i=0; i<Count; i++) *(dest++)+=*(source++);
xue@1 213 }//Add
xue@1 214
xue@1 215 /*
xue@1 216 function Add: vector addition
xue@1 217
xue@1 218 In: addend[count], adder[count]: two vectors
xue@1 219 Out: out[count]: their sum
xue@1 220
xue@1 221 No return value.
xue@1 222 */
xue@1 223 void Add(double* out, double* addend, double* adder, int count)
xue@1 224 {
xue@1 225 for (int i=0; i<count; i++) *(out++)=*(addend++)+*(adder++);
xue@1 226 }//Add
xue@1 227
xue@1 228 //---------------------------------------------------------------------------
xue@1 229
xue@1 230 /*
xue@1 231 function ApplyWindow: applies window function to signal buffer.
xue@1 232
xue@1 233 In: Buffer[Size]: signal to be windowed
xue@1 234 Weight[Size]: the window
xue@1 235 Out: OutBuffer[Size]: windowed signal
xue@1 236
xue@1 237 No return value;
xue@1 238 */
xue@1 239 void ApplyWindow(double* OutBuffer, double* Buffer, double* Weights, int Size)
xue@1 240 {
xue@1 241 for (int i=0; i<Size; i++) *(OutBuffer++)=*(Buffer++)**(Weights++);
xue@1 242 }//ApplyWindow
xue@1 243
xue@1 244 //---------------------------------------------------------------------------
xue@1 245 /*
xue@1 246 function Avg: average
xue@1 247
xue@1 248 In: data[Count]: a data array
xue@1 249
xue@1 250 Returns the average of the array.
xue@1 251 */
xue@1 252 double Avg(double* data, int Count, void*)
xue@1 253 {
xue@1 254 if (Count<=0) return 0;
xue@1 255 double avg=0;
xue@1 256 for (int i=0; i<Count; i++) avg+=*(data++);
xue@1 257 avg/=Count;
xue@1 258 return avg;
xue@1 259 }//Avg
xue@1 260
xue@1 261 //---------------------------------------------------------------------------
xue@1 262 /*
xue@1 263 function AvgFilter: get slow-varying wave trace by averaging
xue@1 264
xue@1 265 In: data[Count]: input signal
xue@1 266 HWid: half the size of the averaging window
xue@1 267 Out: datout[Count]: the slow-varying part of data[].
xue@1 268
xue@1 269 No return value.
xue@1 270 */
xue@1 271 void AvgFilter(double* dataout, double* data, int Count, int HWid)
xue@1 272 {
xue@1 273 double sum=0;
xue@1 274
xue@1 275 dataout[0]=data[0];
xue@1 276
xue@1 277 for (int i=1; i<=HWid; i++)
xue@1 278 {
xue@1 279 sum+=data[2*i-1]+data[2*i];
xue@1 280 dataout[i]=sum/(2*i+1);
xue@1 281 }
xue@1 282
xue@1 283 for (int i=HWid+1; i<Count-HWid; i++)
xue@1 284 {
xue@1 285 sum=sum+data[i+HWid]-data[i-HWid-1];
xue@1 286 dataout[i]=sum/(2*HWid+1);
xue@1 287 }
xue@1 288
xue@1 289 for (int i=Count-HWid; i<Count; i++)
xue@1 290 {
xue@1 291 sum=sum-data[2*i-Count-1]-data[2*i-Count];
xue@1 292 dataout[i]=sum/(2*(Count-i)-1);
xue@1 293 }
xue@1 294 }//AvgFilter
xue@1 295
xue@1 296 //---------------------------------------------------------------------------
xue@1 297 /*
xue@1 298 function CalculateSpectrogram: computes the spectrogram of a signal
xue@1 299
xue@1 300 In: data[Count]: the time-domain signal
xue@1 301 start, end: start and end points marking the section for which the spectrogram is to be computed
xue@1 302 Wid, Offst: frame size and hop size
xue@1 303 Window: window function
xue@1 304 amp: a pre-amplifier
xue@1 305 half: specifies if the spectral values at Wid/2 are to be retried
xue@1 306 Out: Spec[][Wid/2] or Spec[][Wid/2+1]: amplitude spectrogram
xue@1 307 ph[][][Wid/2] or Ph[][Wid/2+1]: phase spectrogram
xue@1 308
xue@1 309 No return value. The caller is repsonse to arrange storage spance of output buffers.
xue@1 310 */
xue@1 311 void CalculateSpectrogram(double* data, int Count, int start, int end, int Wid, int Offst, double* Window, double** Spec, double** Ph, double amp, bool half)
xue@1 312 {
xue@1 313 AllocateFFTBuffer(Wid, fft, w, x);
xue@1 314
xue@1 315 int Fr=(end-start-Wid)/Offst+1;
xue@1 316
xue@1 317 for (int i=0; i<Fr; i++)
xue@1 318 {
xue@1 319 RFFTCW(&data[i*Offst+start], Window, 0, 0, log2(Wid), w, x);
xue@1 320
xue@1 321 if (Spec)
xue@1 322 {
xue@1 323 for (int j=0; j<Wid/2; j++)
xue@1 324 Spec[i][j]=sqrt(x[j].x*x[j].x+x[j].y*x[j].y)*amp;
xue@1 325 if (half)
xue@1 326 Spec[i][Wid/2]=sqrt(x[Wid/2].x*x[Wid/2].x+x[Wid/2].y*x[Wid/2].y)*amp;
xue@1 327 }
xue@1 328 if (Ph)
xue@1 329 {
xue@1 330 for (int j=0; j<=Wid/2; j++)
xue@1 331 Ph[i][j]=Atan2(x[j].y, x[j].x);
xue@1 332 if (half)
xue@1 333 Ph[i][Wid/2]=Atan2(x[Wid/2].y, x[Wid/2].x);
xue@1 334 }
xue@1 335 }
xue@1 336 FreeFFTBuffer(fft);
xue@1 337 }//CalculateSpectrogram
xue@1 338
xue@1 339 //---------------------------------------------------------------------------
xue@1 340 /*
xue@1 341 function Conv: simple convolution
xue@1 342
xue@1 343 In: in1[N1], in2[N2]: two sequences
xue@1 344 Out: out[N1+N2-1]: their convolution
xue@1 345
xue@1 346 No return value.
xue@1 347 */
xue@1 348 void Conv(double* out, int N1, double* in1, int N2, double* in2)
xue@1 349 {
xue@1 350 int N=N1+N1-1;
xue@1 351 memset(out, 0, sizeof(double)*N);
xue@1 352 for (int n1=0; n1<N1; n1++)
xue@1 353 for (int n2=0; n2<N2; n2++)
xue@1 354 out[n1+n2]+=in1[n1]*in2[n2];
xue@1 355 }//Conv
xue@1 356
xue@1 357 //---------------------------------------------------------------------------
xue@1 358 /*
xue@1 359 function Correlation: computes correlation coefficient of 2 vectors a & b, equals cos(aOb).
xue@1 360
xue@1 361 In: a[Count], b[Count]: two vectors
xue@1 362
xue@1 363 Returns their correlation coefficient.
xue@1 364 */
xue@1 365 double Correlation(double* a, double* b, int Count)
xue@1 366 {
xue@1 367 double aa=0, bb=0, ab=0;
xue@1 368 for (int i=0; i<Count; i++)
xue@1 369 {
xue@1 370 aa+=*a**a;
xue@1 371 bb+=*b**b;
xue@1 372 ab+=*(a++)**(b++);
xue@1 373 }
xue@1 374 return ab/sqrt(aa*bb);
xue@1 375 }//Correlation
xue@1 376
xue@1 377 //---------------------------------------------------------------------------
xue@1 378 /*
xue@1 379 function DCAmplitude: DC amplitude
xue@1 380
xue@1 381 In: data[Count]: a signal
xue@1 382
xue@1 383 Returns its DC amplitude (=AC amplitude without DC removing)
xue@1 384 */
xue@1 385 double DCAmplitude(double* data, int Count, void*)
xue@1 386 {
xue@1 387 if (Count<=0) return 0;
xue@1 388 double power=0, tmp;
xue@1 389 for (int i=0; i<Count; i++)
xue@1 390 {
xue@1 391 tmp=*(data++);
xue@1 392 power+=tmp*tmp;
xue@1 393 }
xue@1 394 power/=Count;
xue@1 395 return sqrt(2*power);
xue@1 396 }//DCAmplitude
xue@1 397
xue@1 398 /*
xue@1 399 function DCPower: DC power
xue@1 400
xue@1 401 In: data[Count]: a signal
xue@1 402
xue@1 403 Returns its DC power.
xue@1 404 */
xue@1 405 double DCPower(double* data, int Count, void*)
xue@1 406 {
xue@1 407 if (Count<=0) return 0;
xue@1 408 double power=0, tmp;
xue@1 409 for (int i=0; i<Count; i++)
xue@1 410 {
xue@1 411 tmp=*(data++);
xue@1 412 power+=tmp*tmp;
xue@1 413 }
xue@1 414 power/=Count;
xue@1 415 return power;
xue@1 416 }//DCPower
xue@1 417
xue@1 418 //---------------------------------------------------------------------------
xue@1 419 /*
xue@1 420 DCT: discrete cosine transform, direct computation. For fast DCT, see fft.cpp.
xue@1 421
xue@1 422 In: input[N]: a signal
xue@1 423 Out: output[N]: its DCT
xue@1 424
xue@1 425 No return value.
xue@1 426 */
xue@1 427 void DCT( double* output, double* input, int N)
xue@1 428 {
xue@1 429 double Wn;
xue@1 430
xue@1 431 for (int n=0; n<N; n++)
xue@1 432 {
xue@1 433 output[n]=0;
xue@1 434 Wn=n*M_PI/2/N;
xue@1 435 for (int k=0; k<N; k++)
xue@1 436 output[n]+=input[k]*cos((2*k+1)*Wn);
xue@1 437 if (n==0) output[n]*=1.4142135623730950488016887242097/N;
xue@1 438 else output[n]*=2.0/N;
xue@1 439 }
xue@1 440 }//DCT
xue@1 441
xue@1 442 /*
xue@1 443 function IDCT: inverse discrete cosine transform, direct computation. For fast IDCT, see fft.cpp.
xue@1 444
xue@1 445 In: input[N]: a signal
xue@1 446 Out: output[N]: its IDCT
xue@1 447
xue@1 448 No return value.
xue@1 449 */
xue@1 450 void IDCT(double* output, double* input, int N)
xue@1 451 {
xue@1 452 for (int k=0; k<N; k++)
xue@1 453 {
xue@1 454 double Wk=(2*k+1)*M_PI/2/N;
xue@1 455 output[k]=input[0]/1.4142135623730950488016887242097;
xue@1 456 for (int n=1; n<N; n++)
xue@1 457 output[k]+=input[n]*cos(n*Wk);
xue@1 458 }
xue@1 459 }//IDCT
xue@1 460
xue@1 461 //---------------------------------------------------------------------------
xue@1 462 /*
xue@1 463 function DeDC: removes DC component of a signal
xue@1 464
xue@1 465 In: data[Count]: the signal
xue@1 466 HWid: half of averaging window size
xue@1 467 Out: data[Count]: de-DC-ed signal
xue@1 468
xue@1 469 No return value.
xue@1 470 */
xue@1 471 void DeDC(double* data, int Count, int HWid)
xue@1 472 {
xue@1 473 double* data2=new double[Count];
xue@1 474 AvgFilter(data2, data, Count, HWid);
xue@1 475 for (int i=0; i<Count; i++)
xue@1 476 *(data++)-=*(data2++);
xue@1 477 delete[] data2;
xue@1 478 }//DeDC
xue@1 479
xue@1 480 /*
xue@1 481 function DeDC_static: removes DC component statically
xue@1 482
xue@1 483 In: data[Count]: the signal
xue@1 484 Out: data[Count]: DC-removed signal
xue@1 485
xue@1 486 No return value.
xue@1 487 */
xue@1 488 void DeDC_static(double* data, int Count)
xue@1 489 {
xue@1 490 double avg=Avg(data, Count, 0);
xue@1 491 for (int i=0; i<Count; i++) *(data++)-=avg;
xue@1 492 }//DeDC_static
xue@1 493
xue@1 494 //---------------------------------------------------------------------------
xue@1 495 /*
xue@1 496 function DoubleToInt: converts double-precision floating point array to integer array
xue@1 497
xue@1 498 In: in[Count]: the double array
xue@1 499 BytesPerSample: bytes per sample of destination integers
xue@1 500 Out: out[Count]: the integer array
xue@1 501
xue@1 502 No return value.
xue@1 503 */
xue@1 504 void DoubleToInt(void* out, int BytesPerSample, double* in, int Count)
xue@1 505 {
xue@1 506 if (BytesPerSample==1){unsigned char* out8=(unsigned char*)out; for (int k=0; k<Count; k++) *(out8++)=*(in++)+128.5;}
xue@1 507 else {__int16* out16=(__int16*)out; for (int k=0; k<Count; k++) *(out16++)=floor(*(in++)+0.5);}
xue@1 508 }//DoubleToInt
xue@1 509
xue@1 510 /*
xue@1 511 function DoubleToIntAdd: adds double-precision floating point array to integer array
xue@1 512
xue@1 513 In: in[Count]: the double array
xue@1 514 out[Count]: the integer array
xue@1 515 BytesPerSample: bytes per sample of destination integers
xue@1 516 Out: out[Count]: the sum of the two arrays
xue@1 517
xue@1 518 No return value.
xue@1 519 */
xue@1 520 void DoubleToIntAdd(void* out, int BytesPerSample, double* in, int Count)
xue@1 521 {
xue@1 522 if (BytesPerSample==1)
xue@1 523 {
xue@1 524 unsigned char* out8=(unsigned char*)out;
xue@1 525 for (int k=0; k<Count; k++){*out8=*out8+*in+128.5; out8++; in++;}
xue@1 526 }
xue@1 527 else
xue@1 528 {
xue@1 529 __int16* out16=(__int16*)out;
xue@1 530 for (int k=0; k<Count; k++){*out16=*out16+floor(*in+0.5); out16++; in++;}
xue@1 531 }
xue@1 532 }//DoubleToIntAdd
xue@1 533
xue@1 534 //---------------------------------------------------------------------------
xue@1 535 /*
xue@1 536 DPower: in-frame power variation
xue@1 537
xue@1 538 In: data[Count]: a signal
xue@1 539
xue@1 540 returns the different between AC powers of its first and second halves.
xue@1 541 */
xue@1 542 double DPower(double* data, int Count, void*)
xue@1 543 {
xue@1 544 double ene1=ACPower(data, Count/2, 0);
xue@1 545 double ene2=ACPower(&data[Count/2], Count/2, 0);
xue@1 546 return ene2-ene1;
xue@1 547 }//DPower
xue@1 548
xue@1 549 //---------------------------------------------------------------------------
xue@1 550 /*
xue@1 551 funciton Energy: energy
xue@1 552
xue@1 553 In: data[Count]: a signal
xue@1 554
xue@1 555 Returns its total energy
xue@1 556 */
xue@1 557 double Energy(double* data, int Count)
xue@1 558 {
xue@1 559 double result=0;
xue@1 560 for (int i=0; i<Count; i++) result+=data[i]*data[i];
xue@1 561 return result;
xue@1 562 }//Energy
xue@1 563
xue@1 564 //---------------------------------------------------------------------------
xue@1 565 /*
xue@1 566 function ExpOnsetFilter: onset filter with exponential impulse response h(t)=Aexp(-t/Tr)-Bexp(-t/Ta),
xue@1 567 A=1-exp(-1/Tr), B=1-exp(-1/Ta).
xue@1 568
xue@1 569 In: data[Count]: signal to filter
xue@1 570 Tr, Ta: time constants of h(t)
xue@1 571 Out: dataout[Count]: filtered signal, normalized by multiplying a factor.
xue@1 572
xue@1 573 Returns the normalization factor. Identical data and dataout is allowed.
xue@1 574 */
xue@1 575 double ExpOnsetFilter(double* dataout, double* data, int Count, double Tr, double Ta)
xue@1 576 {
xue@1 577 double FA=0, FB=0;
xue@1 578 double EA=exp(-1.0/Tr), EB=exp(-1.0/Ta);
xue@1 579 double A=1-EA, B=1-EB;
xue@1 580 double NormFactor=1/sqrt((1-EA)*(1-EA)/(1-EA*EA)+(1-EB)*(1-EB)/(1-EB*EB)-2*(1-EA)*(1-EB)/(1-EA*EB));
xue@1 581 for (int i=0; i<Count; i++)
xue@1 582 {
xue@1 583 FA=FA*EA+*data;
xue@1 584 FB=FB*EB+*(data++);
xue@1 585 *(dataout++)=(A*FA-B*FB)*NormFactor;
xue@1 586 }
xue@1 587 return NormFactor;
xue@1 588 }//ExpOnsetFilter
xue@1 589
xue@1 590 /*
xue@1 591 function ExpOnsetFilter_balanced: exponential onset filter without starting step response. It
xue@1 592 extends the input signal at the front end by bal*Ta samples by repeating the its value at 0, then
xue@1 593 applies the onset filter on the extended signal instead.
xue@1 594
xue@1 595 In: data[Count]: signal to filter
xue@1 596 Tr, Ta: time constants to the impulse response of onset filter, see ExpOnsetFilter().
xue@1 597 bal: balancing factor
xue@1 598 Out: dataout[Count]: filtered signal, normalized by multiplying a factor.
xue@1 599
xue@1 600 Returns the normalization factor. Identical data and dataout is allowed.
xue@1 601 */
xue@1 602 double ExpOnsetFilter_balanced(double* dataout, double* data, int Count, double Tr, double Ta, int bal)
xue@1 603 {
xue@1 604 double* tmpdata=new double[int(Count+bal*Ta)];
xue@1 605 double* ltmpdata=tmpdata;
xue@1 606 for (int i=0; i<bal*Ta; i++) *(ltmpdata++)=data[0];
xue@1 607 memcpy(ltmpdata, data, sizeof(double)*Count);
xue@1 608 double result=ExpOnsetFilter(tmpdata, tmpdata, bal*Ta+Count, Tr, Ta);
xue@1 609 memcpy(dataout, ltmpdata, sizeof(double)*Count);
xue@1 610 delete[] tmpdata;
xue@1 611 return result;
xue@1 612 }//ExpOnsetFilter_balanced
xue@1 613
xue@1 614 //---------------------------------------------------------------------------
xue@1 615 /*
xue@1 616 function ExtractLinearComponent: Legendre linear component
xue@1 617
xue@1 618 In: data[Count+1]: a signal
xue@1 619 Out: dataout[Count+1]: its Legendre linear component, optional.
xue@1 620
xue@1 621 Returns the coefficient to the linear component.
xue@1 622 */
xue@1 623 double ExtractLinearComponent(double* dataout, double* data, int Count)
xue@1 624 {
xue@1 625 double tmp=0;
xue@1 626 int N=Count*2;
xue@1 627 for (int n=0; n<=Count; n++) tmp+=n**(data++);
xue@1 628 tmp=tmp*24/N/(N+1)/(N+2);
xue@1 629 if (dataout)
xue@1 630 for (int n=0; n<=Count; n++) *(dataout++)=tmp*n;
xue@1 631 return tmp;
xue@1 632 }//ExtractLinearComponent
xue@1 633
xue@1 634 //---------------------------------------------------------------------------
xue@1 635 /*
xue@1 636 function FFTConv: fast convolution of two series by FFT overlap-add. In an overlap-add scheme it is
xue@1 637 assumed that one of the convolvends is short compared to the other one, which can be potentially
xue@1 638 infinitely long. The long convolvend is devided into short segments, each of which is convolved with
xue@1 639 the short convolvend, the results of which are then assembled into the final result. The minimal delay
xue@1 640 from input to output is the amount of overlap, which is the size of the short convolvend minus 1.
xue@1 641
xue@1 642 In: source1[size1]: convolvend
xue@1 643 source2[size2]: second convolvend
xue@1 644 zero: position of first point in convoluton result, relative to main output buffer.
xue@1 645 pre_buffer[-zero]: buffer hosting values to be overlap-added to the start of the result.
xue@1 646 Out: dest[size1]: the middle part of convolution result
xue@1 647 pre_buffer[-zero]: now updated by adding beginning part of the convolution result
xue@1 648 post_buffer[size2+zero]: end part of the convolution result
xue@1 649
xue@1 650 No return value. Identical dest and source1 allowed.
xue@1 651
xue@1 652 The convolution result has length size1+size2 (counting one trailing zero). If zero lies in the range
xue@1 653 between -size2 and 0, then the first -zero samples are added to pre_buffer[], next size1 samples are
xue@1 654 saved to dest[], and the last size2+zero sampled are saved to post_buffer[]; if not, the middle size1
xue@1 655 samples are saved to dest[], while pre_buffer[] and post_buffer[] are not used.
xue@1 656 */
xue@1 657 void FFTConv(double* dest, double* source1, int size1, double* source2, int size2, int zero, double* pre_buffer, double* post_buffer)
xue@1 658 {
xue@1 659 int order=log2(size2-1)+1+1;
xue@1 660 int Wid=1<<order;
xue@1 661 int HWid=Wid/2;
xue@1 662 int Fr=size1/HWid;
xue@1 663 int res=size1-HWid*Fr;
xue@1 664 bool trunc=false;
xue@1 665 if (zero<-size2+1 || zero>0) zero=-size2/2, trunc=true;
xue@1 666 if (pre_buffer==NULL || (post_buffer==NULL && size2+zero!=0)) trunc=true;
xue@1 667
xue@1 668 AllocateFFTBuffer(Wid, fft, w, x1);
xue@1 669 int* hbitinv=CreateBitInvTable(order-1);
xue@1 670 cdouble* x2=new cdouble[Wid];
xue@1 671 double* tmp=new double[HWid];
xue@1 672 memset(tmp, 0, sizeof(double)*HWid);
xue@1 673
xue@1 674 memcpy(fft, source2, sizeof(double)*size2);
xue@1 675 memset(&fft[size2], 0, sizeof(double)*(Wid-size2));
xue@1 676 RFFTC(fft, 0, 0, order, w, x2, hbitinv);
xue@1 677
xue@1 678 double r1, r2, i1, i2;
xue@1 679 int ind, ind_;
xue@1 680 for (int i=0; i<Fr; i++)
xue@1 681 {
xue@1 682 memcpy(fft, &source1[i*HWid], sizeof(double)*HWid);
xue@1 683 memset(&fft[HWid], 0, sizeof(double)*HWid);
xue@1 684
xue@1 685 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 686
xue@1 687 for (int j=0; j<Wid; j++)
xue@1 688 {
xue@1 689 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 690 x1[j].x=r1*r2-i1*i2;
xue@1 691 x1[j].y=r1*i2+r2*i1;
xue@1 692 }
xue@1 693 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 694 for (int j=0; j<HWid; j++) tmp[j]+=fft[j];
xue@1 695
xue@1 696 ind=i*HWid+zero; //(i+1)*HWid<=size1
xue@1 697 ind_=ind+HWid; //ind_=(i+1)*HWid+zero<=size1
xue@1 698 if (ind<0)
xue@1 699 {
xue@1 700 if (!trunc)
xue@1 701 memdoubleadd(pre_buffer, tmp, -ind);
xue@1 702 memcpy(dest, &tmp[-ind], sizeof(double)*(HWid+ind));
xue@1 703 }
xue@1 704 else
xue@1 705 memcpy(&dest[ind], tmp, sizeof(double)*HWid);
xue@1 706 memcpy(tmp, &fft[HWid], sizeof(double)*HWid);
xue@1 707 }
xue@1 708
xue@1 709 if (res>0)
xue@1 710 {
xue@1 711 memcpy(fft, &source1[Fr*HWid], sizeof(double)*res);
xue@1 712 memset(&fft[res], 0, sizeof(double)*(Wid-res));
xue@1 713
xue@1 714 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 715
xue@1 716 for (int j=0; j<Wid; j++)
xue@1 717 {
xue@1 718 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 719 x1[j].x=r1*r2-i1*i2;
xue@1 720 x1[j].y=r1*i2+r2*i1;
xue@1 721 }
xue@1 722 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 723 for (int j=0; j<HWid; j++)
xue@1 724 tmp[j]+=fft[j];
xue@1 725
xue@1 726 ind=Fr*HWid+zero; //Fr*HWid=size1-res, ind=size1-res+zero<size1
xue@1 727 ind_=ind+HWid; //ind_=size1 -res+zero+HWid
xue@1 728 if (ind<0)
xue@1 729 {
xue@1 730 if (!trunc)
xue@1 731 memdoubleadd(pre_buffer, tmp, -ind);
xue@1 732 memcpy(dest, &tmp[-ind], sizeof(double)*(HWid+ind));
xue@1 733 }
xue@1 734 else if (ind_>size1)
xue@1 735 {
xue@1 736 memcpy(&dest[ind], tmp, sizeof(double)*(size1-ind));
xue@1 737 if (!trunc && post_buffer)
xue@1 738 {
xue@1 739 if (ind_>size1+size2+zero)
xue@1 740 memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(size2+zero));
xue@1 741 else
xue@1 742 memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(ind_-size1));
xue@1 743 }
xue@1 744 }
xue@1 745 else
xue@1 746 memcpy(&dest[ind], tmp, sizeof(double)*HWid);
xue@1 747 memcpy(tmp, &fft[HWid], sizeof(double)*HWid);
xue@1 748 Fr++;
xue@1 749 }
xue@1 750
xue@1 751 ind=Fr*HWid+zero;
xue@1 752 ind_=ind+HWid;
xue@1 753
xue@1 754 if (ind<size1)
xue@1 755 {
xue@1 756 if (ind_>size1)
xue@1 757 {
xue@1 758 memcpy(&dest[ind], tmp, sizeof(double)*(size1-ind));
xue@1 759 if (!trunc && post_buffer)
xue@1 760 {
xue@1 761 if (ind_>size1+size2+zero)
xue@1 762 memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(size2+zero));
xue@1 763 else
xue@1 764 memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(ind_-size1));
xue@1 765 }
xue@1 766 }
xue@1 767 else
xue@1 768 memcpy(&dest[ind], tmp, sizeof(double)*HWid);
xue@1 769 }
xue@1 770 else //ind>=size1 => ind_>=size1+size2+zero
xue@1 771 {
xue@1 772 if (!trunc && post_buffer)
xue@1 773 memcpy(&post_buffer[ind-size1], tmp, sizeof(double)*(size1+size2+zero-ind));
xue@1 774 }
xue@1 775
xue@1 776 FreeFFTBuffer(fft);
xue@1 777 delete[] x2;
xue@1 778 delete[] tmp;
xue@1 779 delete[] hbitinv;
xue@1 780 }//FFTConv
xue@1 781
xue@1 782 /*
xue@1 783 function FFTConv: the simplified version using two output buffers instead of three. This is almost
xue@1 784 equivalent to setting zero=-size2 in the three-output-buffer version (so that post_buffer no longer
xue@1 785 exists), except that this version requires size2 (renamed HWid) be a power of 2, and pre_buffer point
xue@1 786 to the END of the storage (so that pre_buffer=dest automatically connects the two buffers in a
xue@1 787 continuous memory block).
xue@1 788
xue@1 789 In: source1[size1]: convolvend
xue@1 790 source2[HWid]: second convolved, HWid be a power of 2
xue@1 791 pre_buffer[-HWid:-1]: buffer hosting values to be overlap-added to the start of the result.
xue@1 792 Out: dest[size1]: main output buffer, now hosting end part of the result (after HWid samples).
xue@1 793 pre_buffer[-HWid:-1]: now updated by added the start of the result
xue@1 794
xue@1 795 No return value.
xue@1 796 */
xue@1 797 void FFTConv(double* dest, double* source1, int size1, double* source2, int HWid, double* pre_buffer)
xue@1 798 {
xue@1 799 int Wid=HWid*2;
xue@1 800 int order=log2(Wid);
xue@1 801 int Fr=size1/HWid;
xue@1 802 int res=size1-HWid*Fr;
xue@1 803
xue@1 804 AllocateFFTBuffer(Wid, fft, w, x1);
xue@1 805 cdouble *x2=new cdouble[Wid];
xue@1 806 double *tmp=new double[HWid];
xue@1 807 int* hbitinv=CreateBitInvTable(order-1);
xue@1 808
xue@1 809 memcpy(fft, source2, sizeof(double)*HWid);
xue@1 810 memset(&fft[HWid], 0, sizeof(double)*HWid);
xue@1 811 RFFTC(fft, 0, 0, order, w, x2, hbitinv);
xue@1 812
xue@1 813 double r1, r2, i1, i2;
xue@1 814 for (int i=0; i<Fr; i++)
xue@1 815 {
xue@1 816 memcpy(fft, &source1[i*HWid], sizeof(double)*HWid);
xue@1 817 memset(&fft[HWid], 0, sizeof(double)*HWid);
xue@1 818
xue@1 819 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 820
xue@1 821 for (int j=0; j<Wid; j++)
xue@1 822 {
xue@1 823 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 824 x1[j].x=r1*r2-i1*i2;
xue@1 825 x1[j].y=r1*i2+r2*i1;
xue@1 826 }
xue@1 827 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 828
xue@1 829 if (i==0)
xue@1 830 {
xue@1 831 if (pre_buffer!=NULL)
xue@1 832 {
xue@1 833 double* destl=&pre_buffer[-HWid+1];
xue@1 834 for (int j=0; j<HWid-1; j++) destl[j]+=fft[j];
xue@1 835 }
xue@1 836 }
xue@1 837 else
xue@1 838 {
xue@1 839 for (int j=0; j<HWid-1; j++) tmp[j+1]+=fft[j];
xue@1 840 memcpy(&dest[(i-1)*HWid], tmp, sizeof(double)*HWid);
xue@1 841 }
xue@1 842 memcpy(tmp, &fft[HWid-1], sizeof(double)*HWid);
xue@1 843 }
xue@1 844
xue@1 845 if (res>0)
xue@1 846 {
xue@1 847 if (Fr==0) memset(tmp, 0, sizeof(double)*HWid);
xue@1 848
xue@1 849 memcpy(fft, &source1[Fr*HWid], sizeof(double)*res);
xue@1 850 memset(&fft[res], 0, sizeof(double)*(Wid-res));
xue@1 851
xue@1 852 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 853 for (int j=0; j<Wid; j++)
xue@1 854 {
xue@1 855 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 856 x1[j].x=r1*r2-i1*i2;
xue@1 857 x1[j].y=r1*i2+r2*i1;
xue@1 858 }
xue@1 859 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 860
xue@1 861 if (Fr==0)
xue@1 862 {
xue@1 863 if (pre_buffer!=NULL)
xue@1 864 {
xue@1 865 double* destl=&pre_buffer[-HWid+1];
xue@1 866 for (int j=0; j<HWid-1; j++) destl[j]+=fft[j];
xue@1 867 }
xue@1 868 }
xue@1 869 else
xue@1 870 {
xue@1 871 for (int j=0; j<HWid-1; j++) tmp[j+1]+=fft[j];
xue@1 872 memcpy(&dest[(Fr-1)*HWid], tmp, sizeof(double)*HWid);
xue@1 873 }
xue@1 874
xue@1 875 memcpy(&dest[Fr*HWid], &fft[HWid-1], sizeof(double)*res);
xue@1 876 }
xue@1 877 else
xue@1 878 memcpy(&dest[(Fr-1)*HWid], tmp, sizeof(double)*HWid);
xue@1 879
xue@1 880 FreeFFTBuffer(fft);
xue@1 881 delete[] x2; delete[] tmp; delete[] hbitinv;
xue@1 882 }//FFTConv
xue@1 883
xue@1 884 /*
xue@1 885 function FFTConv: fast convolution of two series by FFT overlap-add. Same as the three-output-buffer
xue@1 886 version above but using integer output buffers as well as integer source1.
xue@1 887
xue@1 888 In: source1[size1]: convolvend
xue@1 889 bps: bytes per sample of integer units in source1[].
xue@1 890 source2[size2]: second convolvend
xue@1 891 zero: position of first point in convoluton result, relative to main output buffer.
xue@1 892 pre_buffer[-zero]: buffer hosting values to be overlap-added to the start of the result.
xue@1 893 Out: dest[size1]: the middle part of convolution result
xue@1 894 pre_buffer[-zero]: now updated by adding beginning part of the convolution result
xue@1 895 post_buffer[size2+zero]: end part of the convolution result
xue@1 896
xue@1 897 No return value. Identical dest and source1 allowed.
xue@1 898 */
xue@1 899 void FFTConv(unsigned char* dest, unsigned char* source1, int bps, int size1, double* source2, int size2, int zero, unsigned char* pre_buffer, unsigned char* post_buffer)
xue@1 900 {
xue@1 901 int order=log2(size2-1)+1+1;
xue@1 902 int Wid=1<<order;
xue@1 903 int HWid=Wid/2;
xue@1 904 int Fr=size1/HWid;
xue@1 905 int res=size1-HWid*Fr;
xue@1 906 bool trunc=false;
xue@1 907 if (zero<-size2+1 || zero>0) zero=-size2/2, trunc=true;
xue@1 908 if (pre_buffer==NULL || (post_buffer==NULL && size2+zero!=0)) trunc=true;
xue@1 909
xue@1 910 AllocateFFTBuffer(Wid, fft, w, x1);
xue@1 911 cdouble* x2=new cdouble[Wid];
xue@1 912 double* tmp=new double[HWid];
xue@1 913 memset(tmp, 0, sizeof(double)*HWid);
xue@1 914 int* hbitinv=CreateBitInvTable(order-1);
xue@1 915
xue@1 916 memcpy(fft, source2, sizeof(double)*size2);
xue@1 917 memset(&fft[size2], 0, sizeof(double)*(Wid-size2));
xue@1 918 RFFTC(fft, 0, 0, order, w, x2, hbitinv);
xue@1 919
xue@1 920 double r1, r2, i1, i2;
xue@1 921 int ind, ind_;
xue@1 922 for (int i=0; i<Fr; i++)
xue@1 923 {
xue@1 924 IntToDouble(fft, &source1[i*HWid*bps], bps, HWid);
xue@1 925 memset(&fft[HWid], 0, sizeof(double)*HWid);
xue@1 926
xue@1 927 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 928
xue@1 929 for (int j=0; j<Wid; j++)
xue@1 930 {
xue@1 931 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 932 x1[j].x=r1*r2-i1*i2;
xue@1 933 x1[j].y=r1*i2+r2*i1;
xue@1 934 }
xue@1 935 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 936 for (int j=0; j<HWid; j++) tmp[j]+=fft[j];
xue@1 937
xue@1 938 ind=i*HWid+zero; //(i+1)*HWid<=size1
xue@1 939 ind_=ind+HWid; //ind_=(i+1)*HWid+zero<=size1
xue@1 940 if (ind<0)
xue@1 941 {
xue@1 942 if (!trunc)
xue@1 943 DoubleToIntAdd(pre_buffer, bps, tmp, -ind);
xue@1 944 DoubleToInt(dest, bps, &tmp[-ind], HWid+ind);
xue@1 945 }
xue@1 946 else
xue@1 947 DoubleToInt(&dest[ind*bps], bps, tmp, HWid);
xue@1 948 memcpy(tmp, &fft[HWid], sizeof(double)*HWid);
xue@1 949 }
xue@1 950
xue@1 951 if (res>0)
xue@1 952 {
xue@1 953 IntToDouble(fft, &source1[Fr*HWid*bps], bps, res);
xue@1 954 memset(&fft[res], 0, sizeof(double)*(Wid-res));
xue@1 955
xue@1 956 RFFTC(fft, 0, 0, order, w, x1, hbitinv);
xue@1 957
xue@1 958 for (int j=0; j<Wid; j++)
xue@1 959 {
xue@1 960 r1=x1[j].x, r2=x2[j].x, i1=x1[j].y, i2=x2[j].y;
xue@1 961 x1[j].x=r1*r2-i1*i2;
xue@1 962 x1[j].y=r1*i2+r2*i1;
xue@1 963 }
xue@1 964 CIFFTR(x1, order, w, fft, hbitinv);
xue@1 965 for (int j=0; j<HWid; j++)
xue@1 966 tmp[j]+=fft[j];
xue@1 967
xue@1 968 ind=Fr*HWid+zero; //Fr*HWid=size1-res, ind=size1-res+zero<size1
xue@1 969 ind_=ind+HWid; //ind_=size1 -res+zero+HWid
xue@1 970 if (ind<0)
xue@1 971 {
xue@1 972 if (!trunc)
xue@1 973 DoubleToIntAdd(pre_buffer, bps, tmp, -ind);
xue@1 974 DoubleToInt(dest, bps, &tmp[-ind], HWid+ind);
xue@1 975 }
xue@1 976 else if (ind_>size1)
xue@1 977 {
xue@1 978 DoubleToInt(&dest[ind*bps], bps, tmp, size1-ind);
xue@1 979 if (!trunc && post_buffer)
xue@1 980 {
xue@1 981 if (ind_>size1+size2+zero)
xue@1 982 DoubleToInt(post_buffer, bps, &tmp[size1-ind], size2+zero);
xue@1 983 else
xue@1 984 DoubleToInt(post_buffer, bps, &tmp[size1-ind], ind_-size1);
xue@1 985 }
xue@1 986 }
xue@1 987 else
xue@1 988 DoubleToInt(&dest[ind*bps], bps, tmp, HWid);
xue@1 989 memcpy(tmp, &fft[HWid], sizeof(double)*HWid);
xue@1 990 Fr++;
xue@1 991 }
xue@1 992
xue@1 993 ind=Fr*HWid+zero;
xue@1 994 ind_=ind+HWid;
xue@1 995
xue@1 996 if (ind<size1)
xue@1 997 {
xue@1 998 if (ind_>size1)
xue@1 999 {
xue@1 1000 DoubleToInt(&dest[ind*bps], bps, tmp, size1-ind);
xue@1 1001 if (!trunc && post_buffer)
xue@1 1002 {
xue@1 1003 if (ind_>size1+size2+zero)
xue@1 1004 DoubleToInt(post_buffer, bps, &tmp[size1-ind], size2+zero);
xue@1 1005 else
xue@1 1006 DoubleToInt(post_buffer, bps, &tmp[size1-ind], ind_-size1);
xue@1 1007 }
xue@1 1008 }
xue@1 1009 else
xue@1 1010 DoubleToInt(&dest[ind*bps], bps, tmp, HWid);
xue@1 1011 }
xue@1 1012 else //ind>=size1 => ind_>=size1+size2+zero
xue@1 1013 {
xue@1 1014 if (!trunc && post_buffer)
xue@1 1015 DoubleToInt(&post_buffer[(ind-size1)*bps], bps, tmp, size1+size2+zero-ind);
xue@1 1016 }
xue@1 1017
xue@1 1018 FreeFFTBuffer(fft);
xue@1 1019 delete[] x2;
xue@1 1020 delete[] tmp;
xue@1 1021 delete[] hbitinv;
xue@1 1022 }//FFTConv
xue@1 1023
xue@1 1024 //---------------------------------------------------------------------------
xue@1 1025 /*
xue@1 1026 function FFTFilter: FFT with cosine-window overlap-add: This FFT filter is not an actural LTI system,
xue@1 1027 but an block processing with overlap-add. In this function the blocks are overlapped by 50% and summed
xue@1 1028 up with Hann windowing.
xue@1 1029
xue@1 1030 In: data[Count]: input data
xue@1 1031 Wid: DFT size
xue@1 1032 On, Off: cut-off frequencies of FFT filter. On<Off: band-pass; On>Off: band-stop.
xue@1 1033 Out: dataout[Count]: filtered data
xue@1 1034
xue@1 1035 No return value. Identical data and dataout allowed
xue@1 1036 */
xue@1 1037 void FFTFilter(double* dataout, double* data, int Count, int Wid, int On, int Off)
xue@1 1038 {
xue@1 1039 int Order=log2(Wid);
xue@1 1040 int HWid=Wid/2;
xue@1 1041 int Fr=(Count-Wid)/HWid+1;
xue@1 1042 AllocateFFTBuffer(Wid, ldata, w, x);
xue@1 1043
xue@1 1044 double* win=new double[Wid];
xue@1 1045 for (int i=0; i<Wid; i++) win[i]=sqrt((1-cos(2*M_PI*i/Wid))/2);
xue@1 1046 double* tmpdata=new double[HWid];
xue@1 1047 memset(tmpdata, 0, HWid*sizeof(double));
xue@1 1048
xue@1 1049 for (int i=0; i<Fr; i++)
xue@1 1050 {
xue@1 1051 memcpy(ldata, &data[i*HWid], Wid*sizeof(double));
xue@1 1052 if (i>0)
xue@1 1053 for (int k=0; k<HWid; k++)
xue@1 1054 ldata[k]=ldata[k]*win[k];
xue@1 1055 for (int k=HWid; k<Wid; k++)
xue@1 1056 ldata[k]=ldata[k]*win[k];
xue@1 1057
xue@1 1058 RFFTC(ldata, NULL, NULL, Order, w, x, 0);
xue@1 1059
xue@1 1060 if (On<Off) //band pass: keep [On, Off) and set other bins to zero
xue@1 1061 {
xue@1 1062 memset(x, 0, On*sizeof(cdouble));
xue@1 1063 if (On>=1)
xue@1 1064 memset(&x[Wid-On+1], 0, (On-1)*sizeof(cdouble));
xue@1 1065 if (Off*2<=Wid)
xue@1 1066 memset(&x[Off], 0, (Wid-Off*2+1)*sizeof(cdouble));
xue@1 1067 }
xue@1 1068 else //band stop: set [Off, On) to zero.
xue@1 1069 {
xue@1 1070 memset(&x[Off], 0, sizeof(cdouble)*(On-Off));
xue@1 1071 memset(&x[Wid-On+1], 0, sizeof(double)*(On-Off));
xue@1 1072 }
xue@1 1073
xue@1 1074 CIFFTR(x, Order, w, ldata);
xue@1 1075
xue@1 1076 if (i>0) for (int k=0; k<HWid; k++) ldata[k]=ldata[k]*win[k];
xue@1 1077 for (int k=HWid; k<Wid; k++) ldata[k]=ldata[k]*win[k];
xue@1 1078
xue@1 1079 memcpy(&dataout[i*HWid], tmpdata, HWid*sizeof(double));
xue@1 1080 for (int k=0; k<HWid; k++) dataout[i*HWid+k]+=ldata[k];
xue@1 1081 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 1082 }
xue@1 1083
xue@1 1084 memcpy(&dataout[Fr*HWid], tmpdata, HWid*sizeof(double));
xue@1 1085 memset(&dataout[Fr*HWid+HWid], 0, (Count-Fr*HWid-HWid)*sizeof(double));
xue@1 1086
xue@1 1087 delete[] win;
xue@1 1088 delete[] tmpdata;
xue@1 1089 FreeFFTBuffer(ldata);
xue@1 1090 }//FFTFilter
xue@1 1091
xue@1 1092 /*
xue@1 1093 funtion FFTFilterOLA: FFTFilter with overlap-add support. This is a true LTI filter whose impulse
xue@1 1094 response is constructed using IFFT. The filtering is implemented by fast convolution.
xue@1 1095
xue@1 1096 In: data[Count]: input data
xue@1 1097 Wid: FFT size
xue@1 1098 On, Off: cut-off frequencies, in bins, of the filter
xue@1 1099 pre_buffer[Wid]: buffer hosting sampled to be added with the start of output
xue@1 1100 Out: dataout[Count]: main output buffer, hosting the last $Count samples of output.
xue@1 1101 pre_buffer[Wid]: now updated by adding the first Wid samples of output
xue@1 1102
xue@1 1103 No return value. The complete output contains Count+Wid effective samples (including final 0); firt
xue@1 1104 $Wid are added to pre_buffer[], next Count samples saved to dataout[].
xue@1 1105 */
xue@1 1106 void FFTFilterOLA(double* dataout, double* data, int Count, int Wid, int On, int Off, double* pre_buffer)
xue@1 1107 {
xue@1 1108 AllocateFFTBuffer(Wid, spec, w, x);
xue@1 1109 memset(x, 0, sizeof(cdouble)*Wid);
xue@1 1110 for (int i=On+1; i<Off; i++) x[i].x=x[Wid-i].x=1-2*(i%2);
xue@1 1111 CIFFTR(x, log2(Wid), w, spec);
xue@1 1112 FFTConv(dataout, data, Count, spec, Wid, -Wid, pre_buffer, NULL);
xue@1 1113 FreeFFTBuffer(spec);
xue@1 1114 }//FFTFilterOLA
xue@1 1115 //version for integer input and output, where BytesPerSample specifies the integer format.
xue@1 1116 void FFTFilterOLA(unsigned char* dataout, unsigned char* data, int BytesPerSample, int Count, int Wid, int On, int Off, unsigned char* pre_buffer)
xue@1 1117 {
xue@1 1118 AllocateFFTBuffer(Wid, spec, w, x);
xue@1 1119 memset(x, 0, sizeof(cdouble)*Wid);
xue@1 1120 for (int i=On+1; i<Off; i++) x[i].x=x[Wid-i].x=1-2*(i%2);
xue@1 1121 CIFFTR(x, log2(Wid), w, spec);
xue@1 1122 FFTConv(dataout, data, BytesPerSample, Count, spec, Wid, -Wid, pre_buffer, NULL);
xue@1 1123 FreeFFTBuffer(spec);
xue@1 1124 }//FFTFilterOLA
xue@1 1125
xue@1 1126 /*
xue@1 1127 function FFTFilterOLA: FFT filter with overlap-add support.
xue@1 1128
xue@1 1129 In: data[Count]: input data
xue@1 1130 amp[0:HWid]: amplitude response
xue@1 1131 ph[0:HWid]: phase response, where ph[0]=ph[HWid]=0;
xue@1 1132 pre_buffer[Wid]: buffer hosting sampled to be added to the beginning of the output
xue@1 1133 Out: dataout[Count]: main output buffer, hosting the middle $Count samples of output.
xue@1 1134 pre_buffer[Wid]: now updated by adding the first Wid/2 samples of output
xue@1 1135
xue@1 1136 No return value.
xue@1 1137 */
xue@1 1138 void FFTFilterOLA(double* dataout, double* data, int Count, double* amp, double* ph, int Wid, double* pre_buffer)
xue@1 1139 {
xue@1 1140 int HWid=Wid/2;
xue@1 1141 AllocateFFTBuffer(Wid, spec, w, x);
xue@1 1142 x[0].x=amp[0], x[0].y=0;
xue@1 1143 for (int i=1; i<HWid; i++)
xue@1 1144 {
xue@1 1145 x[i].x=x[Wid-i].x=amp[i]*cos(ph[i]);
xue@1 1146 x[i].y=amp[i]*sin(ph[i]);
xue@1 1147 x[Wid-i].y=-x[i].y;
xue@1 1148 }
xue@1 1149 x[HWid].x=amp[HWid], x[HWid].y=0;
xue@1 1150 CIFFTR(x, log2(Wid), w, spec);
xue@1 1151 FFTConv(dataout, data, Count, spec, Wid, -Wid, pre_buffer, NULL);
xue@1 1152 FreeFFTBuffer(spec);
xue@1 1153 }//FFTFilterOLA
xue@1 1154
xue@1 1155 /*
xue@1 1156 function FFTMask: masks a band of a signal with noise
xue@1 1157
xue@1 1158 In: data[Count]: input signal
xue@1 1159 DigiOn, DigiOff: cut-off frequences of the band to mask
xue@1 1160 maskcoef: masking noise amplifier. If set to 1 than the mask level is set to the highest signal
xue@1 1161 level in the masking band.
xue@1 1162 Out: dataout[Count]: output data
xue@1 1163
xue@1 1164 No return value.
xue@1 1165 */
xue@1 1166 double FFTMask(double* dataout, double* data, int Count, int Wid, double DigiOn, double DigiOff, double maskcoef)
xue@1 1167 {
xue@1 1168 int Order=log2(Wid);
xue@1 1169 int HWid=Wid/2;
xue@1 1170 int Fr=(Count-Wid)/HWid+1;
xue@1 1171 int On=Wid*DigiOn, Off=Wid*DigiOff;
xue@1 1172 AllocateFFTBuffer(Wid, ldata, w, x);
xue@1 1173
xue@1 1174 double* winhann=new double[Wid];
xue@1 1175 double* winhamm=new double[Wid];
xue@1 1176 for (int i=0; i<Wid; i++)
xue@1 1177 {winhamm[i]=0.54-0.46*cos(2*M_PI*i/Wid); winhann[i]=(1-cos(2*M_PI*i/Wid))/2/winhamm[i];}
xue@1 1178 double* tmpdata=new double[HWid];
xue@1 1179 memset(tmpdata, 0, HWid*sizeof(double));
xue@1 1180 double max, randfi;
xue@1 1181
xue@1 1182 max=0;
xue@1 1183 for (int i=0; i<Fr; i++)
xue@1 1184 {
xue@1 1185 memcpy(ldata, &data[i*HWid], Wid*sizeof(double));
xue@1 1186 if (i>0)
xue@1 1187 for (int k=0; k<HWid; k++)
xue@1 1188 ldata[k]=ldata[k]*winhamm[k];
xue@1 1189 for (int k=HWid; k<Wid; k++)
xue@1 1190 ldata[k]=ldata[k]*winhamm[k];
xue@1 1191
xue@1 1192 RFFTC(ldata, ldata, NULL, Order, w, x, 0);
xue@1 1193
xue@1 1194 for (int k=On; k<Off; k++)
xue@1 1195 {
xue@1 1196 x[k].x=x[Wid-k].x=x[k].y=x[Wid-k].y=0;
xue@1 1197 if (max<ldata[k]) max=ldata[k];
xue@1 1198 }
xue@1 1199
xue@1 1200 CIFFTR(x, Order, w, ldata);
xue@1 1201
xue@1 1202 if (i>0)
xue@1 1203 for (int k=0; k<HWid; k++) ldata[k]=ldata[k]*winhann[k];
xue@1 1204 for (int k=HWid; k<Wid; k++) ldata[k]=ldata[k]*winhann[k];
xue@1 1205
xue@1 1206 for (int k=0; k<HWid; k++) tmpdata[k]+=ldata[k];
xue@1 1207 memcpy(&dataout[i*HWid], tmpdata, HWid*sizeof(double));
xue@1 1208 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 1209 }
xue@1 1210 memcpy(&dataout[Fr*HWid], tmpdata, HWid*sizeof(double));
xue@1 1211
xue@1 1212 max*=maskcoef;
xue@1 1213
xue@1 1214 for (int i=0; i<Wid; i++)
xue@1 1215 winhann[i]=winhann[i]*winhamm[i];
xue@1 1216
xue@1 1217 for (int i=0; i<Fr; i++)
xue@1 1218 {
xue@1 1219 memset(x, 0, sizeof(cdouble)*Wid);
xue@1 1220 for (int k=On; k<Off; k++)
xue@1 1221 {
xue@1 1222 randfi=rand()*M_PI*2/RAND_MAX;
xue@1 1223 x[k].x=x[Wid-k].x=max*cos(randfi);
xue@1 1224 x[k].y=max*sin(randfi);
xue@1 1225 x[Wid-k].y=-x[k].y;
xue@1 1226 }
xue@1 1227
xue@1 1228 CIFFTR(x, Order, w, ldata);
xue@1 1229
xue@1 1230 if (i>0)
xue@1 1231 for (int k=0; k<HWid; k++)
xue@1 1232 ldata[k]=ldata[k]*winhann[k];
xue@1 1233 for (int k=HWid; k<Wid; k++)
xue@1 1234 ldata[k]=ldata[k]*winhann[k];
xue@1 1235
xue@1 1236 for (int k=0; k<Wid; k++) dataout[i*HWid+k]+=ldata[k];
xue@1 1237 }
xue@1 1238
xue@1 1239 memset(&dataout[Fr*HWid+HWid], 0, (Count-Fr*HWid-HWid)*sizeof(double));
xue@1 1240
xue@1 1241 delete[] winhann;
xue@1 1242 delete[] winhamm;
xue@1 1243 delete[] tmpdata;
xue@1 1244 FreeFFTBuffer(ldata);
xue@1 1245
xue@1 1246 return max;
xue@1 1247 }//FFTMask
xue@1 1248
xue@1 1249 //---------------------------------------------------------------------------
xue@1 1250 /*
xue@1 1251 function FindInc: find the element in ordered list data that is closest to value.
xue@1 1252
xue@1 1253 In: data[Count]: a ordered list
xue@1 1254 value: the value to locate in the list
xue@1 1255
xue@1 1256 Returns the index of the element in the sorted list which is closest to $value.
xue@1 1257 */
xue@1 1258 int FindInc(double value, double* data, int Count)
xue@1 1259 {
xue@1 1260 if (value>=data[Count-1]) return Count-1;
xue@1 1261 if (value<data[0]) return 0;
xue@1 1262 int end=InsertInc(value, data, Count, false);
xue@1 1263 if (fabs(value-data[end-1])<fabs(value-data[end])) return end-1;
xue@1 1264 else return end;
xue@1 1265 }//FindInc
xue@1 1266
xue@1 1267 //---------------------------------------------------------------------------
xue@1 1268 /*
xue@1 1269 function Gaussian: Gaussian function
xue@1 1270
xue@1 1271 In: Vector[Dim]: a vector
xue@1 1272 Mean[Dim]: mean of Gaussian function
xue@1 1273 Dev[Fim]: diagonal autocorrelation matrix of Gaussian function
xue@1 1274
xue@1 1275 Returns the value of Gaussian function at Vector[].
xue@1 1276 */
xue@1 1277 double Gaussian(int Dim, double* Vector, double* Mean, double* Dev)
xue@1 1278 {
xue@1 1279 double bmt=0, tmp;
xue@1 1280 for (int dim=0; dim<Dim; dim++)
xue@1 1281 {
xue@1 1282 tmp=Vector[dim]-Mean[dim];
xue@1 1283 bmt+=tmp*tmp/Dev[dim];
xue@1 1284 }
xue@1 1285 bmt=-bmt/2;
xue@1 1286 tmp=log(Dev[0]);
xue@1 1287 for (int dim=1; dim<Dim; dim++) tmp+=log(Dev[dim]);
xue@1 1288 bmt-=tmp/2;
xue@1 1289 bmt-=Dim*log(M_PI*2)/2;
xue@1 1290 bmt=exp(bmt);
xue@1 1291 return bmt;
xue@1 1292 }//Gaussian
xue@1 1293
xue@1 1294
xue@1 1295 //---------------------------------------------------------------------------
xue@1 1296 /*
xue@1 1297 function Hamming: calculates the amplitude spectrum of Hamming window at a given frequency
xue@1 1298
xue@1 1299 In: f: frequency
xue@1 1300 T: size of Hamming window
xue@1 1301
xue@1 1302 Returns the amplitude spectrum at specified frequency.
xue@1 1303 */
xue@1 1304 double Hamming(double f, double T)
xue@1 1305 {
xue@1 1306 double omg0=2*M_PI/T;
xue@1 1307 double omg=f*2*M_PI;
xue@1 1308 cdouble c1, c2, c3;
xue@1 1309 cdouble nj(0, -1);
xue@1 1310 cdouble pj(0, 1);
xue@1 1311 double a=0.54, b=0.46;
xue@1 1312
xue@1 1313 cdouble c=1.0-exp(nj*T*omg);
xue@1 1314 double half=0.5;
xue@1 1315
xue@1 1316 if (fabs(omg)<1e-100)
xue@1 1317 c1=a*T;
xue@1 1318 else
xue@1 1319 c1=a*c/(pj*omg);
xue@1 1320
xue@1 1321 if (fabs(omg+omg0)<1e-100)
xue@1 1322 c2=b*0.5*T;
xue@1 1323 else
xue@1 1324 c2=c*b*half/(nj*cdouble(omg+omg0));
xue@1 1325
xue@1 1326 if (fabs(omg-omg0)<1e-100)
xue@1 1327 c3=b*0.5*T;
xue@1 1328 else
xue@1 1329 c3=b*c*half/(nj*cdouble(omg-omg0));
xue@1 1330
xue@1 1331 c=c1+c2+c3;
xue@1 1332 return abs(c);
xue@1 1333 }//Hamming*/
xue@1 1334
xue@1 1335 //---------------------------------------------------------------------------
xue@1 1336 /*
xue@1 1337 function HannSq: computes the square norm of Hann window spectrum (window-size-normalized)
xue@1 1338
xue@1 1339 In: x: frequency, in bins
xue@1 1340 N: size of Hann window
xue@1 1341
xue@1 1342 Return the square norm.
xue@1 1343 */
xue@1 1344 double HannSq(double x, double N)
xue@1 1345 {
xue@1 1346 double re, im;
xue@1 1347 double pim=M_PI*x;
xue@1 1348 double pimf=pim/N;
xue@1 1349 double pif=M_PI/N;
xue@1 1350
xue@1 1351 double sinpim=sin(pim);
xue@1 1352 double sinpimf=sin(pimf);
xue@1 1353 double sinpimplus1f=sin(pimf+pif);
xue@1 1354 double sinpimminus1f=sin(pimf-pif);
xue@1 1355
xue@1 1356 double spmdivbyspmf, spmdivbyspmpf, spmdivbyspmmf;
xue@1 1357
xue@1 1358 if (sinpimf==0)
xue@1 1359 spmdivbyspmf=N, spmdivbyspmpf=spmdivbyspmmf=0;
xue@1 1360 else if (sinpimplus1f==0)
xue@1 1361 spmdivbyspmpf=-N, spmdivbyspmf=spmdivbyspmmf=0;
xue@1 1362 else if (sinpimminus1f==0)
xue@1 1363 spmdivbyspmmf=-N, spmdivbyspmf=spmdivbyspmpf=0;
xue@1 1364 else
xue@1 1365 spmdivbyspmf=sinpim/sinpimf, spmdivbyspmpf=sinpim/sinpimplus1f, spmdivbyspmmf=sinpim/sinpimminus1f;
xue@1 1366
xue@1 1367 re=0.5*spmdivbyspmf-0.25*cos(pif)*(spmdivbyspmpf+spmdivbyspmmf);
xue@1 1368 im=0.25*sin(pif)*(-spmdivbyspmpf+spmdivbyspmmf);
xue@1 1369
xue@1 1370 return (re*re+im*im)/(N*N);
xue@1 1371 }//HannSq
xue@1 1372
xue@1 1373 /*
xue@1 1374 function Hann: computes the Hann window amplitude spectrum (window-size-normalized).
xue@1 1375
xue@1 1376 In: x: frequency, in bins
xue@1 1377 N: size of Hann window
xue@1 1378
xue@1 1379 Return the amplitude spectrum evaluated at x. Maximum 0.5 is reached at x=0. Time 2 to normalize
xue@1 1380 maximum to 1.
xue@1 1381 */
xue@1 1382 double Hann(double x, double N)
xue@1 1383 {
xue@1 1384 double pim=M_PI*x;
xue@1 1385 double pif=M_PI/N;
xue@1 1386 double pimf=pif*x;
xue@1 1387
xue@1 1388 double sinpim=sin(pim);
xue@1 1389 double tanpimf=tan(pimf);
xue@1 1390 double tanpimplus1f=tan(pimf+pif);
xue@1 1391 double tanpimminus1f=tan(pimf-pif);
xue@1 1392
xue@1 1393 double spmdivbyspmf, spmdivbyspmpf, spmdivbyspmmf;
xue@1 1394
xue@1 1395 if (fabs(tanpimf)<1e-10)
xue@1 1396 spmdivbyspmf=N, spmdivbyspmpf=spmdivbyspmmf=0;
xue@1 1397 else if (fabs(tanpimplus1f)<1e-10)
xue@1 1398 spmdivbyspmpf=-N, spmdivbyspmf=spmdivbyspmmf=0;
xue@1 1399 else if (fabs(tanpimminus1f)<1e-10)
xue@1 1400 spmdivbyspmmf=-N, spmdivbyspmf=spmdivbyspmpf=0;
xue@1 1401 else
xue@1 1402 spmdivbyspmf=sinpim/tanpimf, spmdivbyspmpf=sinpim/tanpimplus1f, spmdivbyspmmf=sinpim/tanpimminus1f;
xue@1 1403
xue@1 1404 double result=0.5*spmdivbyspmf-0.25*(spmdivbyspmpf+spmdivbyspmmf);
xue@1 1405
xue@1 1406 return result/N;
xue@1 1407 }//HannC
xue@1 1408
xue@1 1409 /*
xue@1 1410 function HxPeak2: fine spectral peak detection. This does detection and high-precision LSE estimation
xue@1 1411 in one go. However, since in practise most peaks are spurious, LSE estimation is not necessary on
xue@1 1412 them. Accordingly, HxPeak2 is deprecated in favour of faster but coarser peak picking methods, such as
xue@1 1413 QIFFT, which leaves fine estimation to a later stage of processing.
xue@1 1414
xue@1 1415 In: F, dF, ddF: pointers to functions that compute LSE peak energy for, plus its 1st and 2nd
xue@1 1416 derivatives against, a given frequency.
xue@1 1417 params: pointer to a data structure (l_hx) hosting input data fed to F, dF, and ddF
xue@1 1418 (st, en): frequency range, in bins, to search for peaks in
xue@1 1419 epf: convergence detection threshold
xue@1 1420 Out: hps[return value]: peak frequencies
xue@1 1421 vps[return value]; peak amplitudes
xue@1 1422
xue@1 1423 Returns the number of peaks detected.
xue@1 1424 */
xue@1 1425 int HxPeak2(double*& hps, double*& vhps, double (*F)(double, void*), double (*dF)(double, void*), double(*ddF)(double, void*), void* params, double st, double en, double epf)
xue@1 1426 {
xue@1 1427 struct l_hx {int N; union {double B; struct {int k1; int k2;};}; cdouble* x; double dhxpeak; double hxpeak;} *p=(l_hx *)params;
Chris@3 1428 int dfshift=offsetof(l_hx, dhxpeak);
Chris@3 1429 int fshift=offsetof(l_hx, hxpeak);
xue@1 1430 double B=p->B;
xue@1 1431 int count=0;
xue@1 1432
xue@1 1433 int den=ceil(en), dst=floor(st);
xue@1 1434 if (den-dst<3) den++, dst--;
xue@1 1435 if (den-dst<3) den++, dst--;
xue@1 1436 if (dst<1) dst=1;
xue@1 1437
xue@1 1438 double step=0.5;
xue@1 1439 int num=(den-dst)/step+1;
xue@1 1440 bool allochps=false, allocvhps=false;
xue@1 1441 if (hps==NULL) allochps=true, hps=new double[num];
xue@1 1442 if (vhps==NULL) allocvhps=true, vhps=new double[num];
xue@1 1443
xue@1 1444 {
xue@1 1445 double* inp=new double[num];
xue@1 1446 for (int i=0; i<num; i++)
xue@1 1447 {
xue@1 1448 double lf=dst+step*i;
xue@1 1449 p->k1=ceil(lf-B); if (p->k1<0) p->k1=0;
xue@1 1450 p->k2=floor(lf+B); if (p->k2>=p->N/2) p->k2=p->N/2-1;
xue@1 1451 inp[i]=F(lf, params);
xue@1 1452 }
xue@1 1453
xue@1 1454 for (int i=1; i<num-1; i++)
xue@1 1455 {
xue@1 1456 if (inp[i]>=inp[i-1] && inp[i]>=inp[i+1]) //inp[i]=F(dst+step*i)
xue@1 1457 {
xue@1 1458 if (inp[i]==inp[i-1] && inp[i]==inp[i+1]) continue;
xue@1 1459 double fa=dst+step*(i-1), fb=dst+step*(i+1);
xue@1 1460 double ff=dst+step*i;
xue@1 1461 p->k1=ceil(ff-B); if (p->k1<0) p->k1=0;
xue@1 1462 p->k2=floor(ff+B); if (p->k2>=p->N/2) p->k2=p->N/2-1;
xue@1 1463
xue@1 1464 double tmp=Newton1dmax(ff, fa, fb, ddF, params, dfshift, fshift, dF, dfshift, epf);
xue@1 1465
xue@1 1466 //although we have selected inp[i] to be a local maximum, different truncation
xue@1 1467 // of local spectrum implies it may not hold as the truncation of inp[i] is
xue@1 1468 // used for recalculating inp[i-1] and inp[i+1] in init_Newton method. In this
xue@1 1469 // case we retry the sub-maximal frequency to see if it becomes a local maximum
xue@1 1470 // when the spectrum is truncated to centre on it.
xue@1 1471
xue@1 1472 if (tmp==-0.5 || tmp==-0.7) //y(fa)<=y(ff)<y(fb) or y(ff)<y(fa)<y(fb)
xue@1 1473 {
xue@1 1474 tmp=Newton1dmax(fb, ff, 2*fb-ff, ddF, params, dfshift, fshift, dF, dfshift, epf);
xue@1 1475 if (tmp==-0.5 || tmp==-0.7) continue;
xue@1 1476 /*
xue@1 1477 double ff2=(ff+fb)/2;
xue@1 1478 p->k1=ceil(ff2-B); if (p->k1<0) p->k1=0;
xue@1 1479 p->k2=floor(ff2+B); if (p->k2>=p->N/2) p->k2=p->N/2-1;
xue@1 1480 tmp=Newton1dmax(ff2, ff, fb, ddF, params, dfshift, fshift, dF, dfshift, epf);
xue@1 1481 p->k1=ceil(ff-B); if (p->k1<0) p->k1=0;
xue@1 1482 p->k2=floor(ff+B); if (p->k2>=p->N/2) p->k2=p->N/2-1; */
xue@1 1483 }
xue@1 1484 else if (tmp==-0.6 || tmp==-0.8) //y(fb)<=y(ff)<y(fa)
xue@1 1485 {
xue@1 1486 tmp=Newton1dmax(fa, 2*fa-ff, ff, ddF, params, dfshift, fshift, dF, dfshift, epf);
xue@1 1487 if (tmp==-0.6 || tmp==-0.8) continue;
xue@1 1488 }
xue@1 1489 if (tmp<0 /*tmp==-0.5 || tmp==-0.6 || tmp==-1 || tmp==-2 || tmp==-3*/)
xue@1 1490 {
xue@1 1491 Search1Dmax(ff, params, F, dst+step*(i-1), dst+step*(i+1), &vhps[count], epf);
xue@1 1492 }
xue@1 1493 else
xue@1 1494 {
xue@1 1495 vhps[count]=p->hxpeak;
xue@1 1496 }
xue@1 1497 if (ff>=st && ff<=en && ff>dst+step*(i-0.99) && ff<dst+step*(i+0.99))
xue@1 1498 {
xue@1 1499 // if (count==0 || fabs(tmp-hps[count-1])>0.1)
xue@1 1500 // {
xue@1 1501 hps[count]=ff;
xue@1 1502 count++;
xue@1 1503 // }
xue@1 1504 }
xue@1 1505 }
xue@1 1506 }
xue@1 1507 delete[] inp;
xue@1 1508 }
xue@1 1509
xue@1 1510 if (allochps) hps=(double*)realloc(hps, sizeof(double)*count);
xue@1 1511 if (allocvhps) vhps=(double*)realloc(vhps, sizeof(double)*count);
xue@1 1512 return count;
xue@1 1513 }//HxPeak2
xue@1 1514
xue@1 1515 //---------------------------------------------------------------------------
xue@1 1516 /*
xue@1 1517 function InsertDec: inserts value into sorted decreasing list
xue@1 1518
xue@1 1519 In: data[Count]: a sorted decreasing list.
xue@1 1520 value: the value to be added
xue@1 1521 Out: data[Count]: the list with $value inserted if the latter is larger than its last entry, in which
xue@1 1522 case the original last entry is discarded.
xue@1 1523
xue@1 1524 Returns the index where $value is located in data[], or -1 if $value is smaller than or equal to
xue@1 1525 data[Count-1].
xue@1 1526 */
xue@1 1527 int InsertDec(int value, int* data, int Count)
xue@1 1528 {
xue@1 1529 if (Count<=0) return -1;
xue@1 1530 if (value<=data[Count-1]) return -1;
xue@1 1531 if (value>data[0])
xue@1 1532 {
xue@1 1533 memmove(&data[1], &data[0], sizeof(int)*(Count-1));
xue@1 1534 data[0]=value;
xue@1 1535 return 0;
xue@1 1536 }
xue@1 1537
xue@1 1538 //now Count>=2
xue@1 1539 int head=0, end=Count-1, mid;
xue@1 1540
xue@1 1541 //D(head)>=value>D(end)
xue@1 1542 while (end-head>1)
xue@1 1543 {
xue@1 1544 mid=(head+end)/2;
xue@1 1545 if (value<=data[mid]) head=mid;
xue@1 1546 else end=mid;
xue@1 1547 }
xue@1 1548
xue@1 1549 //D(head=end-1)>=value>D(end)
xue@1 1550 memmove(&data[end+1], &data[end], sizeof(int)*(Count-end-1));
xue@1 1551 data[end]=value;
xue@1 1552 return end;
xue@1 1553 }//InsertDec
xue@1 1554 //the double version
xue@1 1555 int InsertDec(double value, double* data, int Count)
xue@1 1556 {
xue@1 1557 if (Count<=0) return -1;
xue@1 1558 if (value<=data[Count-1]) return -1;
xue@1 1559 if (value>data[0])
xue@1 1560 {
xue@1 1561 memmove(&data[1], &data[0], sizeof(double)*(Count-1));
xue@1 1562 data[0]=value;
xue@1 1563 return 0;
xue@1 1564 }
xue@1 1565
xue@1 1566 //now Count>=2
xue@1 1567 int head=0, end=Count-1, mid;
xue@1 1568
xue@1 1569 //D(head)>=value>D(end)
xue@1 1570 while (end-head>1)
xue@1 1571 {
xue@1 1572 mid=(head+end)/2;
xue@1 1573 if (value<=data[mid]) head=mid;
xue@1 1574 else end=mid;
xue@1 1575 }
xue@1 1576
xue@1 1577 //D(head=end-1)>=value>D(end)
xue@1 1578 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1));
xue@1 1579 data[end]=value;
xue@1 1580 return end;
xue@1 1581 }//InsertDec
xue@1 1582
xue@1 1583 /*
xue@1 1584 function InsertDec: inserts value and attached integer into sorted decreasing list
xue@1 1585
xue@1 1586 In: data[Count]: a sorted decreasing list
xue@1 1587 indices[Count]: a list of integers attached to entries of data[]
xue@1 1588 value, index: the value to be added and its attached integer
xue@1 1589 Out: data[Count], indices[Count]: the lists with $value and $index inserted if $value is larger than
xue@1 1590 the last entry of data[], in which case the original last entries are discarded.
xue@1 1591
xue@1 1592 Returns the index where $value is located in data[], or -1 if $value is smaller than or equal to
xue@1 1593 data[Count-1].
xue@1 1594 */
xue@1 1595 int InsertDec(double value, int index, double* data, int* indices, int Count)
xue@1 1596 {
xue@1 1597 if (Count<=0) return -1;
xue@1 1598 if (value<=data[Count-1]) return -1;
xue@1 1599 if (value>data[0])
xue@1 1600 {
xue@1 1601 memmove(&data[1], data, sizeof(double)*(Count-1));
xue@1 1602 memmove(&indices[1], indices, sizeof(int)*(Count-1));
xue@1 1603 data[0]=value, indices[0]=index;
xue@1 1604 return 0;
xue@1 1605 }
xue@1 1606
xue@1 1607 //now Count>=2
xue@1 1608 int head=0, end=Count-1, mid;
xue@1 1609
xue@1 1610 //D(head)>=value>D(end)
xue@1 1611 while (end-head>1)
xue@1 1612 {
xue@1 1613 mid=(head+end)/2;
xue@1 1614 if (value<=data[mid]) head=mid;
xue@1 1615 else end=mid;
xue@1 1616 }
xue@1 1617
xue@1 1618 //D(head=end-1)>=value>D(end)
xue@1 1619 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1));
xue@1 1620 memmove(&indices[end+1], &indices[end], sizeof(int)*(Count-end-1));
xue@1 1621 data[end]=value, indices[end]=index;
xue@1 1622 return end;
xue@1 1623 }//InsertDec
xue@1 1624
xue@1 1625 /*
xue@1 1626 InsertInc: inserts value into sorted increasing list.
xue@1 1627
xue@1 1628 In: data[Count]: a sorted increasing list.
xue@1 1629 Capacity: maximal size of data[]
xue@1 1630 value: the value to be added
xue@1 1631 Compare: pointer to function that compare two values
xue@1 1632 Out: data[Count]: the list with $value inserted. If the original list is full (Count=Capacity) then
xue@1 1633 either $value, or the last entry of data[], whichever is larger, is discarded.
xue@1 1634
xue@1 1635 Returns the index where $value is located in data[], or -1 if it is not inserted, which happens if
xue@1 1636 Count=Capacity and $value is larger than or equal to the last entry in data[Capacity].
xue@1 1637 */
xue@1 1638 int InsertInc(void* value, void** data, int Count, int Capacity, int (*Compare)(void*, void*))
xue@1 1639 {
xue@1 1640 if (Capacity<=0) return -1;
xue@1 1641 if (Count>Capacity) Count=Capacity;
xue@1 1642
xue@1 1643 //Compare(A,B)<0 if A<B, =0 if A=B, >0 if A>B
xue@1 1644 int PosToInsert;
xue@1 1645 if (Count==0) PosToInsert=0;
xue@1 1646 else if (Compare(value, data[Count-1])>0) PosToInsert=Count;
xue@1 1647 else if (Compare(value, data[0])<0) PosToInsert=0;
xue@1 1648 else
xue@1 1649 {
xue@1 1650 //now Count>=2
xue@1 1651 int head=0, end=Count-1, mid;
xue@1 1652
xue@1 1653 //D(head)<=value<D(end)
xue@1 1654 while (end-head>1)
xue@1 1655 {
xue@1 1656 mid=(head+end)/2;
xue@1 1657 if (Compare(value, data[mid])>=0) head=mid;
xue@1 1658 else end=mid;
xue@1 1659 }
xue@1 1660 //D(head=end-1)<=value<D(end)
xue@1 1661 PosToInsert=end;
xue@1 1662 }
xue@1 1663
xue@1 1664 if (Count<Capacity)
xue@1 1665 {
xue@1 1666 memmove(&data[PosToInsert+1], &data[PosToInsert], sizeof(void*)*(Count-PosToInsert));
xue@1 1667 data[PosToInsert]=value;
xue@1 1668 }
xue@1 1669 else //Count==Capacity
xue@1 1670 {
xue@1 1671 if (PosToInsert>=Capacity) return -1;
xue@1 1672 memmove(&data[PosToInsert+1], &data[PosToInsert], sizeof(void*)*(Count-PosToInsert-1));
xue@1 1673 data[PosToInsert]=value;
xue@1 1674 }
xue@1 1675 return PosToInsert;
xue@1 1676 }//InsertInc
xue@1 1677
xue@1 1678 /*
xue@1 1679 function InsertInc: inserts value into sorted increasing list
xue@1 1680
xue@1 1681 In: data[Count]: a sorted increasing list.
xue@1 1682 value: the value to be added
xue@1 1683 doinsert: specifies whether the actually insertion is to be performed
xue@1 1684 Out: data[Count]: the list with $value inserted if the latter is smaller than its last entry, in which
xue@1 1685 case the original last entry of data[] is discarded.
xue@1 1686
xue@1 1687 Returns the index where $value is located in data[], or -1 if value is larger than or equal to
xue@1 1688 data[Count-1].
xue@1 1689 */
xue@1 1690 int InsertInc(double value, double* data, int Count, bool doinsert)
xue@1 1691 {
xue@1 1692 if (Count<=0) return -1;
xue@1 1693 if (value>=data[Count-1]) return -1;
xue@1 1694 if (value<data[0])
xue@1 1695 {
xue@1 1696 memmove(&data[1], &data[0], sizeof(double)*(Count-1));
xue@1 1697 if (doinsert) data[0]=value;
xue@1 1698 return 0;
xue@1 1699 }
xue@1 1700
xue@1 1701 //now Count>=2
xue@1 1702 int head=0, end=Count-1, mid;
xue@1 1703
xue@1 1704 //D(head)<=value<D(end)
xue@1 1705 while (end-head>1)
xue@1 1706 {
xue@1 1707 mid=(head+end)/2;
xue@1 1708 if (value>=data[mid]) head=mid;
xue@1 1709 else end=mid;
xue@1 1710 }
xue@1 1711
xue@1 1712 //D(head=end-1)<=value<D(end)
xue@1 1713 if (doinsert)
xue@1 1714 {
xue@1 1715 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1));
xue@1 1716 data[end]=value;
xue@1 1717 }
xue@1 1718 return end;
xue@1 1719 }//InsertInc
xue@1 1720 //version where data[] is int.
xue@1 1721 int InsertInc(double value, int* data, int Count, bool doinsert)
xue@1 1722 {
xue@1 1723 if (Count<=0) return -1;
xue@1 1724 if (value>=data[Count-1]) return -1;
xue@1 1725 if (value<data[0])
xue@1 1726 {
xue@1 1727 memmove(&data[1], &data[0], sizeof(int)*(Count-1));
xue@1 1728 if (doinsert) data[0]=value;
xue@1 1729 return 0;
xue@1 1730 }
xue@1 1731
xue@1 1732 //now Count>=2
xue@1 1733 int head=0, end=Count-1, mid;
xue@1 1734
xue@1 1735 //D(head)<=value<D(end)
xue@1 1736 while (end-head>1)
xue@1 1737 {
xue@1 1738 mid=(head+end)/2;
xue@1 1739 if (value>=data[mid]) head=mid;
xue@1 1740 else end=mid;
xue@1 1741 }
xue@1 1742
xue@1 1743 //D(head=end-1)<=value<D(end)
xue@1 1744 if (doinsert)
xue@1 1745 {
xue@1 1746 memmove(&data[end+1], &data[end], sizeof(int)*(Count-end-1));
xue@1 1747 data[end]=value;
xue@1 1748 }
xue@1 1749 return end;
xue@1 1750 }//InsertInc
xue@1 1751
xue@1 1752 /*
xue@1 1753 function InsertInc: inserts value and attached integer into sorted increasing list
xue@1 1754
xue@1 1755 In: data[Count]: a sorted increasing list
xue@1 1756 indices[Count]: a list of integers attached to entries of data[]
xue@1 1757 value, index: the value to be added and its attached integer
xue@1 1758 Out: data[Count], indices[Count]: the lists with $value and $index inserted if $value is smaller than
xue@1 1759 the last entry of data[], in which case the original last entries are discarded.
xue@1 1760
xue@1 1761 Returns the index where $value is located in data[], or -1 if $value is larger than or equal to
xue@1 1762 data[Count-1].
xue@1 1763 */
xue@1 1764 int InsertInc(double value, int index, double* data, int* indices, int Count)
xue@1 1765 {
xue@1 1766 if (Count<=0) return -1;
xue@1 1767 if (value>=data[Count-1]) return -1;
xue@1 1768 if (value<data[0])
xue@1 1769 {
xue@1 1770 memmove(&data[1], data, sizeof(double)*(Count-1));
xue@1 1771 memmove(&indices[1], indices, sizeof(int)*(Count-1));
xue@1 1772 data[0]=value, indices[0]=index;
xue@1 1773 return 0;
xue@1 1774 }
xue@1 1775
xue@1 1776 //now Count>=2
xue@1 1777 int head=0, end=Count-1, mid;
xue@1 1778
xue@1 1779 //D(head)>=value>D(end)
xue@1 1780 while (end-head>1)
xue@1 1781 {
xue@1 1782 mid=(head+end)/2;
xue@1 1783 if (value>=data[mid]) head=mid;
xue@1 1784 else end=mid;
xue@1 1785 }
xue@1 1786
xue@1 1787 //D(head=end-1)>=value>D(end)
xue@1 1788 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1));
xue@1 1789 memmove(&indices[end+1], &indices[end], sizeof(int)*(Count-end-1));
xue@1 1790 data[end]=value, indices[end]=index;
xue@1 1791 return end;
xue@1 1792 }//InsertInc
xue@1 1793 //version where indices[] is double-precision floating point.
xue@1 1794 int InsertInc(double value, double index, double* data, double* indices, int Count)
xue@1 1795 {
xue@1 1796 if (Count<=0) return -1;
xue@1 1797 if (value>=data[Count-1]) return -1;
xue@1 1798 if (value<data[0])
xue@1 1799 {
xue@1 1800 memmove(&data[1], data, sizeof(double)*(Count-1));
xue@1 1801 memmove(&indices[1], indices, sizeof(double)*(Count-1));
xue@1 1802 data[0]=value, indices[0]=index;
xue@1 1803 return 0;
xue@1 1804 }
xue@1 1805
xue@1 1806 //now Count>=2
xue@1 1807 int head=0, end=Count-1, mid;
xue@1 1808
xue@1 1809 //D(head)>=value>D(end)
xue@1 1810 while (end-head>1)
xue@1 1811 {
xue@1 1812 mid=(head+end)/2;
xue@1 1813 if (value>=data[mid]) head=mid;
xue@1 1814 else end=mid;
xue@1 1815 }
xue@1 1816
xue@1 1817 //D(head=end-1)>=value>D(end)
xue@1 1818 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1));
xue@1 1819 memmove(&indices[end+1], &indices[end], sizeof(double)*(Count-end-1));
xue@1 1820 data[end]=value, indices[end]=index;
xue@1 1821 return end;
xue@1 1822 }//InsertInc
xue@1 1823
xue@1 1824 /*
xue@1 1825 function InsertIncApp: inserts value into flexible-length sorted increasing list
xue@1 1826
xue@1 1827 In: data[Count]: a sorted increasing list.
xue@1 1828 value: the value to be added
xue@1 1829 Out: data[Count+1]: the list with $value inserted.
xue@1 1830
xue@1 1831 Returns the index where $value is located in data[], or -1 if Count<0. data[] must have Count+1
xue@1 1832 storage units on calling.
xue@1 1833 */
xue@1 1834 int InsertIncApp(double value, double* data, int Count)
xue@1 1835 {
xue@1 1836 if (Count<0) return -1;
xue@1 1837 if (Count==0){data[0]=value; return 0;}
xue@1 1838 if (value>=data[Count-1]){data[Count]=value; return Count;}
xue@1 1839 if (value<data[0])
xue@1 1840 {
xue@1 1841 memmove(&data[1], &data[0], sizeof(double)*Count);
xue@1 1842 data[0]=value;
xue@1 1843 return 0;
xue@1 1844 }
xue@1 1845
xue@1 1846 //now Count>=2
xue@1 1847 int head=0, end=Count-1, mid;
xue@1 1848
xue@1 1849 //D(head)<=value<D(end)
xue@1 1850 while (end-head>1)
xue@1 1851 {
xue@1 1852 mid=(head+end)/2;
xue@1 1853 if (value>=data[mid]) head=mid;
xue@1 1854 else end=mid;
xue@1 1855 }
xue@1 1856
xue@1 1857 //D(head=end-1)<=value<D(end)
xue@1 1858 memmove(&data[end+1], &data[end], sizeof(double)*(Count-end));
xue@1 1859 data[end]=value;
xue@1 1860
xue@1 1861 return end;
xue@1 1862 }//InsertIncApp
xue@1 1863
xue@1 1864 //---------------------------------------------------------------------------
xue@1 1865 /*
xue@1 1866 function InstantFreq; calculates instantaneous frequency from spectrum, evaluated at bin k
xue@1 1867
xue@1 1868 In: x[hwid]: spectrum with scale 2hwid
xue@1 1869 k: reference frequency, in bins
xue@1 1870 mode: must be 1.
xue@1 1871
xue@1 1872 Returns an instantaneous frequency near bin k.
xue@1 1873 */
xue@1 1874 double InstantFreq(int k, int hwid, cdouble* x, int mode)
xue@1 1875 {
xue@1 1876 double result;
xue@1 1877 switch(mode)
xue@1 1878 {
xue@1 1879 //mode 1: the phase vocoder method, based on J. Brown, where the spectrogram
xue@1 1880 // MUST be calculated using rectangular window
xue@1 1881 case 1:
xue@1 1882 {
xue@1 1883 if (k<1) k=1;
xue@1 1884 if (k>hwid-2) k=hwid-2;
xue@1 1885 double hr=0.5*(x[k].x-0.5*(x[k+1].x+x[k-1].x)), hi=0.5*(x[k].y-0.5*(x[k+1].y+x[k-1].y));
xue@1 1886 double ph0=Atan2(hi, hr);
xue@1 1887 double c=cos(M_PI/hwid), s=sin(M_PI/hwid);
xue@1 1888 hr=0.5*(x[k].x-0.5*(x[k+1].x*c-x[k+1].y*s+x[k-1].x*c+x[k-1].y*s));
xue@1 1889 hi=0.5*(x[k].y-0.5*(x[k+1].y*c+x[k+1].x*s+x[k-1].y*c-x[k-1].x*s));
xue@1 1890 double ph1=Atan2(hi, hr);
xue@1 1891 result=(ph1-ph0)/(2*M_PI);
xue@1 1892 if (result<-0.5) result+=1;
xue@1 1893 if (result>0.5) result-=1;
xue@1 1894 result+=k*0.5/hwid;
xue@1 1895 break;
xue@1 1896 }
xue@1 1897 case 2:
xue@1 1898 break;
xue@1 1899 }
xue@1 1900 return result;
xue@1 1901 }//InstantFreq
xue@1 1902
xue@1 1903 /*
xue@1 1904 function InstantFreq; calculates "frequency spectrum", a sequence of frequencies evaluated at DFT bins
xue@1 1905
xue@1 1906 In: x[hwid]: spectrum with scale 2hwid
xue@1 1907 mode: must be 1.
xue@1 1908 Out: freqspec[hwid]: the frequency spectrum
xue@1 1909
xue@1 1910 No return value.
xue@1 1911 */
xue@1 1912 void InstantFreq(double* freqspec, int hwid, cdouble* x, int mode)
xue@1 1913 {
xue@1 1914 for (int i=0; i<hwid; i++)
xue@1 1915 freqspec[i]=InstantFreq(i, hwid, x, mode);
xue@1 1916 }//InstantFreq
xue@1 1917
xue@1 1918 //---------------------------------------------------------------------------
xue@1 1919 /*
xue@1 1920 function IntToDouble: copy content of integer array to double array
xue@1 1921
xue@1 1922 In: in: pointer to integer array
xue@1 1923 BytesPerSample: number of bytes each integer takes
xue@1 1924 Count: size of integer array, in integers
xue@1 1925 Out: vector out[Count].
xue@1 1926
xue@1 1927 No return value.
xue@1 1928
xue@1 1929 This version is currently commented out in favour of the version implemented in QuickSpec.cpp which
xue@1 1930 supports 24-bit integers.
xue@1 1931 *//*
xue@1 1932 void IntToDouble(double* out, void* in, int BytesPerSample, int Count)
xue@1 1933 {
xue@1 1934 if (BytesPerSample==1){unsigned char* in8=(unsigned char*)in; for (int k=0; k<Count; k++) *(out++)=*(in8++)-128.0;}
xue@1 1935 else {__int16* in16=(__int16*)in; for (int k=0; k<Count; k++) *(out++)=*(in16++);}
xue@1 1936 }//IntToDouble*/
xue@1 1937
xue@1 1938 //---------------------------------------------------------------------------
xue@1 1939 /*
xue@1 1940 function IPHannC: inner product with Hann window spectrum
xue@1 1941
xue@1 1942 In: x[N]: spectrum
xue@1 1943 f: reference frequency
xue@1 1944 K1, K2: spectral truncation bounds
xue@1 1945
xue@1 1946 Returns the absolute value of the inner product of x[K1:K2] with the corresponding band of the
xue@1 1947 spectrum of a sinusoid at frequency f.
xue@1 1948 */
xue@1 1949 double IPHannC(double f, cdouble* x, int N, int K1, int K2)
xue@1 1950 {
xue@1 1951 int M; double c[4], iH2;
xue@1 1952 windowspec(wtHann, N, &M, c, &iH2);
xue@1 1953 return abs(IPWindowC(f, x, N, M, c, iH2, K1, K2));
xue@1 1954 }//IPHannC
xue@1 1955
xue@1 1956
xue@1 1957 //---------------------------------------------------------------------------
xue@1 1958 /*
xue@1 1959 function lse: linear regression y=ax+b
xue@1 1960
xue@1 1961 In: x[Count], y[Count]: input points
xue@1 1962 Out: a, b: LSE estimation of coefficients in y=ax+b
xue@1 1963
xue@1 1964 No return value.
xue@1 1965 */
xue@1 1966 void lse(double* x, double* y, int Count, double& a, double& b)
xue@1 1967 {
xue@1 1968 double sx=0, sy=0, sxx=0, sxy=0;
xue@1 1969 for (int i=0; i<Count; i++)
xue@1 1970 {
xue@1 1971 sx+=x[i];
xue@1 1972 sy+=y[i];
xue@1 1973 sxx+=x[i]*x[i];
xue@1 1974 sxy+=x[i]*y[i];
xue@1 1975 }
xue@1 1976 b=(sxx*sy-sx*sxy)/(Count*sxx-sx*sx);
xue@1 1977 a=(sy-Count*b)/sx;
xue@1 1978 }//lse
xue@1 1979
xue@1 1980 //--------------------------------------------------------------------------
xue@1 1981 /*
xue@1 1982 memdoubleadd: vector addition
xue@1 1983
xue@1 1984 In: dest[count], source[count]: addends
xue@1 1985 Out: dest[count]: sum
xue@1 1986
xue@1 1987 No return value.
xue@1 1988 */
xue@1 1989 void memdoubleadd(double* dest, double* source, int count)
xue@1 1990 {
xue@1 1991 for (int i=0; i<count; i++){*dest=*dest+*source; dest++; source++;}
xue@1 1992 }//memdoubleadd
xue@1 1993
xue@1 1994 //--------------------------------------------------------------------------
xue@1 1995 /*
xue@1 1996 function Mel: converts frequency in Hz to frequency in mel.
xue@1 1997
xue@1 1998 In: f: frequency, in Hz
xue@1 1999
xue@1 2000 Returns the frequency measured on mel scale.
xue@1 2001 */
xue@1 2002 double Mel(double f)
xue@1 2003 {
xue@1 2004 return 1127.01048*log(1+f/700);
xue@1 2005 }//Mel
xue@1 2006
xue@1 2007 /*
xue@1 2008 function InvMel: converts frequency in mel to frequency in Hz.
xue@1 2009
xue@1 2010 In: f: frequency, in mel.
xue@1 2011
xue@1 2012 Returns the frequency in Hz.
xue@1 2013 */
xue@1 2014 double InvMel(double mel)
xue@1 2015 {
xue@1 2016 return 700*(exp(mel/1127.01048)-1);
xue@1 2017 }//InvMel
xue@1 2018
xue@1 2019 /*
xue@1 2020 function MFCC: calculates MFCC.
xue@1 2021
xue@1 2022 In: Data[FrameWidth]: data
xue@1 2023 NumBands: number of frequency bands on mel scale
xue@1 2024 Bands[3*NumBands]: mel frequency bands, comes as $NumBands triples, each containing the lower,
xue@1 2025 middle and high frequencies, in bins, of one band, from which a weighting window is created to
xue@1 2026 weight individual bins.
xue@1 2027 Ceps_Order: number of MFC coefficients (i.e. DCT coefficients)
xue@1 2028 W, X: FFT buffers
xue@1 2029 Out: C[Ceps_Order]: MFCC
xue@1 2030 Amps[NumBands]: log spectrum on MF bands
xue@1 2031
xue@1 2032 No return value. Use MFCCPrepareBands() to retrieve Bands[].
xue@1 2033 */
xue@1 2034 void MFCC(int FrameWidth, int NumBands, int Ceps_Order, double* Data, double* Bands, double* C, double* Amps, cdouble* W, cdouble* X)
xue@1 2035 {
xue@1 2036 double tmp, b2s, b2c, b2e;
xue@1 2037
xue@1 2038 RFFTC(Data, 0, 0, log2(FrameWidth), W, X, 0);
xue@1 2039 for (int i=0; i<=FrameWidth/2; i++) Amps[i]=X[i].x*X[i].x+X[i].y*X[i].y;
xue@1 2040
xue@1 2041 for (int i=0; i<NumBands; i++)
xue@1 2042 {
xue@1 2043 tmp=0;
xue@1 2044 b2s=Bands[3*i], b2c=Bands[3*i+1], b2e=Bands[3*i+2];
xue@1 2045
xue@1 2046 for (int j=ceil(b2s); j<ceil(b2c); j++)
xue@1 2047 tmp+=Amps[j]*(j-b2s)/(b2c-b2s);
xue@1 2048 for (int j=ceil(b2c); j<b2e; j++)
xue@1 2049 tmp+=Amps[j]*(b2e-j)/(b2e-b2c);
xue@1 2050
xue@1 2051 if (tmp<3.7200759760208359629596958038631e-44)
xue@1 2052 Amps[i]=-100;
xue@1 2053 else
xue@1 2054 Amps[i]=log(tmp);
xue@1 2055 }
xue@1 2056
xue@1 2057 for (int i=0; i<Ceps_Order; i++)
xue@1 2058 {
xue@1 2059 tmp=Amps[0]*cos(M_PI*(i+1)/2/NumBands);
xue@1 2060 for (int j=1; j<NumBands; j++)
xue@1 2061 tmp+=Amps[j]*cos(M_PI*(i+0.5)*(j+0.5)/NumBands);
xue@1 2062 C[i]=tmp;
xue@1 2063 }
xue@1 2064 }//MFCC
xue@1 2065
xue@1 2066 /*
xue@1 2067 function MFCCPrepareBands: returns a array of OVERLAPPING bands given in triples, whose 1st and 3rd
xue@1 2068 entries are the start and end of a band, in bins, and the 2nd is a middle frequency.
xue@1 2069
xue@1 2070 In: SamplesPerSec: sampling rate
xue@1 2071 NumberOfBins: FFT size
xue@1 2072 NumberOfBands: number of mel-frequency bands
xue@1 2073
xue@1 2074 Returns pointer to the array of triples.
xue@1 2075 */
xue@1 2076 double* MFCCPrepareBands(int NumberOfBands, int SamplesPerSec, int NumberOfBins)
xue@1 2077 {
xue@1 2078 double* Bands=new double[NumberOfBands*3];
xue@1 2079 double naqfreq=SamplesPerSec/2.0; //naqvist freq
xue@1 2080 double binwid=SamplesPerSec*1.0/NumberOfBins;
xue@1 2081 double naqmel=Mel(naqfreq);
xue@1 2082 double b=naqmel/(NumberOfBands+1);
xue@1 2083
xue@1 2084 Bands[0]=0;
xue@1 2085 Bands[1]=InvMel(b)/binwid;
xue@1 2086 Bands[2]=InvMel(b*2)/binwid;
xue@1 2087 for (int i=1; i<NumberOfBands; i++)
xue@1 2088 {
xue@1 2089 Bands[3*i]=Bands[3*i-2];
xue@1 2090 Bands[3*i+1]=Bands[3*i-1];
xue@1 2091 Bands[3*i+2]=InvMel(b*(i+2))/binwid;
xue@1 2092 }
xue@1 2093 return Bands;
xue@1 2094 }//MFCCPrepareBands
xue@1 2095
xue@1 2096 //---------------------------------------------------------------------------
xue@1 2097 /*
xue@1 2098 function Multi: vector-constant multiplication
xue@1 2099
xue@1 2100 In: data[count]: a vector
xue@1 2101 mul: a constant
xue@1 2102 Out: data[count]: their product
xue@1 2103
xue@1 2104 No return value.
xue@1 2105 */
xue@1 2106 void Multi(double* data, int count, double mul)
xue@1 2107 {
xue@1 2108 for (int i=0; i<count; i++){*data=*data*mul; data++;}
xue@1 2109 }//Multi
xue@1 2110
xue@1 2111 /*
xue@1 2112 function Multi: vector-constant multiplication
xue@1 2113
xue@1 2114 In: in[count]: a vector
xue@1 2115 mul: a constant
xue@1 2116 Out: out[count]: their product
xue@1 2117
xue@1 2118 No return value.
xue@1 2119 */
xue@1 2120 void Multi(double* out, double* in, int count, double mul)
xue@1 2121 {
xue@1 2122 for (int i=0; i<count; i++) *(out++)=*(in++)*mul;
xue@1 2123 }//Multi
xue@1 2124
xue@1 2125 /*
xue@1 2126 function Multi: vector-constant multiply-addition
xue@1 2127
xue@1 2128 In: in[count], adder[count]: vectors
xue@1 2129 mul: a constant
xue@1 2130 Out: out[count]: in[]+adder[]*mul
xue@1 2131
xue@1 2132 No return value.
xue@1 2133 */
xue@1 2134 void MultiAdd(double* out, double* in, double* adder, int count, double mul)
xue@1 2135 {
xue@1 2136 for (int i=0; i<count; i++) *(out++)=*(in++)+*(adder++)*mul;
xue@1 2137 }//MultiAdd
xue@1 2138
xue@1 2139 //---------------------------------------------------------------------------
xue@1 2140 /*
xue@1 2141 function NearestPeak: finds a peak value in an array that is nearest to a given index
xue@1 2142
xue@1 2143 In: data[count]: an array
xue@1 2144 anindex: an index
xue@1 2145
xue@1 2146 Returns the index to a peak of data[] that is closest to anindex. In case of two cloest indices,
xue@1 2147 returns the index to the higher peak of the two.
xue@1 2148 */
xue@1 2149 int NearestPeak(double* data, int count, int anindex)
xue@1 2150 {
xue@1 2151 int upind=anindex, downind=anindex;
xue@1 2152 if (anindex<1) anindex=1;
xue@1 2153 if (anindex>count-2) anindex=count-2;
xue@1 2154
xue@1 2155 if (data[anindex]>data[anindex-1] && data[anindex]>data[anindex+1]) return anindex;
xue@1 2156
xue@1 2157 if (data[anindex]<data[anindex-1])
xue@1 2158 while (downind>0 && data[downind-1]>data[downind]) downind--;
xue@1 2159 if (data[anindex]<data[anindex+1])
xue@1 2160 while (upind<count-1 && data[upind]<data[upind+1]) upind++;
xue@1 2161
xue@1 2162 if (upind==anindex) return downind;
xue@1 2163 if (downind==anindex) return upind;
xue@1 2164
xue@1 2165 if (anindex-downind<upind-anindex) return downind;
xue@1 2166 else if (anindex-downind>upind-anindex) return upind;
xue@1 2167 else if (data[upind]<data[downind]) return downind;
xue@1 2168 else return upind;
xue@1 2169 }//NearestPeak
xue@1 2170
xue@1 2171 //---------------------------------------------------------------------------
xue@1 2172 /*
xue@1 2173 function NegativeExp: fits the curve y=1-x^lmd.
xue@1 2174
xue@1 2175 In: x[Count], y[Count]: sample points to fit, x[0]=0, x[Count-1]=1, y[0]=1, y[Count-1]=0
xue@1 2176 Out: lmd: coefficient of y=1-x^lmd.
xue@1 2177
xue@1 2178 Returns rms fitting error.
xue@1 2179 */
xue@1 2180 double NegativeExp(double* x, double* y, int Count, double& lmd, int sample, double step, double eps, int maxiter)
xue@1 2181 {
xue@1 2182 lmd=0;
xue@1 2183 for (int i=1; i<Count-1; i++)
xue@1 2184 {
xue@1 2185 if (y[i]<1)
xue@1 2186 lmd+=log(1-y[i])/log(x[i]);
xue@1 2187 else
xue@1 2188 lmd+=-50/log(x[i]);
xue@1 2189 }
xue@1 2190 lmd/=(Count-2);
xue@1 2191
xue@1 2192 //lmd has been initialized
xue@1 2193 //coming up will be the recursive calculation of lmd by lgg
xue@1 2194
xue@1 2195 int iter=0;
xue@1 2196 double laste, lastdel, e=0, del=0, tmp;
xue@1 2197 do
xue@1 2198 {
xue@1 2199 iter++;
xue@1 2200 laste=e;
xue@1 2201 lastdel=del;
xue@1 2202 e=0, del=0;
xue@1 2203 for (int i=1; i<Count-1; i+=sample)
xue@1 2204 {
xue@1 2205 tmp=pow(x[i], lmd);
xue@1 2206 e=e+(y[i]+tmp-1)*(y[i]+tmp-1);
xue@1 2207 del=del+(y[i]+tmp-1)*tmp*log(x[i]);
xue@1 2208 }
xue@1 2209 if (laste && e>laste) lmd+=step*lastdel, step/=2;
xue@1 2210 else lmd+=-step*sample*del;
xue@1 2211 }
xue@1 2212 while (e && iter<=maxiter && (!laste || fabs(laste-e)/e>eps));
xue@1 2213 return sqrt(e/Count);
xue@1 2214 }//NegativeExp
xue@1 2215
xue@1 2216 //---------------------------------------------------------------------------
xue@1 2217 /*
xue@1 2218 function: NL: noise level, calculated on 5% of total frames with least energy
xue@1 2219
xue@1 2220 In: data[Count]:
xue@1 2221 Wid: window width for power level estimation
xue@1 2222
xue@1 2223 Returns noise level, in rms.
xue@1 2224 */
xue@1 2225 double NL(double* data, int Count, int Wid)
xue@1 2226 {
xue@1 2227 int Fr=Count/Wid;
xue@1 2228 int Num=Fr/20+1;
xue@1 2229 double* ene=new double[Num], tmp;
xue@1 2230 for (int i=0; i<Num; i++) ene[i]=1e30;
xue@1 2231 for (int i=0; i<Fr; i++)
xue@1 2232 {
xue@1 2233 tmp=DCPower(&data[i*Wid], Wid, 0);
xue@1 2234 InsertInc(tmp, ene, Num);
xue@1 2235 }
xue@1 2236 double result=Avg(ene, Num, 0);
xue@1 2237 delete[] ene;
xue@1 2238 result=sqrt(result);
xue@1 2239 return result;
xue@1 2240 }//NL
xue@1 2241
xue@1 2242 //---------------------------------------------------------------------------
xue@1 2243 /*
xue@1 2244 function Normalize: normalizes data to [-Maxi, Maxi], without zero shift
xue@1 2245
xue@1 2246 In: data[Count]: data to be normalized
xue@1 2247 Maxi: destination maximal absolute value
xue@1 2248 Out: data[Count]: normalized data
xue@1 2249
xue@1 2250 Returns the original maximal absolute value.
xue@1 2251 */
xue@1 2252 double Normalize(double* data, int Count, double Maxi)
xue@1 2253 {
xue@1 2254 double max=0;
xue@1 2255 double* ldata=data;
xue@1 2256 for (int i=0; i<Count; i++)
xue@1 2257 {
xue@1 2258 if (*ldata>max) max=*ldata;
xue@1 2259 else if (-*ldata>max) max=-*ldata;
xue@1 2260 ldata++;
xue@1 2261 }
xue@1 2262 if (max>0)
xue@1 2263 {
xue@1 2264 Maxi=Maxi/max;
xue@1 2265 for (int i=0; i<Count; i++) *(data++)*=Maxi;
xue@1 2266 }
xue@1 2267 return max;
xue@1 2268 }//Normalize
xue@1 2269
xue@1 2270 /*
xue@1 2271 function Normalize2: normalizes data to a specified Euclidian norm
xue@1 2272
xue@1 2273 In: data[Count]: data to normalize
xue@1 2274 Norm: destination Euclidian norm
xue@1 2275 Out: data[Count]: normalized data.
xue@1 2276
xue@1 2277 Returns the original Euclidian norm.
xue@1 2278 */
xue@1 2279 double Normalize2(double* data, int Count, double Norm)
xue@1 2280 {
xue@1 2281 double norm=0;
xue@1 2282 for (int i=0; i<Count; i++) norm+=data[i]*data[i];
xue@1 2283 norm=sqrt(norm);
xue@1 2284 double mul=norm/Norm;
xue@1 2285 if (mul!=0) for (int i=0; i<Count; i++) data[i]/=mul;
xue@1 2286 return norm;
xue@1 2287 }//Normalize2
xue@1 2288
xue@1 2289 //---------------------------------------------------------------------------
xue@1 2290 /*
xue@1 2291 function PhaseSpan: computes the unwrapped phase variation across the Nyquist range
xue@1 2292
xue@1 2293 In: data[Count]: time-domain data
xue@1 2294 aparams: a fftparams structure
xue@1 2295
xue@1 2296 Returns the difference between unwrapped phase angles at 0 and Nyquist frequency.
xue@1 2297 */
xue@1 2298 double PhaseSpan(double* data, int Count, void* aparams)
xue@1 2299 {
xue@1 2300 int Pad=1;
xue@1 2301 fftparams* params=(fftparams*)aparams;
xue@1 2302 double* Arg=new double[Count*Pad];
xue@1 2303 AllocateFFTBuffer(Count*Pad, Amp, w, x);
xue@1 2304 memset(Amp, 0, sizeof(double)*Count*Pad);
xue@1 2305 memcpy(&Amp[Count*(Pad-1)/2], data, sizeof(double)*Count);
xue@1 2306 ApplyWindow(Amp, Amp, params->Amp, Count);
xue@1 2307 RFFTC(Amp, Amp, Arg, log2(Count*Pad), w, x, 0);
xue@1 2308
xue@1 2309 SmoothPhase(Arg, Count*Pad/2+1);
xue@1 2310 double result=Arg[Count*Pad/2]-Arg[0];
xue@1 2311 delete[] Arg;
xue@1 2312 FreeFFTBuffer(Amp);
xue@1 2313 return result;
xue@1 2314 }//PhaseSpan
xue@1 2315
xue@1 2316 //---------------------------------------------------------------------------
xue@1 2317 /*
xue@1 2318 function PolyFit: least square polynomial fitting y=sum(i){a[i]*x^i}
xue@1 2319
xue@1 2320 In: x[N], y[N]: sample points
xue@1 2321 P: order of polynomial, P<N
xue@1 2322 Out: a[P+1]: coefficients of polynomial
xue@1 2323
xue@1 2324 No return value.
xue@1 2325 */
xue@1 2326 void PolyFit(int P, double* a, int N, double* x, double* y)
xue@1 2327 {
xue@1 2328 Alloc2(P+1, P+1, aa);
xue@1 2329 double ai0, bi, *bb=new double[P+1], *s=new double[N], *r=new double[N];
xue@1 2330 aa[0][0]=N; bi=0; for (int i=0; i<N; i++) s[i]=1, r[i]=y[i], bi+=y[i]; bb[0]=bi;
xue@1 2331
xue@1 2332 for (int i=1; i<=P; i++)
xue@1 2333 {
xue@1 2334 ai0=bi=0; for (int j=0; j<N; j++) {s[j]*=x[j], r[j]*=x[j]; ai0+=s[j], bi+=r[j];}
xue@1 2335 for (int j=0; j<=i; j++) aa[i-j][j]=ai0; bb[i]=bi;
xue@1 2336 }
xue@1 2337 for (int i=P+1; i<=2*P; i++)
xue@1 2338 {
xue@1 2339 ai0=0; for (int j=0; j<N; j++) {s[j]*=x[j]; ai0+=s[j];}
xue@1 2340 for (int j=i-P; j<=P; j++) aa[i-j][j]=ai0;
xue@1 2341 }
xue@1 2342 GESCP(P+1, a, aa, bb);
xue@1 2343 DeAlloc2(aa); delete[] bb; delete[] s; delete[] r;
xue@1 2344 }//PolyFit
xue@1 2345
xue@1 2346 //---------------------------------------------------------------------------
xue@1 2347 /*
xue@1 2348 function Pow: vector power function
xue@1 2349
xue@1 2350 In: data[Count]: a vector
xue@1 2351 ex: expontnet
xue@1 2352 Out: data[Count]: point-wise $ex-th power of data[]
xue@1 2353
xue@1 2354 No return value.
xue@1 2355 */
xue@1 2356 void Pow(double* data, int Count, double ex)
xue@1 2357 {
xue@1 2358 for (int i=0; i<Count; i++)
xue@1 2359 data[i]=pow(data[i], ex);
xue@1 2360 }//Power
xue@1 2361
xue@1 2362 //---------------------------------------------------------------------------
xue@1 2363 /*
xue@1 2364 Rectify: semi-wave rectification
xue@1 2365
xue@1 2366 In: data[Count]: data to rectify
xue@1 2367 th: rectification threshold: values below th are rectified to th
xue@1 2368 Out: data[Count]: recitified data
xue@1 2369
xue@1 2370 Returns number of preserved (i.e. not rectified) samples.
xue@1 2371 */
xue@1 2372 int Rectify(double* data, int Count, double th)
xue@1 2373 {
xue@1 2374 int Result=0;
xue@1 2375 for (int i=0; i<Count; i++)
xue@1 2376 {
xue@1 2377 if (data[i]<=th) data[i]=th;
xue@1 2378 else Result++;
xue@1 2379 }
xue@1 2380 return Result;
xue@1 2381 }//Rectify
xue@1 2382
xue@1 2383 //---------------------------------------------------------------------------
xue@1 2384 /*
xue@1 2385 function Res: minimum absolute residue.
xue@1 2386
xue@1 2387 In: in: a number
xue@1 2388 mod: modulus
xue@1 2389
xue@1 2390 Returns the minimal absolute residue of $in devided by $mod.
xue@1 2391 */
xue@1 2392 double Res(double in, double mod)
xue@1 2393 {
xue@1 2394 int i=in/mod;
xue@1 2395 in=in-i*mod;
xue@1 2396 if (in>mod/2) in-=mod;
xue@1 2397 if (in<-mod/2) in+=mod;
xue@1 2398 return in;
xue@1 2399 }//Res
xue@1 2400
xue@1 2401 //---------------------------------------------------------------------------
xue@1 2402 /*
xue@1 2403 function Romberg: Romberg algorithm for numerical integration
xue@1 2404
xue@1 2405 In: f: function to integrate
xue@1 2406 params: extra argument for calling f
xue@1 2407 a, b: integration boundaries
xue@1 2408 n: depth of sampling
xue@1 2409
xue@1 2410 Returns the integral of f(*, params) over [a, b].
xue@1 2411 */
xue@1 2412 double Romberg(int n, double(*f)(double, void*), double a, double b, void* params)
xue@1 2413 {
xue@1 2414 int np=1;
Chris@3 2415 double* r1=new double[n+1];
xue@1 2416 double* r2=new double[n+1];
xue@1 2417 double h=b-a, *swp;
xue@1 2418 r1[1]=h*(f(a, params)+f(b, params))/2;
xue@1 2419 for (int i=2; i<=n; i++)
xue@1 2420 {
xue@1 2421 double akh=a+0.5*h; r2[1]=f(akh, params);
xue@1 2422 for (int k=2; k<=np; k++) {akh+=h; r2[1]+=f(akh, params);} //akh=a+(k-0.5)h
xue@1 2423 r2[1]=0.5*(r1[1]+h*r2[1]);
xue@1 2424 double fj=4;
xue@1 2425 for (int j=2; j<=i; j++) {r2[j]=(fj*r2[j-1]-r1[j-1])/(fj-1); fj*=4;} //fj=4^(j-1)
xue@1 2426 h/=2; np*=2;
xue@1 2427 swp=r1; r1=r2; r2=swp;
xue@1 2428 }
xue@1 2429 h=r1[n];
xue@1 2430 delete[] r1;
xue@1 2431 delete[] r2;
xue@1 2432 return h;
xue@1 2433 }//Romberg
xue@1 2434
xue@1 2435 /*
xue@1 2436 function Romberg: Romberg algorithm for numerical integration, may return before specified depth on
xue@1 2437 convergence.
xue@1 2438
xue@1 2439 In: f: function to integrate
xue@1 2440 params: extra argument for calling f
xue@1 2441 a, b: integration boundaries
xue@1 2442 n: depth of sampling
xue@1 2443 ep: convergence test threshold
xue@1 2444
xue@1 2445 Returns the integral of f(*, params) over [a, b].
xue@1 2446 */
xue@1 2447 double Romberg(double(*f)(double, void*), double a, double b, void* params, int n, double ep)
xue@1 2448 {
xue@1 2449 int i, np=1;
xue@1 2450 double* r1=new double[n+1];
xue@1 2451 double* r2=new double[n+1];
xue@1 2452 double h=b-a, *swp;
xue@1 2453 r1[1]=h*(f(a, params)+f(b, params))/2;
xue@1 2454 bool mep=false;
xue@1 2455 for (i=2; i<=n; i++)
xue@1 2456 {
xue@1 2457 double akh=a+0.5*h; r2[1]=f(akh, params);
xue@1 2458 for (int k=2; k<=np; k++) {akh+=h; r2[1]+=f(akh, params);} //akh=a+(k-0.5)h
xue@1 2459 r2[1]=0.5*(r1[1]+h*r2[1]);
xue@1 2460 double fj=4;
xue@1 2461 for (int j=2; j<=i; j++) {r2[j]=(fj*r2[j-1]-r1[j-1])/(fj-1); fj*=4;} //fj=4^(j-1)
xue@1 2462
xue@1 2463 if (fabs(r2[i]-r1[i-1])<ep)
xue@1 2464 {
xue@1 2465 if (mep) break;
xue@1 2466 else mep=true;
xue@1 2467 }
xue@1 2468 else mep=false;
xue@1 2469
xue@1 2470 h/=2; np*=2;
xue@1 2471 swp=r1; r1=r2; r2=swp;
xue@1 2472 }
xue@1 2473 if (i<=n) h=r2[i];
xue@1 2474 else h=r1[n];
xue@1 2475 delete[] r1;
xue@1 2476 delete[] r2;
xue@1 2477 return h;
xue@1 2478 }//Romberg
xue@1 2479
xue@1 2480 //---------------------------------------------------------------------------
xue@1 2481 //analog and digital sinc functions
xue@1 2482
xue@1 2483 //sinca(0)=1, sincd(0)=N, sinca(1)=sincd(1)=0.
xue@1 2484 /*
xue@1 2485 function sinca: analog sinc function.
xue@1 2486
xue@1 2487 In: x: frequency
xue@1 2488
xue@1 2489 Returns sinc(x)=sin(pi*x)/(pi*x), sinca(0)=1, sinca(1)=0
xue@1 2490 */
xue@1 2491 double sinca(double x)
xue@1 2492 {
xue@1 2493 if (x==0) return 1;
xue@1 2494 return sin(M_PI*x)/(M_PI*x);
xue@1 2495 }//sinca
xue@1 2496
xue@1 2497 /*
xue@1 2498 function sincd_unn: unnormalized discrete sinc function
xue@1 2499
xue@1 2500 In: x: frequency
xue@1 2501 N: scale (window size, DFT size)
xue@1 2502
xue@1 2503 Returns sinc(x)=sin(pi*x)/sin(pi*x/N), sincd(0)=N, sincd(1)=0.
xue@1 2504 */
xue@1 2505 double sincd_unn(double x, int N)
xue@1 2506 {
xue@1 2507 if (x==0) return N;
xue@1 2508 return sin(M_PI*x)/sin(M_PI*x/N);
xue@1 2509 }//sincd
xue@1 2510
xue@1 2511 //---------------------------------------------------------------------------
xue@1 2512 /*
xue@1 2513 SmoothPhase: phase unwrapping on module mpi*PI, 2PI by default
xue@1 2514
xue@1 2515 In: Arg[Count]: phase angles to unwrap
xue@1 2516 mpi: unwrapping modulus, in pi's
xue@1 2517 Out: Arg[Count]: unwrapped phase
xue@1 2518
xue@1 2519 Returns the amount of unwrap, in pi's, of the last phase angle
xue@1 2520 */
xue@1 2521 double SmoothPhase(double* Arg, int Count, int mpi)
xue@1 2522 {
xue@1 2523 double m2pi=mpi*M_PI;
xue@1 2524 for (int i=1; i<Count-1; i++)
xue@1 2525 Arg[i]=Arg[i-1]+Res(Arg[i]-Arg[i-1], m2pi);
xue@1 2526 double tmp=Res(Arg[Count-1]-Arg[Count-2], m2pi);
xue@1 2527 double result=(Arg[Count-1]-Arg[Count-2]-tmp)/m2pi;
xue@1 2528 Arg[Count-1]=Arg[Count-2]+tmp;
xue@1 2529
xue@1 2530 return result;
xue@1 2531 }//SmoothPhase
xue@1 2532
xue@1 2533 //---------------------------------------------------------------------------
xue@1 2534 //the stiff string partial frequency model f[m]=mf[1]*sqrt(1+B(m*m-1)).
xue@1 2535
xue@1 2536 /*
xue@1 2537 StiffB: computes stiffness coefficient from fundamental and another partial frequency based on the
xue@1 2538 stiff string partial frequency model f[m]=mf[1]*sqrt(1+B(m*m-1)).
xue@1 2539
xue@1 2540 In: f0: fundamental frequency
xue@1 2541 m: 1-based partial index
xue@1 2542 fm: frequency of partial m
xue@1 2543
xue@1 2544 Returns stiffness coefficient B.
xue@1 2545 */
xue@1 2546 double StiffB(double f0, double fm, int m)
xue@1 2547 {
xue@1 2548 double f2=fm/m/f0;
xue@1 2549 return (f2*f2-1)/(m*m-1);
xue@1 2550 }//StiffB
xue@1 2551
xue@1 2552 //StiffF: partial frequency of a stiff string
xue@1 2553 /*
xue@1 2554 StiffFm: computes a partial frequency from fundamental frequency and partial index based on the stiff
xue@1 2555 string partial frequency model f[m]=mf[1]*sqrt(1+B(m*m-1)).
xue@1 2556
xue@1 2557 In: f0: fundamental frequency
xue@1 2558 m: 1-based partial index
xue@1 2559 B: stiffness coefficient
xue@1 2560
xue@1 2561 Returns frequency of the m-th partial.
xue@1 2562 */
xue@1 2563 double StiffFm(double f0, int m, double B)
xue@1 2564 {
xue@1 2565 return m*f0*sqrt(1+B*(m*m-1));
xue@1 2566 }//StiffFm
xue@1 2567
xue@1 2568 /*
xue@1 2569 StiffF0: computes fundamental frequency from another partial frequency and stiffness coefficient based
xue@1 2570 on the stiff string partial frequency model f[m]=mf[1]*sqrt(1+B(m*m-1)).
xue@1 2571
xue@1 2572 In: m: 1-based partial index
xue@1 2573 fm: frequency of partial m
xue@1 2574 B: stiffness coefficient
xue@1 2575
xue@1 2576 Returns the fundamental frequency.
xue@1 2577 */
xue@1 2578 double StiffF0(double fm, int m, double B)
xue@1 2579 {
xue@1 2580 return fm/m/sqrt(1+B*(m*m-1));
xue@1 2581 }//StiffF0
xue@1 2582
xue@1 2583 /*
xue@1 2584 StiffM: computes 1-based partial index from partial frequency, fundamental frequency and stiffness
xue@1 2585 coefficient based on the stiff string partial frequency model f[m]=mf[1]*sqrt(1+B(m*m-1)).
xue@1 2586
xue@1 2587 In: f0: fundamental freqency
xue@1 2588 fm: a partial frequency
xue@1 2589 B: stiffness coefficient
xue@1 2590
xue@1 2591 Returns the 1-based partial index which will generate the specified partial frequency from the model
xue@1 2592 which, however, does not have to be an integer in this function.
xue@1 2593 */
xue@1 2594 double StiffM(double f0, double fm, double B)
xue@1 2595 {
xue@1 2596 if (B<1e-14) return fm/f0;
xue@1 2597 double b1=B-1, ff=fm/f0;
xue@1 2598 double delta=b1*b1+4*B*ff*ff;
xue@1 2599 if (delta<0)
xue@1 2600 return sqrt(b1/2/B);
xue@1 2601 else
xue@1 2602 return sqrt((b1+sqrt(delta))/2/B);
xue@1 2603 }//StiffMd
xue@1 2604
xue@1 2605 //---------------------------------------------------------------------------
xue@1 2606 /*
xue@1 2607 TFFilter: time-frequency filtering with Hann-windowed overlap-add.
xue@1 2608
xue@1 2609 In: data[Count]: input data
xue@1 2610 Spans: time-frequency spans
xue@1 2611 wt, windp: type and extra parameter of FFT window
xue@1 2612 Sps: sampling rate
xue@1 2613 TOffst: optional offset applied to all time values in Spans, set to Spans timing of of data[0].
xue@1 2614 Pass: set to pass T-F content covered by Spans, clear to stop T-F content covered by Spans
xue@1 2615 Out: dataout[Count]: filtered data
xue@1 2616
xue@1 2617 No return value. Identical data and dataout allowed.
xue@1 2618 */
xue@1 2619 void TFFilter(double* data, double* dataout, int Count, int Wid, TTFSpans* Spans, bool Pass, WindowType wt, double windp, int Sps, int TOffst)
xue@1 2620 {
xue@1 2621 int HWid=Wid/2;
xue@1 2622 int Fr=Count/HWid-1;
xue@1 2623 int Order=log2(Wid);
xue@1 2624
xue@1 2625 int** lspan=new int*[Fr];
xue@1 2626 double* lxspan=new double[Fr];
xue@1 2627
xue@1 2628 lspan[0]=new int[Fr*Wid];
xue@1 2629 for (int i=1; i<Fr; i++)
xue@1 2630 lspan[i]=&lspan[0][i*Wid];
xue@1 2631
xue@1 2632 //fill local filter span table
xue@1 2633 if (Pass)
xue@1 2634 memset(lspan[0], 0, sizeof(int)*Fr*Wid);
xue@1 2635 else
xue@1 2636 for (int i=0; i<Fr; i++)
xue@1 2637 for (int j=0; j<Wid; j++)
xue@1 2638 lspan[i][j]=1;
xue@1 2639
xue@1 2640 for (int i=0; i<Spans->Count; i++)
xue@1 2641 {
xue@1 2642 int lx1, lx2, ly1, ly2;
xue@1 2643 lx1=(Spans->Items[i].T1-TOffst)/HWid-1;
xue@1 2644 lx2=(Spans->Items[i].T2-1-TOffst)/HWid;
xue@1 2645 ly1=Spans->Items[i].F1*2/Sps*HWid+0.001;
xue@1 2646 ly2=Spans->Items[i].F2*2/Sps*HWid+1;
xue@1 2647 if (lx1<0) lx1=0;
xue@1 2648 if (lx2>=Fr) lx2=Fr-1;
xue@1 2649 if (ly1<0) ly1=0;
xue@1 2650 if (ly1>HWid) ly1=HWid;
xue@1 2651 if (Pass)
xue@1 2652 for (int x=lx1; x<=lx2; x++)
xue@1 2653 for (int y=ly1; y<=ly2; y++)
xue@1 2654 lspan[x][y]=1;
xue@1 2655 else
xue@1 2656 for (int x=lx1; x<=lx2; x++)
xue@1 2657 for (int y=ly1; y<=ly2; y++)
xue@1 2658 lspan[x][y]=0;
xue@1 2659 }
xue@1 2660 for (int i=0; i<Fr; i++)
xue@1 2661 {
xue@1 2662 lxspan[i]=0;
xue@1 2663 for (int j=0; j<=HWid; j++)
xue@1 2664 {
xue@1 2665 if (lspan[i][j])
xue@1 2666 lxspan[i]=lxspan[i]+1;
xue@1 2667 }
xue@1 2668 lxspan[i]/=(HWid+1);
xue@1 2669 }
xue@1 2670 double* winf=NewWindow(wt, Wid, 0, &windp);
xue@1 2671 double* wini=NewWindow(wtHann, Wid, NULL, NULL);
xue@1 2672 for (int i=0; i<Wid; i++)
xue@1 2673 if (winf[i]!=0) wini[i]=wini[i]/winf[i];
xue@1 2674 AllocateFFTBuffer(Wid, ldata, w, x);
xue@1 2675 double* tmpdata=new double[HWid];
xue@1 2676 memset(tmpdata, 0, HWid*sizeof(double));
xue@1 2677
xue@1 2678 for (int i=0; i<Fr; i++)
xue@1 2679 {
xue@1 2680 if (lxspan[i]==0)
xue@1 2681 {
xue@1 2682 memcpy(&dataout[i*HWid], tmpdata, sizeof(double)*HWid);
xue@1 2683 memset(tmpdata, 0, sizeof(double)*HWid);
xue@1 2684 continue;
xue@1 2685 }
xue@1 2686 if (lxspan[i]==1)
xue@1 2687 {
xue@1 2688 memcpy(ldata, &data[i*HWid], Wid*sizeof(double));
xue@1 2689 if (i>0)
xue@1 2690 for (int k=0; k<HWid; k++)
xue@1 2691 ldata[k]=ldata[k]*winf[k]*wini[k];
xue@1 2692 for (int k=HWid; k<Wid; k++)
xue@1 2693 ldata[k]=ldata[k]*winf[k]*wini[k];
xue@1 2694
xue@1 2695 memcpy(&dataout[i*HWid], tmpdata, HWid*sizeof(double));
xue@1 2696 for (int k=0; k<HWid; k++)
xue@1 2697 dataout[i*HWid+k]+=ldata[k];
xue@1 2698 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 2699 continue;
xue@1 2700 }
xue@1 2701 memcpy(ldata, &data[i*HWid], Wid*sizeof(double));
xue@1 2702 if (i>0)
xue@1 2703 for (int k=0; k<HWid; k++)
xue@1 2704 ldata[k]=ldata[k]*winf[k];
xue@1 2705 for (int k=HWid; k<Wid; k++)
xue@1 2706 ldata[k]=ldata[k]*winf[k];
xue@1 2707
xue@1 2708 RFFTC(ldata, NULL, NULL, Order, w, x, 0);
xue@1 2709
xue@1 2710 if (!lspan[i][0]) x[0].x=x[0].y=0;
xue@1 2711 for (int j=1; j<=HWid; j++)
xue@1 2712 if (!lspan[i][j]) x[j].x=x[Wid-j].x=x[j].y=x[Wid-j].y=0;
xue@1 2713
xue@1 2714 CIFFTR(x, Order, w, ldata);
xue@1 2715
xue@1 2716 if (i>0)
xue@1 2717 for (int k=0; k<HWid; k++)
xue@1 2718 ldata[k]=ldata[k]*wini[k];
xue@1 2719 for (int k=HWid; k<Wid; k++)
xue@1 2720 ldata[k]=ldata[k]*wini[k];
xue@1 2721
xue@1 2722 memcpy(&dataout[i*HWid], tmpdata, HWid*sizeof(double));
xue@1 2723 for (int k=0; k<HWid; k++)
xue@1 2724 dataout[i*HWid+k]+=ldata[k];
xue@1 2725 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 2726 }
xue@1 2727 memcpy(&dataout[Fr*HWid], tmpdata, sizeof(double)*HWid);
xue@1 2728 memset(&dataout[Fr*HWid+HWid], 0, sizeof(double)*(Count-Fr*HWid-HWid));
xue@1 2729
xue@1 2730 FreeFFTBuffer(ldata);
xue@1 2731 delete[] lspan[0];
xue@1 2732 delete[] lspan;
xue@1 2733 delete[] lxspan;
xue@1 2734 delete[] tmpdata;
xue@1 2735 delete[] winf;
xue@1 2736 delete[] wini;
xue@1 2737 }//TFFilter
xue@1 2738 //version on integer data, where BytesPerSample specified the integer format.
xue@1 2739 void TFFilter(void* data, void* dataout, int BytesPerSample, int Count, int Wid, TTFSpans* Spans, bool Pass, WindowType wt, double windp, int Sps, int TOffst)
xue@1 2740 {
xue@1 2741 int HWid=Wid/2;
xue@1 2742 int Fr=Count/HWid-1;
xue@1 2743 int Order=log2(Wid);
xue@1 2744
xue@1 2745 int** lspan=new int*[Fr];
xue@1 2746 double* lxspan=new double[Fr];
xue@1 2747
xue@1 2748 lspan[0]=new int[Fr*Wid];
xue@1 2749 for (int i=1; i<Fr; i++)
xue@1 2750 lspan[i]=&lspan[0][i*Wid];
xue@1 2751
xue@1 2752 //fill local filter span table
xue@1 2753 if (Pass)
xue@1 2754 memset(lspan[0], 0, sizeof(int)*Fr*Wid);
xue@1 2755 else
xue@1 2756 for (int i=0; i<Fr; i++)
xue@1 2757 for (int j=0; j<Wid; j++)
xue@1 2758 lspan[i][j]=1;
xue@1 2759
xue@1 2760 for (int i=0; i<Spans->Count; i++)
xue@1 2761 {
xue@1 2762 int lx1, lx2, ly1, ly2;
xue@1 2763 lx1=(Spans->Items[i].T1-TOffst)/HWid-1;
xue@1 2764 lx2=(Spans->Items[i].T2-1-TOffst)/HWid;
xue@1 2765 ly1=Spans->Items[i].F1*2/Sps*HWid+0.001;
xue@1 2766 ly2=Spans->Items[i].F2*2/Sps*HWid+1;
xue@1 2767 if (lx1<0) lx1=0;
xue@1 2768 if (lx2>=Fr) lx2=Fr-1;
xue@1 2769 if (ly1<0) ly1=0;
xue@1 2770 if (ly1>HWid) ly1=HWid;
xue@1 2771 if (Pass)
xue@1 2772 for (int x=lx1; x<=lx2; x++)
xue@1 2773 for (int y=ly1; y<=ly2; y++)
xue@1 2774 lspan[x][y]=1;
xue@1 2775 else
xue@1 2776 for (int x=lx1; x<=lx2; x++)
xue@1 2777 for (int y=ly1; y<=ly2; y++)
xue@1 2778 lspan[x][y]=0;
xue@1 2779 }
xue@1 2780 for (int i=0; i<Fr; i++)
xue@1 2781 {
xue@1 2782 lxspan[i]=0;
xue@1 2783 for (int j=0; j<=HWid; j++)
xue@1 2784 {
xue@1 2785 if (lspan[i][j])
xue@1 2786 lxspan[i]=lxspan[i]+1;
xue@1 2787 }
xue@1 2788 lxspan[i]/=(HWid+1);
xue@1 2789 }
xue@1 2790 double* winf=NewWindow(wt, Wid, 0, &windp);
xue@1 2791 double* wini=NewWindow(wtHann, Wid, NULL, NULL);
xue@1 2792 for (int i=0; i<Wid; i++)
xue@1 2793 if (winf[i]!=0) wini[i]=wini[i]/winf[i];
xue@1 2794 AllocateFFTBuffer(Wid, ldata, w, x);
xue@1 2795 double* tmpdata=new double[HWid];
xue@1 2796 memset(tmpdata, 0, HWid*sizeof(double));
xue@1 2797
xue@1 2798 for (int i=0; i<Fr; i++)
xue@1 2799 {
xue@1 2800 if (lxspan[i]==0)
xue@1 2801 {
xue@1 2802 DoubleToInt(&((char*)dataout)[i*HWid*BytesPerSample], BytesPerSample, tmpdata, HWid);
xue@1 2803 memset(tmpdata, 0, sizeof(double)*HWid);
xue@1 2804 continue;
xue@1 2805 }
xue@1 2806 if (lxspan[i]==1)
xue@1 2807 {
xue@1 2808 IntToDouble(ldata, &((char*)data)[i*HWid*BytesPerSample], BytesPerSample, Wid);
xue@1 2809 if (i>0)
xue@1 2810 for (int k=0; k<HWid; k++)
xue@1 2811 ldata[k]=ldata[k]*winf[k]*wini[k];
xue@1 2812 for (int k=HWid; k<Wid; k++)
xue@1 2813 ldata[k]=ldata[k]*winf[k]*wini[k];
xue@1 2814
xue@1 2815 for (int k=0; k<HWid; k++) tmpdata[k]+=ldata[k];
xue@1 2816 DoubleToInt(&((char*)dataout)[i*HWid*BytesPerSample], BytesPerSample, tmpdata, HWid);
xue@1 2817 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 2818 continue;
xue@1 2819 }
xue@1 2820 IntToDouble(ldata, &((char*)data)[i*HWid*BytesPerSample], BytesPerSample, Wid);
xue@1 2821 if (i>0)
xue@1 2822 for (int k=0; k<HWid; k++)
xue@1 2823 ldata[k]=ldata[k]*winf[k];
xue@1 2824 for (int k=HWid; k<Wid; k++)
xue@1 2825 ldata[k]=ldata[k]*winf[k];
xue@1 2826
xue@1 2827 RFFTC(ldata, NULL, NULL, Order, w, x, 0);
xue@1 2828
xue@1 2829 if (!lspan[i][0]) x[0].x=x[0].y=0;
xue@1 2830 for (int j=1; j<=HWid; j++)
xue@1 2831 if (!lspan[i][j]) x[j].x=x[Wid-j].x=x[j].y=x[Wid-j].y=0;
xue@1 2832
xue@1 2833 CIFFTR(x, Order, w, ldata);
xue@1 2834
xue@1 2835 if (i>0)
xue@1 2836 for (int k=0; k<HWid; k++)
xue@1 2837 ldata[k]=ldata[k]*wini[k];
xue@1 2838 for (int k=HWid; k<Wid; k++)
xue@1 2839 ldata[k]=ldata[k]*wini[k];
xue@1 2840
xue@1 2841
xue@1 2842 for (int k=0; k<HWid; k++)
xue@1 2843 tmpdata[k]+=ldata[k];
xue@1 2844 DoubleToInt(&((char*)dataout)[i*HWid*BytesPerSample], BytesPerSample, tmpdata, HWid);
xue@1 2845 memcpy(tmpdata, &ldata[HWid], HWid*sizeof(double));
xue@1 2846 }
xue@1 2847 DoubleToInt(&((char*)dataout)[Fr*HWid*BytesPerSample], BytesPerSample, tmpdata, HWid);
xue@1 2848 memset(&((char*)dataout)[(Fr*HWid+HWid)*BytesPerSample], 0, BytesPerSample*(Count-Fr*HWid-HWid));
xue@1 2849
xue@1 2850 FreeFFTBuffer(ldata);
xue@1 2851
xue@1 2852 delete[] lspan[0];
xue@1 2853 delete[] lspan;
xue@1 2854 delete[] lxspan;
xue@1 2855 delete[] tmpdata;
xue@1 2856 delete[] winf;
xue@1 2857 delete[] wini;
xue@1 2858 }//TFFilter
xue@1 2859
xue@1 2860
xue@1 2861