libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #ifndef cmProc_h
  4. #define cmProc_h
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. //( { file_desc:"Processor Library 1" kw:[proclib]}
  9. //)
  10. //( { label:cmAudioFileRd file_desc:"Audio file reader based on cmAudioFile" kw:[proc] }
  11. typedef struct
  12. {
  13. cmObj obj;
  14. cmAudioFileH_t h; // audio file handle
  15. cmAudioFileInfo_t info; // audio file info record
  16. unsigned chIdx;
  17. cmSample_t* outV; // buffer of audio from last read
  18. unsigned outN; // length of outV in samples
  19. cmChar_t* fn; // name of audio file
  20. unsigned lastReadFrmCnt; // count of samples actually read on last read
  21. bool eofFl;
  22. unsigned begFrmIdx;
  23. unsigned endFrmIdx;
  24. unsigned curFrmIdx; // frame index of the next frame to read
  25. cmMtxFile* mfp;
  26. } cmAudioFileRd;
  27. // set p to NULL to dynamically allocate the object
  28. // fn and chIdx are optional - set fn to NULL to allocate the reader without opening a file.
  29. // If fn is valid then chIdx must also be valid.
  30. // Set 'endSmpIdx' to cmInvalidIdx to return the entire signal in cmAudioFileRdRead().
  31. // Set 'endSmpIdx' to 0 to return all samples between 0 and the end of the file.
  32. cmAudioFileRd* cmAudioFileRdAlloc( cmCtx* c, cmAudioFileRd* p, unsigned procSmpCnt, const char* fn, unsigned chIdx, unsigned begSmpIdx, unsigned endSmpIdx );
  33. cmRC_t cmAudioFileRdFree( cmAudioFileRd** p );
  34. cmRC_t cmAudioFileRdOpen( cmAudioFileRd* p, unsigned procSmpCnt, const cmChar_t* fn, unsigned chIdx, unsigned begSmpIdx, unsigned endSmpIdx );
  35. cmRC_t cmAudioFileRdClose( cmAudioFileRd* p );
  36. // Returns cmEofRC if the end of file is encountered.
  37. cmRC_t cmAudioFileRdRead( cmAudioFileRd* p );
  38. cmRC_t cmAudioFileRdSeek( cmAudioFileRd* p, unsigned frmIdx );
  39. // Find the overall minimum, maximum, and mean sample values without changing the current file location.
  40. cmRC_t cmAudioFileRdMinMaxMean( cmAudioFileRd* p, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr );
  41. //)
  42. //( { label:cmShiftBuf file_desc:"Audio shift buffer processor" kw:[proc] }
  43. //------------------------------------------------------------------------------------------------------------
  44. // The buffer is intended to synchronize sample block rates between processes and to provide an overlapped
  45. // input buffer.
  46. typedef struct cmShiftBuf_str
  47. {
  48. cmObj obj;
  49. unsigned bufSmpCnt; // wndSmpCnt + hopSmpCnt
  50. cmSample_t* bufV; // bufV[bufSmpCnt] all other pointers use this memory
  51. cmSample_t* outV; // output window outV[ outN ]
  52. unsigned outN; // outN == wndSmpCnt
  53. unsigned procSmpCnt; // input sample count
  54. unsigned wndSmpCnt; // output sample count
  55. unsigned hopSmpCnt; // count of samples to shift the buffer by on each call to cmShiftExec()
  56. cmSample_t* inPtr; // ptr to location in outV[] to recv next sample
  57. bool fl; // reflects the last value returned by cmShiftBufExec().
  58. } cmShiftBuf;
  59. // Set p to NULL to dynamically allocate the object. hopSmpCnt must be <= wndSmpCnt.
  60. cmShiftBuf* cmShiftBufAlloc( cmCtx* c, cmShiftBuf* p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt );
  61. cmRC_t cmShiftBufFree( cmShiftBuf** p );
  62. cmRC_t cmShiftBufInit( cmShiftBuf* p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt );
  63. cmRC_t cmShiftBufFinal( cmShiftBuf* p );
  64. // Returns true if a new hop is ready to be read otherwise returns false.
  65. // In general cmShiftBufExec() should be called in a loop until it returns false.
  66. // Note that 'sp' and 'sn' are ignored except for the first call after the function returns false.
  67. // This means that when called in a loop 'sp' and 'sn' are only used on the first time through the loop.
  68. // When procSmpCnt is less than hopSmpCnt the loop will only execute when at least wndSmpCnt
  69. // new samples have been buffered.
  70. // When procSmpCnt is greater than hopSmpCnt the loop will execute multiple times until less
  71. // than wndSmpCnt new samples are available.
  72. // Note that 'sn' must always be less than or equal to procSmpCnt.
  73. //
  74. // Example:
  75. // while( fill(sp,sn) ) // fill sp[] with sn samples
  76. // {
  77. // // shift by hopSmpCnt samples on all passes - insert new samples on first pass
  78. // while( cmShiftBufExec(p,sp,sn) )
  79. // proc(p->outV,p->outN); // process p->outV[wndSmpCnt]
  80. // }
  81. bool cmShiftBufExec( cmShiftBuf* p, const cmSample_t* sp, unsigned sn );
  82. void cmShiftBufTest( cmCtx* c );
  83. //------------------------------------------------------------------------------------------------------------
  84. //)
  85. //( { label:cmWindowFunc file_desc:"Fourier Transform window function generator." kw:[proc]}
  86. enum
  87. {
  88. kInvalidWndId = 0x000,
  89. kHannWndId = 0x001,
  90. kHammingWndId = 0x002,
  91. kTriangleWndId = 0x004,
  92. kKaiserWndId = 0x008,
  93. kHannMatlabWndId= 0x010,
  94. kUnityWndId = 0x020,
  95. kWndIdMask = 0x0ff,
  96. kNormByLengthWndFl = 0x100, // mult by 1/wndSmpCnt
  97. kNormBySumWndFl = 0x200, // mult by wndSmpCnt/sum(wndV)
  98. kSlRejIsBetaWndFl = 0x400 // kaiserSideLobeRejectDb param. is actually kaiser beta arg.
  99. };
  100. typedef struct
  101. {
  102. cmObj obj;
  103. unsigned wndId;
  104. unsigned flags;
  105. cmSample_t* wndV;
  106. cmSample_t* outV;
  107. unsigned outN; // same as wndSmpCnt
  108. double kslRejectDb;
  109. cmMtxFile* mfp;
  110. } cmWndFunc;
  111. // Set p to NULL to dynamically allocate the object
  112. // if wndId is set to a valid value this function will internally call cmWndFuncInit()
  113. cmWndFunc* cmWndFuncAlloc( cmCtx* c, cmWndFunc* p, unsigned wndId, unsigned wndSmpCnt, double kaierSideLobeRejectDb );
  114. cmRC_t cmWndFuncFree( cmWndFunc** pp );
  115. cmRC_t cmWndFuncInit( cmWndFunc* p, unsigned wndId, unsigned wndSmpCnt, double kaiserSideLobeRejectDb );
  116. cmRC_t cmWndFuncFinal( cmWndFunc* p );
  117. cmRC_t cmWndFuncExec( cmWndFunc* p, const cmSample_t* sp, unsigned sn );
  118. void cmWndFuncTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  119. //------------------------------------------------------------------------------------------------------------
  120. //)
  121. //( { label:cmSpecDelay file_desc:"Spectral frame delay. A circular buffer for spectral (or other fixed length) vectors." kw:[proc]}
  122. typedef struct
  123. {
  124. cmObj obj;
  125. cmSample_t* bufPtr;
  126. unsigned maxDelayCnt;
  127. int inIdx;
  128. unsigned outN; // outN == binCnt
  129. } cmSpecDelay;
  130. // Set p to NULL to dynamically allocate the object.
  131. // Allocate a spectral frame delay capable of delaying for 'maxDelayCnt' hops and
  132. // where each vector contains 'binCnt' elements.
  133. cmSpecDelay* cmSpecDelayAlloc( cmCtx* c, cmSpecDelay* p, unsigned maxDelayCnt, unsigned binCnt );
  134. cmRC_t cmSpecDelayFree( cmSpecDelay** p );
  135. cmRC_t cmSpecDelayInit( cmSpecDelay* p, unsigned maxDelayCnt, unsigned binCnt );
  136. cmRC_t cmSpecDelayFinal(cmSpecDelay* p );
  137. // Give an input vector to the delay. 'sn' must <= binCnt
  138. cmRC_t cmSpecDelayExec( cmSpecDelay* p, const cmSample_t* sp, unsigned sn );
  139. // Get a pointer to a delayed vector. 'delayCnt' indicates the length of the delay in hops.
  140. // (e.g. 1 is the previous hop, 2 is two hops previous, ... )
  141. const cmSample_t* cmSpecDelayOutPtr(cmSpecDelay* p, unsigned delayCnt );
  142. //------------------------------------------------------------------------------------------------------------
  143. //)
  144. //( { label:cmFilter file_desc:"General purpose, LTI, Octave compatible, filter." kw:[proc] }
  145. typedef struct cmFilter_str
  146. {
  147. cmObj obj;
  148. cmReal_t* a; // feedback coeff's
  149. int an; // count of fb coeff's
  150. cmReal_t* b; // feedforward coeff's
  151. int bn; // count of ff coeffs'
  152. cmReal_t* d; // delay
  153. int di; //
  154. int cn; // length of delay
  155. cmReal_t b0; // 1st feedforward coeff
  156. cmSample_t* outSmpV; // signal output vector
  157. cmReal_t* outRealV;
  158. unsigned outN; // length of outV (procSmpCnt)
  159. } cmFilter;
  160. // d[dn] is the initial value of the delay line where dn = max(an,bn)-1.
  161. // Set d to NULL to intialize the delays to 0.
  162. cmFilter* cmFilterAlloc( cmCtx* c, cmFilter* p, const cmReal_t* b, unsigned bn, const cmReal_t* a, unsigned an, unsigned procSmpCnt, const cmReal_t* d );
  163. cmFilter* cmFilterAllocEllip( cmCtx* c, cmFilter* p, cmReal_t srate, cmReal_t passHz, cmReal_t stopHz, cmReal_t passDb, cmReal_t stopDb, unsigned procSmpCnt, const cmReal_t* d );
  164. cmRC_t cmFilterFree( cmFilter** pp );
  165. cmRC_t cmFilterInit( cmFilter* p, const cmReal_t* b, unsigned bn, const cmReal_t* a, unsigned an, unsigned procSmpCnt, const cmReal_t* d );
  166. cmRC_t cmFilterInitEllip( cmFilter* p, cmReal_t srate, cmReal_t passHz, cmReal_t stopHz, cmReal_t passDb, cmReal_t stopDb, unsigned procSmpCnt, const cmReal_t* d );
  167. cmRC_t cmFilterFinal( cmFilter* p );
  168. // If y==NULL or yn==0 then the output is sent to p->outV[p->outN].
  169. // This function can safely filter a signal in plcme therefore it is allowable for x[] and y[] to refer to the same memory.
  170. // If x[] overlaps y[] then y must be <= x.
  171. cmRC_t cmFilterExecS( cmFilter* p, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn );
  172. cmRC_t cmFilterExecR( cmFilter* p, const cmReal_t* x, unsigned xn, cmReal_t* y, unsigned yn );
  173. cmRC_t cmFilterSignal( cmCtx* c, const cmReal_t b[], unsigned bn, const cmReal_t a[], unsigned an, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn );
  174. // Perform forward-reverse filtering.
  175. cmRC_t cmFilterFilterS(cmCtx* c, const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn );
  176. cmRC_t cmFilterFilterR(cmCtx* c, const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const cmReal_t* x, unsigned xn, cmReal_t* y, unsigned yn );
  177. void cmFilterTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  178. void cmFilterFilterTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  179. //------------------------------------------------------------------------------------------------------------
  180. //)
  181. //( { label:cmComplexDetect file_desc:"Complex domain onset detection function." kw:[proc] }
  182. typedef struct
  183. {
  184. cmObj obj;
  185. cmSpecDelay phsDelay;
  186. cmSpecDelay magDelay;
  187. unsigned binCnt;
  188. cmSample_t out;
  189. //cmMtxFile* mfp;
  190. //unsigned cdfSpRegId;
  191. } cmComplexDetect;
  192. // Set p to NULL to dynamically allocate the object.
  193. cmComplexDetect* cmComplexDetectAlloc(cmCtx* c, cmComplexDetect* p, unsigned binCnt );
  194. cmRC_t cmComplexDetectFree( cmComplexDetect** pp);
  195. cmRC_t cmComplexDetectInit( cmComplexDetect* p, unsigned binCnt );
  196. cmRC_t cmComplexDetectFinal(cmComplexDetect* p);
  197. cmRC_t cmComplexDetectExec( cmComplexDetect* p, const cmSample_t* magV, const cmSample_t* phsV, unsigned binCnt );
  198. //------------------------------------------------------------------------------------------------------------
  199. //)
  200. //( { label:cmComplexOnset file_desc:"Complex onset detection function" kw:[proc]}
  201. typedef struct
  202. {
  203. cmObj obj;
  204. double threshold;
  205. unsigned medSmpCnt;
  206. unsigned frmCnt; // expected number of frames to store
  207. unsigned dfi;
  208. cmSample_t* df;
  209. cmSample_t* fdf;
  210. cmSample_t onrate;
  211. //cmMtxFile* mfp;
  212. } cmComplexOnset;
  213. cmComplexOnset* cmComplexOnsetAlloc( cmCtx* c, cmComplexOnset* p, unsigned procSmpCnt, double srate, unsigned medFiltWndSmpCnt, double threshold, unsigned frameCnt );
  214. cmRC_t cmComplexOnsetFree( cmComplexOnset** pp);
  215. cmRC_t cmComplexOnsetInit( cmComplexOnset* p, unsigned procSmpCnt, double srate, unsigned medFiltWndSmpCnt, double threshold, unsigned frameCnt );
  216. cmRC_t cmComplexOnsetFinal( cmComplexOnset* p);
  217. cmRC_t cmComplexOnsetExec( cmComplexOnset* p, cmSample_t cdf );
  218. cmRC_t cmComplexOnsetCalc( cmComplexOnset* p );
  219. //------------------------------------------------------------------------------------------------------------
  220. //)
  221. //( { label:cmMfcc file_desc:"Mel Frequency Cepstral Coefficient (MFCC) measurement function." kw:[proc] }
  222. typedef struct
  223. {
  224. cmObj obj;
  225. unsigned melBandCnt;
  226. unsigned dctCoeffCnt;
  227. unsigned binCnt;
  228. cmReal_t* melM;
  229. cmReal_t* dctM;
  230. cmReal_t* outV;
  231. unsigned outN; // outN == dctCoeffCnt
  232. cmMtxFile* mfp;
  233. unsigned mfccSpRegId; // cmStatsProc regId
  234. } cmMfcc;
  235. cmMfcc* cmMfccAlloc( cmCtx* c, cmMfcc* p, double srate, unsigned melBandCnt, unsigned dctCoeffCnt, unsigned binCnt );
  236. cmRC_t cmMfccFree( cmMfcc** pp );
  237. cmRC_t cmMfccInit( cmMfcc* p, double srate, unsigned melBandCnt, unsigned dctCoeffCnt, unsigned binCnt );
  238. cmRC_t cmMfccFinal( cmMfcc* p );
  239. cmRC_t cmMfccExecPower( cmMfcc* p, const cmReal_t* magPowV, unsigned binCnt );
  240. cmRC_t cmMfccExecAmplitude( cmMfcc* p, const cmReal_t* magAmpV, unsigned binCnt );
  241. void cmMfccTest();
  242. //------------------------------------------------------------------------------------------------------------
  243. //)
  244. //( { label:cmSones file_desc:"Sones measurement function." kw:[proc] }
  245. typedef struct
  246. {
  247. cmObj obj;
  248. cmReal_t* ttmV; // Terhardt outer ear filter
  249. cmReal_t* sfM; // Shroeder spreading function
  250. unsigned* barkIdxV; // Bark to bin map
  251. unsigned* barkCntV; //
  252. cmReal_t* outV; // specific loudness in sones
  253. unsigned outN; // outN == barkBandCnt;
  254. cmReal_t overallLoudness; // overall loudness in sones
  255. unsigned binCnt; // expected length of incoming power spectrum
  256. unsigned barkBandCnt; // count of bark bands
  257. unsigned flags; //
  258. cmMtxFile* mfp;
  259. unsigned sonesSpRegId;
  260. unsigned loudSpRegId;
  261. } cmSones;
  262. enum { kDontUseEqlLoudSonesFl=0x00, kUseEqlLoudSonesFl=0x01 };
  263. cmSones* cmSonesAlloc( cmCtx* c, cmSones* p, double srate, unsigned barkBandCnt, unsigned binCnt, unsigned flags );
  264. cmRC_t cmSonesFree( cmSones** pp );
  265. cmRC_t cmSonesInit( cmSones* p, double srate, unsigned barkBandCnt, unsigned binCnt, unsigned flags );
  266. cmRC_t cmSonesFinal( cmSones* p );
  267. cmRC_t cmSonesExec( cmSones* p, const cmReal_t* magPowV, unsigned binCnt );
  268. void cmSonesTest();
  269. //------------------------------------------------------------------------------------------------------------
  270. //)
  271. //( { label: cmAudioOffsetScale file_desc:"Audio signal pre-processing normalizer." kw:[proc] }
  272. typedef struct
  273. {
  274. cmObj obj;
  275. unsigned cBufCnt;
  276. unsigned cBufCurCnt;
  277. unsigned cBufIdx;
  278. double cBufSum;
  279. unsigned cCntSum;
  280. cmReal_t* cBufPtr;
  281. unsigned* cCntPtr;
  282. cmSample_t offset;
  283. double dBref;
  284. cmSample_t* outV;
  285. unsigned outN; // (outN == procSmpCnt)
  286. unsigned flags;
  287. cmMtxFile* mfp;
  288. } cmAudioOffsetScale;
  289. // This processor adds an offset to an audio signal and scales into dB (SPL) using one of two techniques
  290. // 1) Measures the effective sound pressure (via RMS) and then scales the signal to the reference dB (SPL)
  291. // In this case dBref is commonly set to 70. See Timony, 2004, Implementing Loudness Models in Matlab.
  292. //
  293. // 2) treats the dBref as the maximum dB (SPL) and scales the signal by this amount without regard
  294. // measured signal level. In this case dBref is commonly set to 96 (max. dB (SPL) value for 16 bits)
  295. // and rmsWndSecs is ignored.
  296. //
  297. // Note that setting rmsWndSecs to zero has the effect of using procSmpCnt as the window length.
  298. enum { kNoAudioScaleFl=0x01, kRmsAudioScaleFl=0x02, kFixedAudioScaleFl=0x04 };
  299. cmAudioOffsetScale* cmAudioOffsetScaleAlloc( cmCtx* c, cmAudioOffsetScale* p, unsigned procSmpCnt, double srate, cmSample_t offset, double rmsWndSecs, double dBref, unsigned flags );
  300. cmRC_t cmAudioOffsetScaleFree( cmAudioOffsetScale** pp );
  301. cmRC_t cmAudioOffsetScaleInit( cmAudioOffsetScale* p, unsigned procSmpCnt, double srate, cmSample_t offset, double rmsWndSecs, double dBref, unsigned flags );
  302. cmRC_t cmAudioOffsetScaleFinal( cmAudioOffsetScale* p );
  303. cmRC_t cmAudioOffsetScaleExec( cmAudioOffsetScale* p, const cmSample_t* sp, unsigned sn );
  304. //------------------------------------------------------------------------------------------------------------
  305. //)
  306. //( { label:cmSpecMeas file_desc:"Measure a signals RMS, High-Frequency Content, Spectral Centroid, and Spectral Spread." kw:[proc]}
  307. typedef struct
  308. {
  309. cmObj obj;
  310. cmReal_t* rmsV;
  311. cmReal_t* hfcV;
  312. cmReal_t* scnV;
  313. cmReal_t rmsSum;
  314. cmReal_t hfcSum;
  315. cmReal_t scnSum;
  316. cmReal_t ssSum;
  317. cmReal_t rms; // RMS output
  318. cmReal_t hfc; // high-frequency content output
  319. cmReal_t sc; // spectral centroid output
  320. cmReal_t ss; // spectral spread output
  321. unsigned binCnt;
  322. unsigned flags;
  323. unsigned wndFrmCnt;
  324. unsigned frameIdx;
  325. unsigned frameCnt;
  326. double binHz;
  327. cmMtxFile* mfp;
  328. unsigned rmsSpRegId;
  329. unsigned hfcSpRegId;
  330. unsigned scSpRegId;
  331. unsigned ssSpRegId;
  332. } cmSpecMeas;
  333. // Set wndFrmCnt to the number of spectral frames to take the measurement over.
  334. // Setting wndFrmCnt to 1 has the effect of calculating the value on the current frame only.
  335. // Set flags = kWholeSigSpecMeasFl to ignore wndFrmCnt and calculate the result on the entire signal.
  336. // In effect this treats the entire signal as the length of the measurement window.
  337. enum { kWholeSigSpecMeasFl=0x00, kUseWndSpecMeasFl=0x01 };
  338. cmSpecMeas* cmSpecMeasAlloc( cmCtx* c, cmSpecMeas* p, double srate, unsigned binCnt, unsigned wndFrmCnt, unsigned flags );
  339. cmRC_t cmSpecMeasFree( cmSpecMeas** pp );
  340. cmRC_t cmSpecMeasInit( cmSpecMeas* p, double srate, unsigned binCnt, unsigned wndFrmCnt, unsigned flags );
  341. cmRC_t cmSpecMeasFinal( cmSpecMeas* p );
  342. cmRC_t cmSpecMeasExec( cmSpecMeas* p, const cmReal_t* magPowV, unsigned binCnt );
  343. //------------------------------------------------------------------------------------------------------------
  344. //)
  345. //( { label:cmSigMeas file_desc:"Measure a time domain signals zero crossing rate." kw:[proc]}
  346. typedef struct
  347. {
  348. cmObj obj;
  349. cmShiftBuf* sbp; // shift buffer used internally if procSmpCnt < measSmpCnt
  350. cmShiftBuf shiftBuf;
  351. double srate; //
  352. cmReal_t zcr; // zero crossing rate per second
  353. cmSample_t zcrDelay; // used internally by zero crossing count algorithm
  354. unsigned measSmpCnt; // length of measurement window in samples
  355. unsigned procSmpCnt; // expected number of samples per call to exec
  356. unsigned zcrSpRegId;
  357. cmMtxFile* mfp;
  358. } cmSigMeas;
  359. // procSmpCnt must be <= measSmpCnt
  360. cmSigMeas* cmSigMeasAlloc( cmCtx* c, cmSigMeas* p, double srate, unsigned procSmpCnt, unsigned measSmpCnt );
  361. cmRC_t cmSigMeasFree( cmSigMeas** pp );
  362. cmRC_t cmSigMeasInit( cmSigMeas* p, double srate, unsigned procSmpCnt, unsigned measSmpCnt );
  363. cmRC_t cmSigMeasFinal( cmSigMeas* p );
  364. cmRC_t cmSigMeasExec( cmSigMeas* p, const cmSample_t* sigV, unsigned smpCnt );
  365. //------------------------------------------------------------------------------------------------------------
  366. //)
  367. //( { label:cmSRC file_desc:"Sample rate converter" kw:[proc] }
  368. typedef struct
  369. {
  370. cmObj obj;
  371. cmFilter filt;
  372. cmSample_t* outV;
  373. unsigned outN;
  374. unsigned upFact;
  375. unsigned dnFact;
  376. unsigned upi;
  377. unsigned dni;
  378. cmMtxFile* mfp;
  379. } cmSRC;
  380. // The srate paramater is the sample rate of the source signal provided via cmSRCExec()
  381. cmSRC* cmSRCAlloc( cmCtx* c, cmSRC* p, double srate, unsigned procSmpCnt, unsigned upFact, unsigned dnFact );
  382. cmRC_t cmSRCFree( cmSRC** pp );
  383. cmRC_t cmSRCInit( cmSRC* p, double srate, unsigned procSmpCnt, unsigned upFact, unsigned dnFact );
  384. cmRC_t cmSRCFinal( cmSRC* p );
  385. cmRC_t cmSRCExec( cmSRC* p, const cmSample_t* sp, unsigned sn );
  386. void cmSRCTest();
  387. //------------------------------------------------------------------------------------------------------------
  388. //)
  389. //( { label:cmConstQ file_desc:"Contant-Q transform." kw:[proc] }
  390. typedef struct
  391. {
  392. cmObj obj;
  393. cmComplexR_t* fiV;
  394. cmComplexR_t* foV;
  395. cmComplexR_t* skM; // skM[ wndSmpCnt, constQBinCnt ]
  396. unsigned* skBegV; // skBegV[ constQBinCnt ] indexes used to decrease the size of the mtx mult in cmConstQExex()
  397. unsigned* skEndV; // skEndV[ constQBinCnt ]
  398. unsigned wndSmpCnt; // window length of the complex FFT required to feed this transform
  399. unsigned constQBinCnt; // count of bins in the const Q output
  400. unsigned binsPerOctave; //
  401. cmComplexR_t* outV; // outV[ constQBinCnt ]
  402. cmReal_t* magV; // outV[ constQBinCnt ]
  403. cmMtxFile* mfp;
  404. } cmConstQ;
  405. cmConstQ* cmConstQAlloc( cmCtx* c, cmConstQ* p, double srate, unsigned minMidiPitch, unsigned maxMidiPitch, unsigned binsPerOctave, double thresh );
  406. cmRC_t cmConstQFree( cmConstQ** pp );
  407. cmRC_t cmConstQInit( cmConstQ* p, double srate, unsigned minMidiPitch, unsigned maxMidiPitch, unsigned binsPerOctave, double thresh );
  408. cmRC_t cmConstQFinal( cmConstQ* p );
  409. cmRC_t cmConstQExec( cmConstQ* p, const cmComplexR_t* ftV, unsigned binCnt );
  410. //------------------------------------------------------------------------------------------------------------
  411. //)
  412. //( { label:cmTuneHpcp file_desc:"Generate a tuned chromagram." kw:[proc]}
  413. typedef struct
  414. {
  415. cmObj obj;
  416. cmReal_t* hpcpM; // hpcpM[ frameCnt , binsPerOctave ] - stored hpcp
  417. cmReal_t* fhpcpM;// fhpcpM[ binsPerOctave, frameCnt ] - filtered hpcp (note transposed relative to hpcpA)
  418. unsigned* histV; // histM[ binsPerOctave/12 ]
  419. cmReal_t* outM; // outM[ 12, frameCnt ];
  420. unsigned histN; // binsPerOctave/12
  421. unsigned binsPerOctave; // const-q bins representing 1 octave
  422. unsigned constQBinCnt; // total count of const-q bins
  423. unsigned frameCnt; // expected count of hpcp vectors to store.
  424. unsigned frameIdx; // next column in hpcpM[] to receive input
  425. unsigned cqMinMidiPitch;
  426. unsigned medFiltOrder;
  427. cmReal_t* meanV; // meanV[12]
  428. cmReal_t* varV; // varV[12]
  429. cmMtxFile* mf0p; // debug files
  430. cmMtxFile* mf1p;
  431. cmMtxFile* mf2p;
  432. } cmHpcp;
  433. cmHpcp* cmTunedHpcpAlloc( cmCtx* c, cmHpcp* p, unsigned binsPerOctave, unsigned constQBinCnt, unsigned cqMinMidiPitch, unsigned frameCnt, unsigned medFiltOrder );
  434. cmRC_t cmTunedHpcpFree( cmHpcp** pp );
  435. cmRC_t cmTunedHpcpInit( cmHpcp* p, unsigned binsPerOctave, unsigned constQBinCnt, unsigned cqMinMidiPitch, unsigned frameCnt, unsigned medFiltOrder );
  436. cmRC_t cmTunedHpcpFinal( cmHpcp* p );
  437. cmRC_t cmTunedHpcpExec( cmHpcp* p, const cmComplexR_t* constQBinPtr, unsigned constQBinCnt );
  438. cmRC_t cmTunedHpcpTuneAndFilter( cmHpcp* p);
  439. //------------------------------------------------------------------------------------------------------------
  440. //)
  441. //( { label:cmBeatHist file_desc:"Generate a beat candidate histogram." kw:[proc]}
  442. struct cmFftRR_str;
  443. struct cmIFftRR_str;
  444. typedef struct
  445. {
  446. cmObj obj;
  447. struct cmFftRR_str* fft;
  448. struct cmIFftRR_str* ifft;
  449. unsigned frmCnt; // 512 length of df
  450. unsigned maxLagCnt; // 128 length of longest CMF lag
  451. unsigned histBinCnt; // 15 count of histogram elements and rows in H[]
  452. unsigned hColCnt; // 128 count of columns in H[]
  453. cmReal_t* m; // m[ frmCnt x maxLagCnt ]
  454. cmReal_t* H; // histogram transformation mtx
  455. cmReal_t* df; // df[ frmCnt ] onset detection function
  456. cmReal_t* fdf; // fdf[ frmCnt ] filtered onset detection function
  457. unsigned dfi; // index next df[] location to receive an incoming value
  458. cmReal_t* histV; // histV[ histBinCnt ] histogram output
  459. cmMtxFile* mfp;
  460. } cmBeatHist;
  461. cmBeatHist* cmBeatHistAlloc( cmCtx* c, cmBeatHist* p, unsigned frmCnt );
  462. cmRC_t cmBeatHistFree( cmBeatHist** pp );
  463. cmRC_t cmBeatHistInit( cmBeatHist* p, unsigned frmCnt );
  464. cmRC_t cmBeatHistFinal( cmBeatHist* p );
  465. cmRC_t cmBeatHistExec( cmBeatHist* p, cmSample_t df );
  466. cmRC_t cmBeatHistCalc( cmBeatHist* p );
  467. //------------------------------------------------------------------------------------------------------------
  468. //)
  469. //( { label:cmGmm file_desc"Gaussian Mixture Model containing N Gaussian PDF's each of dimension D." kw:[proc model]}
  470. typedef struct
  471. {
  472. cmObj obj;
  473. unsigned K; // count of components
  474. unsigned D; // dimensionality of each component
  475. cmReal_t* gV; // gM[ K ] mixture gain vector
  476. cmReal_t* uM; // uM[ D x K ] component mean column vectors
  477. cmReal_t* sMM; // sMM[D x D x K ] component covariance matrices - each column is a DxD matrix
  478. cmReal_t* isMM; // isMM[D x D x K] inverted covar matrices
  479. cmReal_t* uMM; // uMM[ D x D x K] upper triangle factor of chol(sMM)
  480. cmReal_t* logDetV;// detV[ K ] determinent of covar matrices
  481. cmReal_t* t; // t[ D x D ]scratch matrix used for training
  482. unsigned uflags; // user defined flags
  483. } cmGmm_t;
  484. enum { cmMdgNoFlags=0x0, cmGmmDiagFl=0x01, cmGmmSkipKmeansFl=0x02 };
  485. cmGmm_t* cmGmmAlloc( cmCtx* c, cmGmm_t* p, unsigned N, unsigned D, const cmReal_t* gV, const cmReal_t* uM, const cmReal_t* sMM, unsigned flags );
  486. cmRC_t cmGmmFree( cmGmm_t** pp );
  487. cmRC_t cmGmmInit( cmGmm_t* p, unsigned N, unsigned D, const cmReal_t* gV, const cmReal_t* uM, const cmReal_t* sMM, unsigned flags );
  488. cmRC_t cmGmmFinal( cmGmm_t* p );
  489. // Estimate the parameters of the GMM using the training data in xM[p->D,xN].
  490. // *iterCntPtr on input is the number of iterations with no change in class assignment to signal convergence.
  491. // *iterCntPtr on output is the total number of interations required to converge.
  492. cmRC_t cmGmmTrain( cmGmm_t* p, const cmReal_t* xM, unsigned xN, unsigned* iterCntPtr );
  493. // Return a pointer to the feature vector at frmIdx containing D elements.
  494. typedef const cmReal_t* (*cmGmmReadFunc_t)( void* userPtr, unsigned colIdx );
  495. // Same as cmGmmTrain() but uses a function to access the feature vector.
  496. // The optional matrix uM[D,K] contains the initial mean values or NULL if not used.
  497. // The optional flag array roFlV[K] is used to indicate read-only components and is only used
  498. // when the uM[] arg. is non-NULL. Set roFlV[i] to true to indicate that the mean value supplied by
  499. // the uM[] arg. should not be alterned by the training process.
  500. // If 'maxIterCnt' is positive then it is the maximum number of iterations the training process will make
  501. // otherwise it is ignored.
  502. cmRC_t cmGmmTrain2( cmGmm_t* p, cmGmmReadFunc_t readFunc, void* userFuncPtr, unsigned xN, unsigned* iterCntPtr, const cmReal_t* uM, const bool* roFlV, int maxIterCnt );
  503. // Generate data yN data points from the GMM and store the result in yM[p->D,yN].
  504. cmRC_t cmGmmGenerate( cmGmm_t* p, cmReal_t* yM, unsigned yN );
  505. // Evaluate the probability of each column of xM[p->D,xN] and return the result in y[xN].
  506. // If yM[xN,K] is non-NULL then the individual component prob. values are returned
  507. cmRC_t cmGmmEval( cmGmm_t* p, const cmReal_t* xM, unsigned xN, cmReal_t* yV, cmReal_t* yM);
  508. // Same as cmGmmEval() but uses a a function to access each data vector
  509. cmRC_t cmGmmEval2( cmGmm_t* p, cmGmmReadFunc_t readFunc, void* userFuncPtr, unsigned xN, cmReal_t* yV, cmReal_t* yM);
  510. // Evaluate each component for a single data point
  511. // xV[D] - observed data point
  512. // yV[K] - output contains the evaluation for each component
  513. cmRC_t cmGmmEval3( cmGmm_t* p, const cmReal_t* xV, cmReal_t* yV );
  514. void cmGmmPrint( cmGmm_t* p, bool detailsFl );
  515. void cmGmmTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  516. //------------------------------------------------------------------------------------------------------------
  517. //)
  518. //( { label:cmChmm file_desc:"Continuous Hidden Markov Model" kw:[proc model]}
  519. typedef struct
  520. {
  521. cmObj obj;
  522. unsigned N; // count of states
  523. unsigned K; // count of components per mixture
  524. unsigned D; // dimensionality of the observation data
  525. cmReal_t* iV; // iV[ N ] initial state probability mtx
  526. cmReal_t* aM; // aM[ N x N] transition probability mtx
  527. cmGmm_t** bV; // bV[ N ] observation probability mtx (array of pointers to GMM's)
  528. cmReal_t* bM; // bM[ N,T] state-observation probability matrix
  529. cmMtxFile* mfp;
  530. } cmChmm_t;
  531. // Continuous HMM consisting of stateN states where the observations
  532. // associated with each state are generated by a Gaussian mixture PDF.
  533. // stateN - count of states
  534. // mixN - count of components in the mixtures
  535. // dimN - dimensionality of the observation data
  536. cmChmm_t* cmChmmAlloc( cmCtx* c, cmChmm_t* p, unsigned stateN, unsigned mixN, unsigned dimN, const cmReal_t* iV, const cmReal_t* aM );
  537. cmRC_t cmChmmFree( cmChmm_t** pp );
  538. cmRC_t cmChmmInit( cmChmm_t* p, unsigned stateN, unsigned mixN, unsigned dimN, const cmReal_t* iV, const cmReal_t* aM );
  539. cmRC_t cmChmmFinal( cmChmm_t* p );
  540. // Set the iV,aM and bV parameters to well-formed random values.
  541. cmRC_t cmChmmRandomize( cmChmm_t* p, const cmReal_t* oM, unsigned T );
  542. // Train the HMM using segmental k-means to initialize the model parameters.
  543. // threshProb is the min change in fit between the data and the model above which the procedure will continue to iterate.
  544. // maxIterCnt is the maximum number of iterations the algorithm will make without regard for threshProb.
  545. // iterCnt is the value of iterCnt used in the call cmChmmTrain() on each iteration
  546. cmRC_t cmChmmSegKMeans( cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t threshProb, unsigned maxIterCnt, unsigned iterCnt );
  547. cmRC_t cmChmmSetGmm( cmChmm_t* p, unsigned i, const cmReal_t* wV, const cmReal_t* uM, const cmReal_t* sMM, unsigned flags );
  548. // oM[D,T] - observation matrix
  549. // alphaM[N,T] - prob of being in each state and observtin oM(:,t)
  550. // logPrV[T] - (optional) record the log prob of the data given the model at each time step
  551. // Returns sum(logPrV[T])
  552. cmReal_t cmChmmForward( const cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t* alphaM, cmReal_t* logPrV );
  553. void cmChmmBackward( const cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t* betaM );
  554. // bM[N,T] the state-observation probability table is optional
  555. cmReal_t cmChmmCompare( const cmChmm_t* p0, const cmChmm_t* p1, unsigned T );
  556. // Generate a series of observations.
  557. // oM[ p->D , T ] - output matrix
  558. // sV[ T ] - optional vector to record the state used to generate the ith observation.
  559. cmRC_t cmChmmGenerate( const cmChmm_t* p, cmReal_t* oM, unsigned T, unsigned* sV );
  560. // Infer the HMM parameters (p->iV,p->aM,p->bV) from the observations oM[D,T]
  561. enum { kNoTrainMixCoeffChmmFl=0x01, kNoTrainMeanChmmFl=0x02, kNoTrainCovarChmmFl=0x04 };
  562. cmRC_t cmChmmTrain( cmChmm_t* p, const cmReal_t* oM, unsigned T, unsigned iterCnt, cmReal_t thresh, unsigned flags );
  563. // Determine the ML state sequence yV[T] given the observations oM[D,T].
  564. cmRC_t cmChmmDecode( cmChmm_t* p, const cmReal_t* oM, unsigned T, unsigned* yV );
  565. void cmChmmPrint( cmChmm_t* p );
  566. void cmChmmTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  567. //------------------------------------------------------------------------------------------------------------
  568. //)
  569. //( { label:cmChord file_desc:"HMM based chord recognizer." kw:[proc]}
  570. typedef struct
  571. {
  572. cmObj obj;
  573. cmChmm_t* h; // hmm
  574. unsigned N; // state count N=24
  575. unsigned D; // data dimension D=12
  576. unsigned S; // tonal space dim S=6
  577. unsigned T; // frames in chromaM
  578. cmReal_t* iV; // iV[N]
  579. cmReal_t* aM; // aM[N,N]
  580. cmReal_t* uM; // uM[D,N]
  581. cmReal_t* sMM; // sMM[D*D,N]
  582. cmReal_t* phiM; // phiM[S,T]
  583. cmReal_t* chromaM; // chromaM[D,T]
  584. cmReal_t* tsM; // tsM[S,T]
  585. cmReal_t* cdtsV; // cdts[1,T]
  586. cmReal_t triadSeqMode;
  587. cmReal_t triadSeqVar;
  588. cmReal_t triadIntMean;
  589. cmReal_t triadIntVar;
  590. cmReal_t* tsMeanV; // tsMeanV[S];
  591. cmReal_t* tsVarV; // tsVarV[S]
  592. cmReal_t cdtsMean;
  593. cmReal_t cdtsVar;
  594. } cmChord;
  595. cmChord* cmChordAlloc( cmCtx* c, cmChord* p, const cmReal_t* chromaM, unsigned T );
  596. cmRC_t cmChordFree( cmChord** p );
  597. cmRC_t cmChordInit( cmChord* p, const cmReal_t* chromaM, unsigned T );
  598. cmRC_t cmChordFinal( cmChord* p );
  599. void cmChordTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH );
  600. //------------------------------------------------------------------------------------------------------------
  601. //)
  602. #ifdef __cplusplus
  603. }
  604. #endif
  605. #endif