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: #include xue@1: #include Chris@2: #include "quickspec.h" xue@1: Chris@5: /** \file quickspec.h */ xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::TQuickSpectrogram: xue@1: xue@1: In: AParent: pointer argument for calling G, if G is specified xue@1: AnId: integer argument for calling G, if G is specified xue@1: G: pointer to a function that supplies buffers used for FFT, 0 by default xue@1: Ausex: set if complete complex spectrogram is to be buffered and accessible xue@1: Auseph: set if phase spectrogram is to be buffered and accessible xue@1: */ xue@1: __fastcall TQuickSpectrogram::TQuickSpectrogram(void* AParent, int AnId, bool Ausex, bool Auseph, GetBuf G) xue@1: { xue@1: memset(this, 0, sizeof(TQuickSpectrogram)); xue@1: Parent=AParent; xue@1: Id=AnId; xue@1: usex=Ausex; xue@1: useph=Auseph; xue@1: GetFFTBuffers=G; xue@1: BufferSize=QSpec_BufferSize; xue@1: fwt=wtRectangle; xue@1: Wid=1024; xue@1: Offst=512; xue@1: }//TQuickSpectrogram xue@1: xue@1: //TQuickSpectrogram::~TQuickSpectrogram xue@1: __fastcall TQuickSpectrogram::~TQuickSpectrogram() xue@1: { xue@1: FreeBuffers(); xue@1: free8(fw); xue@1: free8(fwin); xue@1: free(fhbi); xue@1: }//~TQuickSpectrogram xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::A: accesses amplitude spectrogram by frame xue@1: xue@1: In: fr: frame index, 0-based xue@1: xue@1: Returns pointer to amplitude spectrum of the fr'th frame, NULL if N/A xue@1: */ xue@1: QSPEC_FORMAT* __fastcall TQuickSpectrogram::A(int fr) xue@1: { xue@1: if (Capacity==0) SetFrCapacity((DataLength-Wid)/Offst+2); xue@1: if (fr<0 || fr>=Capacity) return NULL; xue@1: if (Frame[fr]<0 || !Valid[fr]) CalculateSpectrum(fr); xue@1: return fA[Frame[fr]]; xue@1: }//A xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::AddBuffer: increases internal buffer by BufferSize frames. Allocated buffers xue@1: beyond Capacity frames will not be indexed or used by TQuickSpectrogram. xue@1: */ xue@1: void TQuickSpectrogram::AddBuffer() xue@1: { xue@1: int base=1, Dim=Wid/2+1; xue@1: if (usex) base+=2; xue@1: if (useph) base+=1; xue@1: QSPEC_FORMAT* newbuffer=(QSPEC_FORMAT*)malloc(sizeof(QSPEC_FORMAT)*Dim*BufferSize*base); xue@1: int fr0=BufferCount*BufferSize; xue@1: for (int i=0; i*)&newbuffer[(BufferSize+i*2)*Dim], base+=2; xue@1: if (useph) fPh[fr]=&newbuffer[(BufferSize*base+i)*Dim]; xue@1: } xue@1: else break; xue@1: } xue@1: BufferCount++; xue@1: }//AddBuffer xue@1: Chris@5: /** xue@1: method TQuickSpectrogram::AddBuffer: increase internal buffer by a multiple of BufferSize so that xue@1: it will be enough to host another AddFrCount frames. xue@1: */ xue@1: void TQuickSpectrogram::AddBuffer(int AddFrCount) xue@1: { xue@1: while (FrCount+AddFrCount>BufferSize*BufferCount) AddBuffer(); xue@1: }//AddBuffer xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function IntToDouble: copy content of integer array to double array xue@1: xue@1: In: in: pointer to integer array xue@1: BytesPerSample: number of bytes each integer takes xue@1: Count: size of integer array, in integers xue@1: Out: vector out[Count]. xue@1: xue@1: No return value. xue@1: */ xue@1: void IntToDouble(double* out, void* in, int BytesPerSample, int Count) xue@1: { xue@1: if (BytesPerSample==1){unsigned char* in8=(unsigned char*)in; for (int k=0; k* lX=usex?fSpec[realfr]:NULL; xue@1: //choose the buffer actually used for FFT - use lX if it is specified as complex double array xue@1: //because it saves unnecessary data copying operations xue@1: cdouble *lx=(usex && sizeof(QSPEC_FORMAT)==sizeof(double))?(cdouble*)lX:x; xue@1: xue@1: //Actual FFT xue@1: if (fr*Offst+Wid<=DataLength) xue@1: ::CalculateSpectrum(&((char*)Data)[fr*Offst*BytesPerSample], BytesPerSample, win, fA[realfr], lph, Wid, w, lx, hbi); xue@1: else xue@1: ::CalculateSpectrum(&((char*)Data)[fr*Offst*BytesPerSample], BytesPerSample, win, fA[realfr], lph, Wid, DataLength-fr*Offst, w, x, hbi); xue@1: xue@1: //optional data copy from x to lX xue@1: if (usex && lx==x) for (int i=0; i=Capacity) fr2=Capacity-1; xue@1: for (int fr=fr1; fr<=fr2; fr++) if (Frame[fr]>=0) Valid[fr]=false, result++; xue@1: } xue@1: return result; xue@1: }//Invalidate xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::Ph: accesses phase spectrogram by frame xue@1: xue@1: In: fr: frame index, 0-based xue@1: xue@1: Returns pointer to phase spectrum of the fr'th frame, NULL if N/A xue@1: */ xue@1: QSPEC_FORMAT* __fastcall TQuickSpectrogram::Ph(int fr) xue@1: { xue@1: if (Capacity==0) SetFrCapacity((DataLength-Wid)/Offst+2); xue@1: if (fr<0 || fr>=Capacity) return NULL; xue@1: if (Frame[fr]<0 || !Valid[fr]) CalculateSpectrum(fr); xue@1: return fPh[Frame[fr]]; xue@1: }//Ph xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::SetFrCapacity: sets the capacity, i.e. the maximal number of frames handled xue@1: by this TQuickSpectrogram. xue@1: xue@1: In: AnFrCapacity: the new Capacity, in frames xue@1: xue@1: This method should not be called to set Capacity to a smaller value. xue@1: */ xue@1: void TQuickSpectrogram::SetFrCapacity(int AnFrCapacity) xue@1: { xue@1: //adjusting the size of index and validity arrays xue@1: Frame=(int*)realloc(Frame, sizeof(int)*AnFrCapacity); xue@1: Valid=(int*)realloc(Valid, sizeof(int)*AnFrCapacity); xue@1: xue@1: // xue@1: fA=(QSPEC_FORMAT**)realloc(fA, sizeof(QSPEC_FORMAT*)*AnFrCapacity); xue@1: if (usex) fSpec=(cmplx**)realloc(fSpec, sizeof(cmplx*)*AnFrCapacity); xue@1: if (useph) fPh=(QSPEC_FORMAT**)realloc(fPh, sizeof(QSPEC_FORMAT*)*AnFrCapacity); xue@1: if (AnFrCapacity>Capacity) xue@1: { xue@1: memset(&Frame[Capacity], 0xFF, sizeof(int)*(AnFrCapacity-Capacity)); xue@1: memset(&Valid[Capacity], 0x00, sizeof(int)*(AnFrCapacity-Capacity)); xue@1: xue@1: if (Capacity*)(&thisbuffer[(BufferSize+lfr*2)*Dim]), base+=2; xue@1: if (useph) fPh[fr]=&thisbuffer[(BufferSize*base+lfr)*Dim]; xue@1: } xue@1: else break; xue@1: } xue@1: } xue@1: } xue@1: Capacity=AnFrCapacity; xue@1: }//SetFrCapacity xue@1: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: method TQuickSpectrogram::Ph: accesses complex spectrogram by frame xue@1: xue@1: In: fr: frame index, 0-based xue@1: xue@1: Returns pointer to complex spectrum of the fr'th frame, NULL if N/A xue@1: */ xue@1: cmplx* __fastcall TQuickSpectrogram::Spec(int fr) xue@1: { xue@1: if (Capacity==0) SetFrCapacity((DataLength-Wid)/Offst+2); xue@1: if (fr<0 || fr>=Capacity) return NULL; xue@1: if (Frame[fr]<0 || !Valid[fr]) CalculateSpectrum(fr); xue@1: return fSpec[Frame[fr]]; xue@1: }//Spec xue@1: xue@1: