xue@11: /* xue@11: Harmonic sinusoidal modelling and tools xue@11: xue@11: C++ code package for harmonic sinusoidal modelling and relevant signal processing. xue@11: Centre for Digital Music, Queen Mary, University of London. xue@11: This file copyright 2011 Wen Xue. xue@11: xue@11: This program is free software; you can redistribute it and/or xue@11: modify it under the terms of the GNU General Public License as xue@11: published by the Free Software Foundation; either version 2 of the xue@11: License, or (at your option) any later version. xue@11: */ xue@1: //--------------------------------------------------------------------------- xue@1: xue@1: #include Chris@2: #include Chris@3: #include xue@1: #include "procedures.h" xue@1: #include "matrix.h" xue@1: #include "opt.h" Chris@2: #include "sinest.h" xue@1: Chris@5: /** \file procedures.h */ Chris@5: xue@1: //--------------------------------------------------------------------------- xue@1: //TGMM methods xue@1: xue@1: //method TGMM::TGMM: default constructor xue@1: TGMM::TGMM() xue@1: { xue@1: p=0, m=dev=0; xue@1: }//TGMM xue@1: xue@1: //method GMM:~TGMM: default destructor xue@1: TGMM::~TGMM() xue@1: { xue@1: ReleaseGMM(p, m, dev) xue@1: }; xue@1: xue@1: //--------------------------------------------------------------------------- xue@1: //TFSpans methods xue@1: xue@1: //method TTFSpans: default constructor xue@1: TTFSpans::TTFSpans() xue@1: { xue@1: Count=0; xue@1: Capacity=100; xue@1: Items=new TTFSpan[Capacity]; xue@1: }//TTFSpans xue@1: xue@1: //method ~TTFSpans: default destructor xue@1: TTFSpans::~TTFSpans() xue@1: { xue@1: delete[] Items; xue@1: }//~TTFSpans xue@1: Chris@5: /** xue@1: method Add: add a new span to the list xue@1: xue@1: In: ATFSpan: the new span to add xue@1: */ xue@1: void TTFSpans::Add(TTFSpan& ATFSpan) xue@1: { xue@1: if (Count==Capacity) xue@1: { xue@1: int OldCapacity=Capacity; xue@1: Capacity+=50; xue@1: TTFSpan* NewItems=new TTFSpan[Capacity]; xue@1: memcpy(NewItems, Items, sizeof(TTFSpan)*OldCapacity); xue@1: delete[] Items; xue@1: Items=NewItems; xue@1: } xue@1: Items[Count]=ATFSpan; xue@1: Count++; xue@1: }//Add xue@1: Chris@5: /** xue@1: method Clear: discard the current content without freeing memory. xue@1: */ xue@1: void TTFSpans::Clear() xue@1: { xue@1: Count=0; xue@1: }//Clear xue@1: Chris@5: /** xue@1: method Delete: delete a span from current list xue@1: xue@1: In: Index: index to the span to delete xue@1: */ xue@1: int TTFSpans::Delete(int Index) xue@1: { xue@1: if (Index<0 || Index>=Count) xue@1: return 0; xue@1: memmove(&Items[Index], &Items[Index+1], sizeof(TTFSpan)*(Count-1-Index)); xue@1: Count--; xue@1: return 1; xue@1: }//Delete xue@1: xue@1: //--------------------------------------------------------------------------- xue@1: //SpecTrack methods xue@1: Chris@5: /** xue@1: method TSpecTrack::Add: adds a SpecPeak to the track. xue@1: xue@1: In: APeak: the SpecPeak to add. xue@1: */ xue@1: int TSpecTrack::Add(TSpecPeak& APeak) xue@1: { xue@1: if (Count>=Capacity) xue@1: { xue@1: Peaks=(TSpecPeak*)realloc(Peaks, sizeof(TSpecPeak)*(Capacity*2)); xue@1: Capacity*=2; xue@1: } xue@1: int ind=LocatePeak(APeak); xue@1: if (ind<0) xue@1: { xue@1: InsertPeak(APeak, -ind-1); xue@1: ind=-ind-1; xue@1: } xue@1: xue@1: int t=APeak.t; xue@1: double f=APeak.f; xue@1: if (Count==1) t1=t2=t, fmin=fmax=f; xue@1: else xue@1: { xue@1: if (tt2) t2=t; xue@1: if (ffmax) fmax=f; xue@1: } xue@1: return ind; xue@1: }//Add xue@1: Chris@5: /** xue@1: method TSpecTrack::TSpecTrack: creates a SpecTrack with an inital capacity. xue@1: xue@1: In: ACapacity: initial capacity, i.e. the number SpecPeak's to allocate storage space for. xue@1: */ xue@1: TSpecTrack::TSpecTrack(int ACapacity) xue@1: { xue@1: Count=0; xue@1: Capacity=ACapacity; xue@1: Peaks=new TSpecPeak[Capacity]; xue@1: }//TSpecTrack xue@1: xue@1: //method TSpecTrack::~TSpecTrack: default destructor. xue@1: TSpecTrack::~TSpecTrack() xue@1: { xue@1: delete[] Peaks; xue@1: }//TSpecTrack xue@1: Chris@5: /** xue@1: method InsertPeak: inserts a new SpecPeak into the track at a given index. Internal use only. xue@1: xue@1: In: APeak: the SpecPeak to insert. xue@1: index: the position in the list to place the new SpecPeak. Original SpecPeak's at and after this xue@1: position are shifted by 1 posiiton. xue@1: */ xue@1: void TSpecTrack::InsertPeak(TSpecPeak& APeak, int index) xue@1: { xue@1: memmove(&Peaks[index+1], &Peaks[index], sizeof(TSpecPeak)*(Count-index)); xue@1: Peaks[index]=APeak; xue@1: Count++; xue@1: }//InsertPeak xue@1: Chris@5: /** xue@1: method TSpecTrack::LocatePeak: looks for a SpecPeak in the track that has the same time (t) as APeak. xue@1: xue@1: In: APeak: a SpecPeak xue@1: xue@1: Returns the index in this track of the first SpecPeak that has the same time stamp as APeak. However, xue@1: if there is no peak with that time stamp, the method returns -1 if APeaks comes before the first xue@1: SpecPeak, -2 if between 1st and 2nd SpecPeak's, -3 if between 2nd and 3rd SpecPeak's, etc. xue@1: */ xue@1: int TSpecTrack::LocatePeak(TSpecPeak& APeak) xue@1: { xue@1: if (APeak.tPeaks[Count-1].t) return -Count-1; xue@1: xue@1: if (APeak.t==Peaks[0].t) return 0; xue@1: else if (APeak.t==Peaks[Count-1].t) return Count-1; xue@1: xue@1: int a=0, b=Count-1, c=(a+b)/2; xue@1: while (a0) zero=-size2/2, trunc=true; xue@1: if (pre_buffer==NULL || (post_buffer==NULL && size2+zero!=0)) trunc=true; xue@1: xue@1: AllocateFFTBuffer(Wid, fft, w, x1); xue@1: int* hbitinv=CreateBitInvTable(order-1); xue@1: cdouble* x2=new cdouble[Wid]; xue@1: double* tmp=new double[HWid]; xue@1: memset(tmp, 0, sizeof(double)*HWid); xue@1: xue@1: memcpy(fft, source2, sizeof(double)*size2); xue@1: memset(&fft[size2], 0, sizeof(double)*(Wid-size2)); xue@1: RFFTC(fft, 0, 0, order, w, x2, hbitinv); xue@1: xue@1: double r1, r2, i1, i2; xue@1: int ind, ind_; xue@1: for (int i=0; i0) xue@1: { xue@1: memcpy(fft, &source1[Fr*HWid], sizeof(double)*res); xue@1: memset(&fft[res], 0, sizeof(double)*(Wid-res)); xue@1: xue@1: RFFTC(fft, 0, 0, order, w, x1, hbitinv); xue@1: xue@1: for (int j=0; jsize1) xue@1: { xue@1: memcpy(&dest[ind], tmp, sizeof(double)*(size1-ind)); xue@1: if (!trunc && post_buffer) xue@1: { xue@1: if (ind_>size1+size2+zero) xue@1: memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(size2+zero)); xue@1: else xue@1: memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(ind_-size1)); xue@1: } xue@1: } xue@1: else xue@1: memcpy(&dest[ind], tmp, sizeof(double)*HWid); xue@1: memcpy(tmp, &fft[HWid], sizeof(double)*HWid); xue@1: Fr++; xue@1: } xue@1: xue@1: ind=Fr*HWid+zero; xue@1: ind_=ind+HWid; xue@1: xue@1: if (indsize1) xue@1: { xue@1: memcpy(&dest[ind], tmp, sizeof(double)*(size1-ind)); xue@1: if (!trunc && post_buffer) xue@1: { xue@1: if (ind_>size1+size2+zero) xue@1: memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(size2+zero)); xue@1: else xue@1: memcpy(post_buffer, &tmp[size1-ind], sizeof(double)*(ind_-size1)); xue@1: } xue@1: } xue@1: else xue@1: memcpy(&dest[ind], tmp, sizeof(double)*HWid); xue@1: } xue@1: else //ind>=size1 => ind_>=size1+size2+zero xue@1: { xue@1: if (!trunc && post_buffer) xue@1: memcpy(&post_buffer[ind-size1], tmp, sizeof(double)*(size1+size2+zero-ind)); xue@1: } xue@1: xue@1: FreeFFTBuffer(fft); xue@1: delete[] x2; xue@1: delete[] tmp; xue@1: delete[] hbitinv; xue@1: }//FFTConv xue@1: Chris@5: /** xue@1: function FFTConv: the simplified version using two output buffers instead of three. This is almost xue@1: equivalent to setting zero=-size2 in the three-output-buffer version (so that post_buffer no longer xue@1: exists), except that this version requires size2 (renamed HWid) be a power of 2, and pre_buffer point xue@1: to the END of the storage (so that pre_buffer=dest automatically connects the two buffers in a xue@1: continuous memory block). xue@1: xue@1: In: source1[size1]: convolvend xue@1: source2[HWid]: second convolved, HWid be a power of 2 xue@1: pre_buffer[-HWid:-1]: buffer hosting values to be overlap-added to the start of the result. xue@1: Out: dest[size1]: main output buffer, now hosting end part of the result (after HWid samples). xue@1: pre_buffer[-HWid:-1]: now updated by added the start of the result xue@1: xue@1: No return value. xue@1: */ xue@1: void FFTConv(double* dest, double* source1, int size1, double* source2, int HWid, double* pre_buffer) xue@1: { xue@1: int Wid=HWid*2; xue@11: int order=Log2(Wid); xue@1: int Fr=size1/HWid; xue@1: int res=size1-HWid*Fr; xue@1: xue@1: AllocateFFTBuffer(Wid, fft, w, x1); xue@1: cdouble *x2=new cdouble[Wid]; xue@1: double *tmp=new double[HWid]; xue@1: int* hbitinv=CreateBitInvTable(order-1); xue@1: xue@1: memcpy(fft, source2, sizeof(double)*HWid); xue@1: memset(&fft[HWid], 0, sizeof(double)*HWid); xue@1: RFFTC(fft, 0, 0, order, w, x2, hbitinv); xue@1: xue@1: double r1, r2, i1, i2; xue@1: for (int i=0; i0) xue@1: { xue@1: if (Fr==0) memset(tmp, 0, sizeof(double)*HWid); xue@1: xue@1: memcpy(fft, &source1[Fr*HWid], sizeof(double)*res); xue@1: memset(&fft[res], 0, sizeof(double)*(Wid-res)); xue@1: xue@1: RFFTC(fft, 0, 0, order, w, x1, hbitinv); xue@1: for (int j=0; j0) zero=-size2/2, trunc=true; xue@1: if (pre_buffer==NULL || (post_buffer==NULL && size2+zero!=0)) trunc=true; xue@1: xue@1: AllocateFFTBuffer(Wid, fft, w, x1); xue@1: cdouble* x2=new cdouble[Wid]; xue@1: double* tmp=new double[HWid]; xue@1: memset(tmp, 0, sizeof(double)*HWid); xue@1: int* hbitinv=CreateBitInvTable(order-1); xue@1: xue@1: memcpy(fft, source2, sizeof(double)*size2); xue@1: memset(&fft[size2], 0, sizeof(double)*(Wid-size2)); xue@1: RFFTC(fft, 0, 0, order, w, x2, hbitinv); xue@1: xue@1: double r1, r2, i1, i2; xue@1: int ind, ind_; xue@1: for (int i=0; i0) xue@1: { xue@1: IntToDouble(fft, &source1[Fr*HWid*bps], bps, res); xue@1: memset(&fft[res], 0, sizeof(double)*(Wid-res)); xue@1: xue@1: RFFTC(fft, 0, 0, order, w, x1, hbitinv); xue@1: xue@1: for (int j=0; jsize1) xue@1: { xue@1: DoubleToInt(&dest[ind*bps], bps, tmp, size1-ind); xue@1: if (!trunc && post_buffer) xue@1: { xue@1: if (ind_>size1+size2+zero) xue@1: DoubleToInt(post_buffer, bps, &tmp[size1-ind], size2+zero); xue@1: else xue@1: DoubleToInt(post_buffer, bps, &tmp[size1-ind], ind_-size1); xue@1: } xue@1: } xue@1: else xue@1: DoubleToInt(&dest[ind*bps], bps, tmp, HWid); xue@1: memcpy(tmp, &fft[HWid], sizeof(double)*HWid); xue@1: Fr++; xue@1: } xue@1: xue@1: ind=Fr*HWid+zero; xue@1: ind_=ind+HWid; xue@1: xue@1: if (indsize1) xue@1: { xue@1: DoubleToInt(&dest[ind*bps], bps, tmp, size1-ind); xue@1: if (!trunc && post_buffer) xue@1: { xue@1: if (ind_>size1+size2+zero) xue@1: DoubleToInt(post_buffer, bps, &tmp[size1-ind], size2+zero); xue@1: else xue@1: DoubleToInt(post_buffer, bps, &tmp[size1-ind], ind_-size1); xue@1: } xue@1: } xue@1: else xue@1: DoubleToInt(&dest[ind*bps], bps, tmp, HWid); xue@1: } xue@1: else //ind>=size1 => ind_>=size1+size2+zero xue@1: { xue@1: if (!trunc && post_buffer) xue@1: DoubleToInt(&post_buffer[(ind-size1)*bps], bps, tmp, size1+size2+zero-ind); xue@1: } xue@1: xue@1: FreeFFTBuffer(fft); xue@1: delete[] x2; xue@1: delete[] tmp; xue@1: delete[] hbitinv; xue@1: }//FFTConv xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function FFTFilter: FFT with cosine-window overlap-add: This FFT filter is not an actural LTI system, xue@1: but an block processing with overlap-add. In this function the blocks are overlapped by 50% and summed xue@1: up with Hann windowing. xue@1: xue@1: In: data[Count]: input data xue@1: Wid: DFT size xue@1: On, Off: cut-off frequencies of FFT filter. OnOff: band-stop. xue@1: Out: dataout[Count]: filtered data xue@1: xue@1: No return value. Identical data and dataout allowed xue@1: */ xue@1: void FFTFilter(double* dataout, double* data, int Count, int Wid, int On, int Off) xue@1: { xue@11: int Order=Log2(Wid); xue@1: int HWid=Wid/2; xue@1: int Fr=(Count-Wid)/HWid+1; xue@1: AllocateFFTBuffer(Wid, ldata, w, x); xue@1: xue@1: double* win=new double[Wid]; xue@1: for (int i=0; i0) xue@1: for (int k=0; k=1) xue@1: memset(&x[Wid-On+1], 0, (On-1)*sizeof(cdouble)); xue@1: if (Off*2<=Wid) xue@1: memset(&x[Off], 0, (Wid-Off*2+1)*sizeof(cdouble)); xue@1: } xue@1: else //band stop: set [Off, On) to zero. xue@1: { xue@1: memset(&x[Off], 0, sizeof(cdouble)*(On-Off)); xue@1: memset(&x[Wid-On+1], 0, sizeof(double)*(On-Off)); xue@1: } xue@1: xue@1: CIFFTR(x, Order, w, ldata); xue@1: xue@1: if (i>0) for (int k=0; k0) xue@1: for (int k=0; k0) xue@1: for (int k=0; k0) xue@1: for (int k=0; k=data[Count-1]) return Count-1; xue@1: if (valueB; xue@1: int count=0; xue@1: xue@1: int den=ceil(en), dst=floor(st); xue@1: if (den-dst<3) den++, dst--; xue@1: if (den-dst<3) den++, dst--; xue@1: if (dst<1) dst=1; xue@1: xue@1: double step=0.5; xue@1: int num=(den-dst)/step+1; xue@1: bool allochps=false, allocvhps=false; xue@1: if (hps==NULL) allochps=true, hps=new double[num]; xue@1: if (vhps==NULL) allocvhps=true, vhps=new double[num]; xue@1: xue@1: { xue@1: double* inp=new double[num]; xue@1: for (int i=0; ik1=ceil(lf-B); if (p->k1<0) p->k1=0; xue@1: p->k2=floor(lf+B); if (p->k2>=p->N/2) p->k2=p->N/2-1; xue@1: inp[i]=F(lf, params); xue@1: } xue@1: xue@1: for (int i=1; i=inp[i-1] && inp[i]>=inp[i+1]) //inp[i]=F(dst+step*i) xue@1: { xue@1: if (inp[i]==inp[i-1] && inp[i]==inp[i+1]) continue; xue@1: double fa=dst+step*(i-1), fb=dst+step*(i+1); xue@1: double ff=dst+step*i; xue@1: p->k1=ceil(ff-B); if (p->k1<0) p->k1=0; xue@1: p->k2=floor(ff+B); if (p->k2>=p->N/2) p->k2=p->N/2-1; xue@1: xue@1: double tmp=Newton1dmax(ff, fa, fb, ddF, params, dfshift, fshift, dF, dfshift, epf); xue@1: xue@1: //although we have selected inp[i] to be a local maximum, different truncation xue@1: // of local spectrum implies it may not hold as the truncation of inp[i] is xue@1: // used for recalculating inp[i-1] and inp[i+1] in init_Newton method. In this xue@1: // case we retry the sub-maximal frequency to see if it becomes a local maximum xue@1: // when the spectrum is truncated to centre on it. xue@1: xue@1: if (tmp==-0.5 || tmp==-0.7) //y(fa)<=y(ff)k1=ceil(ff2-B); if (p->k1<0) p->k1=0; xue@1: p->k2=floor(ff2+B); if (p->k2>=p->N/2) p->k2=p->N/2-1; xue@1: tmp=Newton1dmax(ff2, ff, fb, ddF, params, dfshift, fshift, dF, dfshift, epf); xue@1: p->k1=ceil(ff-B); if (p->k1<0) p->k1=0; xue@1: p->k2=floor(ff+B); if (p->k2>=p->N/2) p->k2=p->N/2-1; */ xue@1: } xue@1: else if (tmp==-0.6 || tmp==-0.8) //y(fb)<=y(ff)hxpeak; xue@1: } xue@1: if (ff>=st && ff<=en && ff>dst+step*(i-0.99) && ff0.1) xue@1: // { xue@1: hps[count]=ff; xue@1: count++; xue@1: // } xue@1: } xue@1: } xue@1: } xue@1: delete[] inp; xue@1: } xue@1: xue@1: if (allochps) hps=(double*)realloc(hps, sizeof(double)*count); xue@1: if (allocvhps) vhps=(double*)realloc(vhps, sizeof(double)*count); xue@1: return count; xue@1: }//HxPeak2 xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function InsertDec: inserts value into sorted decreasing list xue@1: xue@1: In: data[Count]: a sorted decreasing list. xue@1: value: the value to be added xue@1: Out: data[Count]: the list with $value inserted if the latter is larger than its last entry, in which xue@1: case the original last entry is discarded. xue@1: xue@1: Returns the index where $value is located in data[], or -1 if $value is smaller than or equal to xue@1: data[Count-1]. xue@1: */ xue@1: int InsertDec(int value, int* data, int Count) xue@1: { xue@1: if (Count<=0) return -1; xue@1: if (value<=data[Count-1]) return -1; xue@1: if (value>data[0]) xue@1: { xue@1: memmove(&data[1], &data[0], sizeof(int)*(Count-1)); xue@1: data[0]=value; xue@1: return 0; xue@1: } xue@1: xue@1: //now Count>=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)>=value>D(end) xue@1: while (end-head>1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value<=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)>=value>D(end) xue@1: memmove(&data[end+1], &data[end], sizeof(int)*(Count-end-1)); xue@1: data[end]=value; xue@1: return end; xue@1: }//InsertDec xue@1: //the double version xue@1: int InsertDec(double value, double* data, int Count) xue@1: { xue@1: if (Count<=0) return -1; xue@1: if (value<=data[Count-1]) return -1; xue@1: if (value>data[0]) xue@1: { xue@1: memmove(&data[1], &data[0], sizeof(double)*(Count-1)); xue@1: data[0]=value; xue@1: return 0; xue@1: } xue@1: xue@1: //now Count>=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)>=value>D(end) xue@1: while (end-head>1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value<=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)>=value>D(end) xue@1: memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1)); xue@1: data[end]=value; xue@1: return end; xue@1: }//InsertDec xue@1: Chris@5: /** xue@1: function InsertDec: inserts value and attached integer into sorted decreasing list xue@1: xue@1: In: data[Count]: a sorted decreasing list xue@1: indices[Count]: a list of integers attached to entries of data[] xue@1: value, index: the value to be added and its attached integer xue@1: Out: data[Count], indices[Count]: the lists with $value and $index inserted if $value is larger than xue@1: the last entry of data[], in which case the original last entries are discarded. xue@1: xue@1: Returns the index where $value is located in data[], or -1 if $value is smaller than or equal to xue@1: data[Count-1]. xue@1: */ xue@1: int InsertDec(double value, int index, double* data, int* indices, int Count) xue@1: { xue@1: if (Count<=0) return -1; xue@1: if (value<=data[Count-1]) return -1; xue@1: if (value>data[0]) xue@1: { xue@1: memmove(&data[1], data, sizeof(double)*(Count-1)); xue@1: memmove(&indices[1], indices, sizeof(int)*(Count-1)); xue@1: data[0]=value, indices[0]=index; xue@1: return 0; xue@1: } xue@1: xue@1: //now Count>=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)>=value>D(end) xue@1: while (end-head>1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value<=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)>=value>D(end) xue@1: memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1)); xue@1: memmove(&indices[end+1], &indices[end], sizeof(int)*(Count-end-1)); xue@1: data[end]=value, indices[end]=index; xue@1: return end; xue@1: }//InsertDec xue@1: Chris@5: /** xue@1: InsertInc: inserts value into sorted increasing list. xue@1: xue@1: In: data[Count]: a sorted increasing list. xue@1: Capacity: maximal size of data[] xue@1: value: the value to be added xue@1: Compare: pointer to function that compare two values xue@1: Out: data[Count]: the list with $value inserted. If the original list is full (Count=Capacity) then xue@1: either $value, or the last entry of data[], whichever is larger, is discarded. xue@1: xue@1: Returns the index where $value is located in data[], or -1 if it is not inserted, which happens if xue@1: Count=Capacity and $value is larger than or equal to the last entry in data[Capacity]. xue@1: */ xue@1: int InsertInc(void* value, void** data, int Count, int Capacity, int (*Compare)(void*, void*)) xue@1: { xue@1: if (Capacity<=0) return -1; xue@1: if (Count>Capacity) Count=Capacity; xue@1: xue@1: //Compare(A,B)<0 if A0 if A>B xue@1: int PosToInsert; xue@1: if (Count==0) PosToInsert=0; xue@1: else if (Compare(value, data[Count-1])>0) PosToInsert=Count; xue@1: else if (Compare(value, data[0])<0) PosToInsert=0; xue@1: else xue@1: { xue@1: //now Count>=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)<=value1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (Compare(value, data[mid])>=0) head=mid; xue@1: else end=mid; xue@1: } xue@1: //D(head=end-1)<=value=Capacity) return -1; xue@1: memmove(&data[PosToInsert+1], &data[PosToInsert], sizeof(void*)*(Count-PosToInsert-1)); xue@1: data[PosToInsert]=value; xue@1: } xue@1: return PosToInsert; xue@1: }//InsertInc xue@1: Chris@5: /** xue@1: function InsertInc: inserts value into sorted increasing list xue@1: xue@1: In: data[Count]: a sorted increasing list. xue@1: value: the value to be added xue@1: doinsert: specifies whether the actually insertion is to be performed xue@1: Out: data[Count]: the list with $value inserted if the latter is smaller than its last entry, in which xue@1: case the original last entry of data[] is discarded. xue@1: xue@1: Returns the index where $value is located in data[], or -1 if value is larger than or equal to xue@1: data[Count-1]. xue@1: */ xue@1: int InsertInc(double value, double* data, int Count, bool doinsert) xue@1: { xue@1: if (Count<=0) return -1; xue@1: if (value>=data[Count-1]) return -1; xue@1: if (value=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)<=value1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value>=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)<=value=data[Count-1]) return -1; xue@1: if (value=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)<=value1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value>=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)<=value=data[Count-1]) return -1; xue@1: if (value=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)>=value>D(end) xue@1: while (end-head>1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value>=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)>=value>D(end) xue@1: memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1)); xue@1: memmove(&indices[end+1], &indices[end], sizeof(int)*(Count-end-1)); xue@1: data[end]=value, indices[end]=index; xue@1: return end; xue@1: }//InsertInc xue@1: //version where indices[] is double-precision floating point. xue@1: int InsertInc(double value, double index, double* data, double* indices, int Count) xue@1: { xue@1: if (Count<=0) return -1; xue@1: if (value>=data[Count-1]) return -1; xue@1: if (value=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)>=value>D(end) xue@1: while (end-head>1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value>=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)>=value>D(end) xue@1: memmove(&data[end+1], &data[end], sizeof(double)*(Count-end-1)); xue@1: memmove(&indices[end+1], &indices[end], sizeof(double)*(Count-end-1)); xue@1: data[end]=value, indices[end]=index; xue@1: return end; xue@1: }//InsertInc xue@1: Chris@5: /** xue@1: function InsertIncApp: inserts value into flexible-length sorted increasing list xue@1: xue@1: In: data[Count]: a sorted increasing list. xue@1: value: the value to be added xue@1: Out: data[Count+1]: the list with $value inserted. xue@1: xue@1: Returns the index where $value is located in data[], or -1 if Count<0. data[] must have Count+1 xue@1: storage units on calling. xue@1: */ xue@1: int InsertIncApp(double value, double* data, int Count) xue@1: { xue@1: if (Count<0) return -1; xue@1: if (Count==0){data[0]=value; return 0;} xue@1: if (value>=data[Count-1]){data[Count]=value; return Count;} xue@1: if (value=2 xue@1: int head=0, end=Count-1, mid; xue@1: xue@1: //D(head)<=value1) xue@1: { xue@1: mid=(head+end)/2; xue@1: if (value>=data[mid]) head=mid; xue@1: else end=mid; xue@1: } xue@1: xue@1: //D(head=end-1)<=valuehwid-2) k=hwid-2; xue@1: 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: double ph0=Atan2(hi, hr); xue@1: double c=cos(M_PI/hwid), s=sin(M_PI/hwid); xue@1: 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: 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: double ph1=Atan2(hi, hr); xue@1: result=(ph1-ph0)/(2*M_PI); xue@1: if (result<-0.5) result+=1; xue@1: if (result>0.5) result-=1; xue@1: result+=k*0.5/hwid; xue@1: break; xue@1: } xue@1: case 2: xue@1: break; xue@1: } xue@1: return result; xue@1: }//InstantFreq xue@1: Chris@5: /** xue@1: function InstantFreq; calculates "frequency spectrum", a sequence of frequencies evaluated at DFT bins xue@1: xue@1: In: x[hwid]: spectrum with scale 2hwid xue@1: mode: must be 1. xue@1: Out: freqspec[hwid]: the frequency spectrum xue@1: xue@1: No return value. xue@1: */ xue@1: void InstantFreq(double* freqspec, int hwid, cdouble* x, int mode) xue@1: { xue@1: for (int i=0; icount-2) anindex=count-2; xue@1: xue@1: if (data[anindex]>data[anindex-1] && data[anindex]>data[anindex+1]) return anindex; xue@1: xue@1: if (data[anindex]0 && data[downind-1]>data[downind]) downind--; xue@1: if (data[anindex]upind-anindex) return upind; xue@1: else if (data[upind]laste) lmd+=step*lastdel, step/=2; xue@1: else lmd+=-step*sample*del; xue@1: } xue@1: while (e && iter<=maxiter && (!laste || fabs(laste-e)/e>eps)); xue@1: return sqrt(e/Count); xue@1: }//NegativeExp xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function: NL: noise level, calculated on 5% of total frames with least energy xue@1: xue@1: In: data[Count]: xue@1: Wid: window width for power level estimation xue@1: xue@1: Returns noise level, in rms. xue@1: */ xue@1: double NL(double* data, int Count, int Wid) xue@1: { xue@1: int Fr=Count/Wid; xue@1: int Num=Fr/20+1; xue@1: double* ene=new double[Num], tmp; xue@1: for (int i=0; imax) max=*ldata; xue@1: else if (-*ldata>max) max=-*ldata; xue@1: ldata++; xue@1: } xue@1: if (max>0) xue@1: { xue@1: Maxi=Maxi/max; xue@1: for (int i=0; iAmp, Count); xue@11: RFFTC(Amp, Amp, Arg, Log2(Count*Pad), w, x, 0); xue@1: xue@1: SmoothPhase(Arg, Count*Pad/2+1); xue@1: double result=Arg[Count*Pad/2]-Arg[0]; xue@1: delete[] Arg; xue@1: FreeFFTBuffer(Amp); xue@1: return result; xue@1: }//PhaseSpan xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function PolyFit: least square polynomial fitting y=sum(i){a[i]*x^i} xue@1: xue@1: In: x[N], y[N]: sample points xue@1: P: order of polynomial, Pmod/2) in-=mod; xue@1: if (in<-mod/2) in+=mod; xue@1: return in; xue@1: }//Res xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function Romberg: Romberg algorithm for numerical integration xue@1: xue@1: In: f: function to integrate xue@1: params: extra argument for calling f xue@1: a, b: integration boundaries xue@1: n: depth of sampling xue@1: xue@1: Returns the integral of f(*, params) over [a, b]. xue@1: */ xue@1: double Romberg(int n, double(*f)(double, void*), double a, double b, void* params) xue@1: { xue@1: int np=1; Chris@3: double* r1=new double[n+1]; xue@1: double* r2=new double[n+1]; xue@1: double h=b-a, *swp; xue@1: r1[1]=h*(f(a, params)+f(b, params))/2; xue@1: for (int i=2; i<=n; i++) xue@1: { xue@1: double akh=a+0.5*h; r2[1]=f(akh, params); xue@1: for (int k=2; k<=np; k++) {akh+=h; r2[1]+=f(akh, params);} //akh=a+(k-0.5)h xue@1: r2[1]=0.5*(r1[1]+h*r2[1]); xue@1: double fj=4; xue@1: 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: h/=2; np*=2; xue@1: swp=r1; r1=r2; r2=swp; xue@1: } xue@1: h=r1[n]; xue@1: delete[] r1; xue@1: delete[] r2; xue@1: return h; xue@1: }//Romberg xue@1: Chris@5: /** xue@1: function Romberg: Romberg algorithm for numerical integration, may return before specified depth on xue@1: convergence. xue@1: xue@1: In: f: function to integrate xue@1: params: extra argument for calling f xue@1: a, b: integration boundaries xue@1: n: depth of sampling xue@1: ep: convergence test threshold xue@1: xue@1: Returns the integral of f(*, params) over [a, b]. xue@1: */ xue@1: double Romberg(double(*f)(double, void*), double a, double b, void* params, int n, double ep) xue@1: { xue@1: int i, np=1; xue@1: double* r1=new double[n+1]; xue@1: double* r2=new double[n+1]; xue@1: double h=b-a, *swp; xue@1: r1[1]=h*(f(a, params)+f(b, params))/2; xue@1: bool mep=false; xue@1: for (i=2; i<=n; i++) xue@1: { xue@1: double akh=a+0.5*h; r2[1]=f(akh, params); xue@1: for (int k=2; k<=np; k++) {akh+=h; r2[1]+=f(akh, params);} //akh=a+(k-0.5)h xue@1: r2[1]=0.5*(r1[1]+h*r2[1]); xue@1: double fj=4; xue@1: 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: xue@1: if (fabs(r2[i]-r1[i-1])Count; i++) xue@1: { xue@1: int lx1, lx2, ly1, ly2; xue@1: lx1=(Spans->Items[i].T1-TOffst)/HWid-1; xue@1: lx2=(Spans->Items[i].T2-1-TOffst)/HWid; xue@1: ly1=Spans->Items[i].F1*2/Sps*HWid+0.001; xue@1: ly2=Spans->Items[i].F2*2/Sps*HWid+1; xue@1: if (lx1<0) lx1=0; xue@1: if (lx2>=Fr) lx2=Fr-1; xue@1: if (ly1<0) ly1=0; xue@1: if (ly1>HWid) ly1=HWid; xue@1: if (Pass) xue@1: for (int x=lx1; x<=lx2; x++) xue@1: for (int y=ly1; y<=ly2; y++) xue@1: lspan[x][y]=1; xue@1: else xue@1: for (int x=lx1; x<=lx2; x++) xue@1: for (int y=ly1; y<=ly2; y++) xue@1: lspan[x][y]=0; xue@1: } xue@1: for (int i=0; i0) xue@1: for (int k=0; k0) xue@1: for (int k=0; k0) xue@1: for (int k=0; kCount; i++) xue@1: { xue@1: int lx1, lx2, ly1, ly2; xue@1: lx1=(Spans->Items[i].T1-TOffst)/HWid-1; xue@1: lx2=(Spans->Items[i].T2-1-TOffst)/HWid; xue@1: ly1=Spans->Items[i].F1*2/Sps*HWid+0.001; xue@1: ly2=Spans->Items[i].F2*2/Sps*HWid+1; xue@1: if (lx1<0) lx1=0; xue@1: if (lx2>=Fr) lx2=Fr-1; xue@1: if (ly1<0) ly1=0; xue@1: if (ly1>HWid) ly1=HWid; xue@1: if (Pass) xue@1: for (int x=lx1; x<=lx2; x++) xue@1: for (int y=ly1; y<=ly2; y++) xue@1: lspan[x][y]=1; xue@1: else xue@1: for (int x=lx1; x<=lx2; x++) xue@1: for (int y=ly1; y<=ly2; y++) xue@1: lspan[x][y]=0; xue@1: } xue@1: for (int i=0; i0) xue@1: for (int k=0; k0) xue@1: for (int k=0; k0) xue@1: for (int k=0; k