annotate quickspec.h @ 13:de3961f74f30 tip

Add Linux/gcc Makefile; build fix
author Chris Cannam
date Mon, 05 Sep 2011 15:22:35 +0100
parents 977f541d6683
children
rev   line source
xue@11 1 /*
xue@11 2 Harmonic sinusoidal modelling and tools
xue@11 3
xue@11 4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
xue@11 5 Centre for Digital Music, Queen Mary, University of London.
xue@11 6 This file copyright 2011 Wen Xue.
xue@11 7
xue@11 8 This program is free software; you can redistribute it and/or
xue@11 9 modify it under the terms of the GNU General Public License as
xue@11 10 published by the Free Software Foundation; either version 2 of the
xue@11 11 License, or (at your option) any later version.
xue@11 12 */
xue@1 13 #ifndef QuickSpecH
xue@1 14 #define QuickSpecH
xue@1 15
xue@1 16 /*
Chris@5 17 \file quickspec.h - TQuickSpectrogram class
xue@1 18
xue@1 19 TQuickSpectrogram implements a compute-on-request spectrogram class. Every time one frame of the
xue@1 20 spectrogram is read from this class, it checks if the single-frame spectrogram has been computed
xue@1 21 already, computes it if not, and return the pointer to the spectrum.
xue@1 22
xue@1 23 Further reading: "A buffering technique for real-time spectrogram displaying.pdf"
xue@1 24 */
xue@1 25
xue@1 26
xue@1 27 #include <cstddef>
xue@1 28 #include <stdlib.h>
xue@1 29 #include "xcomplex.h"
xue@1 30 #include "windowfunctions.h"
xue@1 31 #include "fft.h"
xue@1 32 //---------------------------------------------------------------------------
xue@1 33
xue@1 34 #define QSPEC_FORMAT float //default spectral data format
xue@1 35 #define QSpec_BufferSize 1024 //default initial buffer size, in frames, of TQuickSpectrogram
xue@1 36
xue@1 37
Chris@5 38 /**
xue@1 39 __int24 is a 24bit signed integer type and __pint24 is its pointer type. Although __int24* will also
xue@1 40 return a pointer to an __int24 structure, operations based on __int24* may have unspecified results,
xue@1 41 depending on structure alignments imposed by compiler. It is therefore necessary to have an explicit
xue@1 42 pointer type __pint24 to enforce 24-bit data alighment.
xue@1 43
xue@1 44 Using __int24:
xue@1 45 When storage format is not a concern, __int24 can be used the same way as __int16 or __int32. However,
xue@1 46 a default 32-bit compiler may fail to implement compact 24-bit alignment to entries of an __int24[]
xue@1 47 array. If 24-bit alignment is desired, then always create the array dynamically with new[], which
xue@1 48 returns a __pint24 type pointer. Assigning a __pint24 type pointer to __int24* type variable should
xue@1 49 be avoided.
xue@1 50 */
xue@1 51
xue@1 52 #ifndef INT24
xue@1 53 #define INT24
xue@1 54 struct __int24;
xue@1 55 struct __pint24
xue@1 56 {
xue@1 57 char* p;
xue@1 58 __fastcall __pint24(){}
xue@1 59 __fastcall __pint24(const void* ap){p=(char*)ap;}
xue@1 60 __pint24& __fastcall operator=(const void* ap){p=(char*)ap; return *this;}
xue@1 61 __int24& __fastcall operator*(){return *(__int24*)p;}
xue@1 62 __int24& __fastcall operator[](int index){return *(__int24*)&p[3*index];}
xue@1 63 __pint24 __fastcall operator++(int){__pint24 result=*this; p+=3; return result;}
xue@1 64 __pint24& __fastcall operator++(){p+=3; return *this;}
xue@1 65 __pint24 __fastcall operator--(int){__pint24 result=*this; p-=3; return result;}
xue@1 66 __pint24& __fastcall operator--(){p-=3; return *this;}
xue@1 67 __pint24& __fastcall operator+=(int a){p+=3*a; return *this;}
xue@1 68 __pint24& __fastcall operator-=(int a){p-=3*a; return *this;}
xue@1 69 __fastcall operator void*() const{return p;}
xue@1 70 };
xue@1 71 struct __int24
xue@1 72 {
xue@1 73 __int16 loword;
xue@1 74 __int8 hibyte;
xue@1 75 __fastcall __int24(){}
xue@1 76 __fastcall __int24(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];}
xue@1 77 __fastcall __int24(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1];}
xue@1 78 __int24& __fastcall operator=(const __int32 a){loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;}
xue@1 79 __int24& __fastcall operator=(const double f){__int32 a=f; loword=*(__int16*)&a; hibyte=((__int16*)&a)[1]; return *this;}
xue@1 80 __fastcall operator __int32() const{__int32 result; *(__int16*)&result=loword; ((__int16*)&result)[1]=hibyte; return result;}
xue@1 81 __pint24 operator &(){return (__pint24)this;}
xue@1 82 void* operator new[](size_t count){void* result=malloc(3*count); return result;}
xue@1 83 void operator delete[](void* p){free(p);}
xue@1 84 };
xue@1 85 #endif
xue@1 86
Chris@5 87
Chris@5 88 typedef void (*GetBuf)(int Id, cdouble* &w, cdouble* &x, double* &win, int* &hbi, void* Parent);
Chris@5 89 /**
xue@1 90 TQuickSpectrogram is a spectrogram class the handles the computation and storage of a spectrogram.
xue@1 91
xue@1 92 Using TQuickSpectrogram:
xue@1 93
xue@1 94 TQuickSpectrogram provides read-only access to the spectrogram of a given waveform. The spectrogram
xue@1 95 contains a sequence of windowed Fourier transforms, computed from uniformly placed frames. The 0th
xue@1 96 frame starts at 0 (inclusive) and finishes at Wid (exclusive). Each spectrum has Wid/2+1 entries.
xue@1 97
xue@1 98 Follow these steps:
xue@1 99 1. create a QuickSpectrogram, specifying usex and useph, and optionally, external buffer provide G
xue@1 100 and its arguments Id and Parent;
xue@1 101 2. set Data, DataLength and BytesPerSample;
xue@1 102 3. set frame size and hop size Wid and Offst;
xue@1 103 4. if G is not specified, set window type (optional extra parameter) for computing spectra;
xue@1 104 5. access the spectrogram via A(fr), Spec(fr) (optional) and Ph(fr) (optional).
xue@1 105 Steps 2~4 do not have to follow the given order.
xue@1 106
xue@1 107 Call Invalidate() to notify the object of changes of waveform content.
xue@1 108 Call FreeBuffers() to return the object to the initial state before step 2.
xue@1 109 */
xue@1 110 class TQuickSpectrogram
xue@1 111 {
Chris@5 112 int BufferCount; ///< number of buffers in use
Chris@5 113 int BufferSize; ///< number of frames each additional buffer holds
Chris@5 114 int FrCount; ///< number of allocated frames
xue@1 115
xue@1 116 //internal storage of spectrogram
Chris@5 117 QSPEC_FORMAT** fPh; ///< phase spectrogram, optional
Chris@5 118 QSPEC_FORMAT** fA; ///< amplitude spectrogram, compulsory
Chris@5 119 cmplx<QSPEC_FORMAT>** fSpec; ///< complete complex spectrogram, optional
xue@1 120
xue@1 121 //internal buffers (optional) for FFT
Chris@5 122 WindowType fwt; ///< type of window
Chris@5 123 int fWid; ///< size of window
Chris@5 124 int* fhbi; ///< half-size bit-inversed integer table
Chris@5 125 double fwdp; ///< additional parameter specifying window type
Chris@5 126 double* fwin; ///< internal window
Chris@5 127 cdouble* fw; ///< FFT twiddle factors
Chris@5 128 cdouble* fx; ///< FFT data buffer
xue@1 129
xue@1 130 //x and ph create-time switch
Chris@5 131 bool usex; ///< set at create time if complex spectrogram is required
Chris@5 132 bool useph; ///< set at create time if phase spectrogram is required
xue@1 133
xue@1 134 //internal methods
xue@1 135 void AddBuffer();
xue@1 136 void AddBuffer(int AddFrCount);
xue@1 137 void __fastcall CalculateSpectrum(int fr);
xue@1 138
xue@1 139 public:
xue@1 140 //if specified, Parent is responsible to supply FFT buffers through GetFFTBuffers (optional)
Chris@5 141 int Id; ///< an identifier given at create time, used as argument for calling GetFFTBuffers()
Chris@5 142 void* Parent; ///< a pointer used as argument for calling GetFFTBuffers()
Chris@5 143 GetBuf GetFFTBuffers; ///< if specified, this supplies FFT buffers
xue@1 144
xue@1 145 //index and validity arrays associated with internal storage
Chris@5 146 int Capacity; ///< size of $Frame[] and &Valid[], usually set to the total number of frames of the data
Chris@5 147 int* Frame; ///< indices to individual frames in internal storage
Chris@5 148 int* Valid; ///< validity tags to individual frames in internal storage
xue@1 149
Chris@5 150 WindowType WinType; ///< window type for computing spectrogram
Chris@5 151 double WinParam; ///< additional parameter specifying certain window types (Gaussian, Kaiser, etc.)
xue@1 152
Chris@5 153 void* Data; ///< pointer to waveform audio
Chris@5 154 int DataLength; ///< length of waveform audio, in samples
Chris@5 155 int BytesPerSample; ///< bytes per sample of waveform audio
xue@1 156
Chris@5 157 int Offst; ///< frame offset
Chris@5 158 int Wid; ///< frame size, the same as window size
xue@1 159
xue@1 160 __fastcall TQuickSpectrogram(void* AParent, int AnId, bool Ausex, bool Auseph, GetBuf G);
xue@1 161 __fastcall ~TQuickSpectrogram();
xue@1 162
Chris@5 163 QSPEC_FORMAT* __fastcall A(int fr); ///< accesses amplitude spectrogram at frame fr
Chris@5 164 void FreeBuffers(); ///< discards all computed frames and free memory
Chris@5 165 int Invalidate(int From, int To); ///< discards computed frames
Chris@5 166 QSPEC_FORMAT* __fastcall Ph(int fr); ///< accesses phase spectrogram at frame fr
xue@11 167 void SetFrCapacity(int AnFrCapacity);
Chris@5 168 cmplx<QSPEC_FORMAT>* __fastcall Spec(int fr); ///< accesses complex spectrogram at frame fr
xue@1 169 };
xue@1 170 #endif