libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmFeatFile.c 73KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458
  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. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmFloatTypes.h"
  6. #include "cmComplexTypes.h"
  7. #include "cmRpt.h"
  8. #include "cmErr.h"
  9. #include "cmCtx.h"
  10. #include "cmMem.h"
  11. #include "cmMallocDebug.h"
  12. #include "cmLinkedHeap.h"
  13. #include "cmSymTbl.h"
  14. #include "cmMath.h"
  15. #include "cmFile.h"
  16. #include "cmAudioFile.h"
  17. #include "cmJson.h"
  18. #include "cmFileSys.h"
  19. #include "cmTime.h"
  20. #include "cmMidi.h"
  21. #include "cmProcObj.h"
  22. #include "cmProcTemplateMain.h"
  23. #include "cmProc.h"
  24. #include "cmProc2.h"
  25. #include "cmVectOps.h"
  26. #include "cmFrameFile.h"
  27. #include "cmFeatFile.h"
  28. #include "cmSerialize.h"
  29. #define kConstQThresh (0.0054)
  30. enum
  31. {
  32. kFrameTypeFtId = 1,
  33. kFrameStreamFtId = 1,
  34. kStatRecdVectCnt = 8 // count of vectors in cmFtSumm_t
  35. };
  36. // master control record
  37. typedef struct
  38. {
  39. cmErr_t err;
  40. cmCtx_t ctx;
  41. cmJsonH_t jsH; //
  42. cmSrH_t srH; // file header serializer
  43. cmFtAttr_t* attrArray; //
  44. unsigned attrCnt; //
  45. cmFtParam_t* paramArray; //
  46. unsigned paramCnt; //
  47. cmCtx* ctxPtr; // process context object
  48. cmAudioFileRd* afRdPtr; // audio file reader object
  49. cmPvAnl* pvocPtr; // phase vocoder object
  50. cmBfcc* bfccPtr; // BFCC generator
  51. cmMfcc* mfccPtr; // MFCC generator
  52. cmCeps* cepsPtr; // Cepstrum generator
  53. cmConstQ* constqPtr; // Const Q generator
  54. unsigned progParamIdx;
  55. unsigned progPassIdx;
  56. unsigned progSmpCnt;
  57. unsigned progSmpIdx;
  58. } _cmFt_t;
  59. // static feature values
  60. typedef struct
  61. {
  62. unsigned order; // determines the order the feature extractors are init'd and exec'd
  63. const char* label; // feature label
  64. unsigned id; // feature id
  65. unsigned ffMtxId; // cmFrameFile matrix type id
  66. unsigned ffUnitsId; // cmFrameFile data unit id
  67. unsigned srcId; // id of the source vector for this secondary feature (or kInvalidFtId if no src)
  68. bool bipolarFl; // this feature is bipolar
  69. unsigned maxCnt; // maximum feature vector element count (scalar==1 no max==0)
  70. } _cmFtLabel_t;
  71. // analysis control record - one recd per feature
  72. typedef struct _cmFtAttr_str
  73. {
  74. cmFtAttr_t* ap; // user supplied feature parameters
  75. const _cmFtLabel_t* lp; // static feature parameters
  76. cmFtSumm_t* sr; // summary record assoc'd with this feature
  77. struct _cmFtAttr_str* sp; // sourcePtr (used by secondary feats to locate primary feature)
  78. cmReal_t* v; // v[ap->cnt*2] feature vector memory used by cvp and pvp
  79. cmReal_t* cvp; // current feat vect
  80. cmReal_t* pvp; // previous feat vect
  81. } _cmFtAnl_t;
  82. // internal feature desc record
  83. typedef struct
  84. {
  85. const cmFtAttr_t* ap;
  86. const _cmFtLabel_t* lp;
  87. cmFtSumm_t* sr;
  88. } _cmFtDesc_t;
  89. // internal feature file control record - file handle record
  90. typedef struct
  91. {
  92. cmFtH_t h; // feat file library handle
  93. cmFrameFileH_t ffH; // handle for the frame file
  94. cmFtInfo_t info; // file hdr recd
  95. _cmFtDesc_t* descArray; // descArray[infoPtr->attrCnt] internal feature desc data
  96. void* hdrBuf; // memory used to hold the serialized header
  97. } _cmFtFile_t;
  98. cmFtH_t cmFtNullHandle = { NULL };
  99. cmFtFileH_t cmFtFileNullHandle = { NULL };
  100. _cmFtLabel_t _cmFtLabelArray[] =
  101. {
  102. { 0, "ampl", kAmplFtId, kMagMId, kAmplUId, kInvalidFtId, false, 0 },
  103. { 1, "db_ampl", kDbAmplFtId, kMagMId, k20DbUId, kAmplFtId, false, 0 },
  104. { 2, "pow", kPowFtId, kMagMId, kPowUId, kInvalidFtId, false, 0 },
  105. { 3, "db_pow", kDbPowFtId, kMagMId, k10DbUId, kPowFtId, false, 0 },
  106. { 4, "phase", kPhaseFtId, kPhsMId, kRadsUId, kInvalidFtId, false, 0 },
  107. { 5, "bfcc", kBfccFtId, kBfccMId, kBfccUId, kInvalidFtId, false, kDefaultBarkBandCnt },
  108. { 6, "mfcc", kMfccFtId, kMfccMId, kMfccUId, kInvalidFtId, false, kDefaultMelBandCnt },
  109. { 7, "ceps", kCepsFtId, kCepsMId, kCepsUId, kInvalidFtId, false, 0 },
  110. { 8, "constq", kConstQFtId, kConstqMId, kAmplUId, kInvalidFtId, false, 0 },
  111. { 9, "log_constq", kLogConstQFtId, kConstqMId, k20DbUId, kConstQFtId, false, 0 },
  112. { 10, "rms", kRmsFtId, kRmsMId, kAmplUId, kInvalidFtId, false, 1 },
  113. { 11, "db_rms", kDbRmsFtId, kRmsMId, k20DbUId, kRmsFtId, false, 1 },
  114. { 12, "d1_ampl", kD1AmplFtId, kMagMId, kAmplUId | kD1UFl, kAmplFtId, true, 0 },
  115. { 13, "d1_db_ampl", kD1DbAmplFtId, kMagMId, k20DbUId | kD1UFl, kDbAmplFtId, true, 0 },
  116. { 14, "d1_pow", kD1PowFtId, kMagMId, kPowUId | kD1UFl, kPowFtId, true, 0 },
  117. { 15, "d1_db_pow", kD1DbPowFtId, kMagMId, k10DbUId | kD1UFl, kDbPowFtId, true, 0 },
  118. { 16, "d1_phase", kD1PhaseFtId, kPhsMId, kRadsUId | kD1UFl, kPhaseFtId, true, 0 },
  119. { 17, "d1_bfcc", kD1BfccFtId, kBfccMId, kBfccUId | kD1UFl, kBfccFtId, true, kDefaultBarkBandCnt },
  120. { 18, "d1_mfcc", kD1MfccFtId, kMfccMId, kMfccUId | kD1UFl, kMfccFtId, true, kDefaultMelBandCnt },
  121. { 19, "d1_ceps", kD1CepsFtId, kCepsMId, kCepsUId | kD1UFl, kCepsFtId, true, 0 },
  122. { 20, "d1_constq", kD1ConstQFtId, kConstqMId, kAmplUId | kD1UFl, kConstQFtId, true, 0 },
  123. { 21, "d1_log_constq", kD1LogConstQFtId,kConstqMId, k20DbUId | kD1UFl, kLogConstQFtId, true, 0 },
  124. { 22, "d1_rms", kD1RmsFtId, kRmsMId, kAmplUId | kD1UFl, kRmsFtId, true, 1 },
  125. { 23, "d1_db_rms", kD1DbRmsFtId, kRmsMId, k20DbUId | kD1UFl, kDbRmsFtId, true, 1 },
  126. { 24, "<invalid>", kInvalidFtId, kInvalidMId,kInvalidUId, kInvalidFtId, true, 0 }
  127. };
  128. void _cmFtPrint( _cmFt_t* p, const char* fmt, ... )
  129. {
  130. va_list vl;
  131. va_start(vl,fmt);
  132. cmRptVPrintf(&p->ctx.rpt,fmt,vl);
  133. va_end(vl);
  134. }
  135. cmFtRC_t _cmFtErrorV( cmFtRC_t rc, _cmFt_t* p, const char* fmt, va_list vl )
  136. { return cmErrVMsg(&p->err,rc,fmt,vl); }
  137. cmFtRC_t _cmFtError( cmFtRC_t rc, _cmFt_t* p, const char* fmt, ... )
  138. {
  139. va_list vl;
  140. va_start(vl,fmt);
  141. _cmFtErrorV(rc,p,fmt,vl);
  142. va_end(vl);
  143. return rc;
  144. }
  145. _cmFt_t* _cmFtHandleToPtr( cmFtH_t h )
  146. {
  147. assert( h.h != NULL );
  148. return (_cmFt_t*)h.h;
  149. }
  150. _cmFtFile_t* _cmFtFileHandleToPtr( cmFtFileH_t h )
  151. {
  152. assert( h.h != NULL );
  153. return (_cmFtFile_t*)h.h;
  154. }
  155. _cmFtLabel_t* _cmFtIdToLabelPtr( unsigned id )
  156. {
  157. unsigned i=0;
  158. for(i=0; _cmFtLabelArray[i].id != kInvalidFtId; ++i)
  159. if( _cmFtLabelArray[i].id == id )
  160. return _cmFtLabelArray + i;
  161. assert(0);
  162. return NULL;
  163. }
  164. enum
  165. {
  166. kInfoSrFtId = kStructSrId,
  167. kParamSrFtId,
  168. kSkipSrFtId,
  169. kAttrSrFtId,
  170. kStatSrFtId,
  171. kHdrSrFtId,
  172. kSkipVSrFtId = kSkipSrFtId + kArraySrFl,
  173. kAttrVSrFtId = kAttrSrFtId + kArraySrFl,
  174. kStatVSrFtId = kStatSrFtId + kArraySrFl
  175. };
  176. cmFtRC_t _cmFtFormatFileHdr( _cmFt_t* p )
  177. {
  178. cmFtRC_t rc = kOkFtRC;
  179. cmSrH_t h = p->srH;
  180. cmSrGetAndClearLastErrorCode(h);
  181. if( cmSrFmtReset( h ) != kOkSrRC )
  182. {
  183. rc = _cmFtError( kSerialFailFtRC, p, "Serializer format reset failed.");
  184. goto errLabel;
  185. }
  186. // cmFtSkip_t smpIdx smpCnt
  187. cmSrDefFmt( h, kSkipSrFtId, kUIntSrId, kUIntSrId, kInvalidSrId );
  188. // cmFtAttr_t featId vect cnt normFl
  189. cmSrDefFmt( h, kAttrSrFtId, kUIntSrId, kUIntSrId, kBoolSrId, kInvalidSrId );
  190. // cmFtParam_t
  191. cmSrDefFmt( h, kParamSrFtId,
  192. // audioFn featFn chIdx
  193. kCharVSrId, kCharVSrId, kUIntSrId,
  194. // wndMs hopFact normAudFl cqMinPitch cqMaxPitch
  195. kRealSrId, kUIntSrId, kBoolSrId, kUCharSrId, kUCharSrId,
  196. // cqBins minDb skipV attrV
  197. kUIntSrId, kRealSrId, kSkipVSrFtId, kAttrVSrFtId, kInvalidSrId );
  198. // cmFtInfo_t
  199. cmSrDefFmt( h, kInfoSrFtId,
  200. // frmCnt srate fftSmpCnt hopSmpCnt binCnt skipFrmCnt floorFrmCnt param
  201. kUIntSrId, kRealSrId, kUIntSrId, kUIntSrId, kUIntSrId, kUIntSrId, kUIntSrId, kParamSrFtId, kInvalidSrId );
  202. // cmFtSumm_t
  203. cmSrDefFmt( h, kStatSrFtId,
  204. // id cnt
  205. kUIntSrId, kUIntSrId,
  206. // raw minV maxV avgV std-dev
  207. kRealVSrId, kRealVSrId, kRealVSrId, kRealVSrId,
  208. // raw min max
  209. kRealSrId, kRealSrId,
  210. // norm minV maxV avgV std-dev
  211. kRealVSrId, kRealVSrId, kRealVSrId, kRealVSrId,
  212. // raw min max
  213. kRealSrId, kRealSrId, kInvalidSrId );
  214. // master header record info stat array
  215. cmSrDefFmt( h, kHdrSrFtId, kInfoSrFtId, kStatVSrFtId, kInvalidSrId );
  216. if( cmSrLastErrorCode(h) != kOkSrRC )
  217. rc = _cmFtError( kSerialFailFtRC,p, "Serializer formatting failed.");
  218. errLabel:
  219. return rc;
  220. }
  221. cmFtRC_t _cmFtSerializeFileHdr( _cmFt_t* p, cmFtInfo_t* f, cmFtParam_t* pp, cmFtSumm_t* summArray, void** bufPtrPtr, unsigned* bufByteCntPtr )
  222. {
  223. cmFtRC_t rc = kOkFtRC;
  224. cmSrH_t h = p->srH;
  225. unsigned i;
  226. cmSrWrReset(h);
  227. cmSrWrStructBegin(h, kHdrSrFtId );
  228. // info record
  229. cmSrWrStruct( h, kInfoSrFtId, 1 );
  230. cmSrWrStructBegin(h, kInfoSrFtId );
  231. cmSrWrUInt( h, f->frmCnt );
  232. cmSrWrReal( h, f->srate );
  233. cmSrWrUInt( h, f->fftSmpCnt );
  234. cmSrWrUInt( h, f->hopSmpCnt );
  235. cmSrWrUInt( h, f->binCnt );
  236. cmSrWrUInt( h, f->skipFrmCnt );
  237. cmSrWrUInt( h, f->floorFrmCnt);
  238. // param recd
  239. cmSrWrStruct( h, kParamSrFtId, 1 );
  240. cmSrWrStructBegin(h, kParamSrFtId );
  241. cmSrWrCharV( h, pp->audioFn, strlen(pp->audioFn)+1);
  242. cmSrWrCharV( h, pp->featFn, strlen(pp->featFn)+1);
  243. cmSrWrUInt( h, pp->chIdx );
  244. cmSrWrReal( h, pp->wndMs );
  245. cmSrWrUInt( h, pp->hopFact);
  246. cmSrWrBool( h, pp->normAudioFl);
  247. cmSrWrUChar( h, pp->constQMinPitch);
  248. cmSrWrUChar( h, pp->constQMaxPitch);
  249. cmSrWrUInt( h, pp->constQBinsPerOctave);
  250. cmSrWrReal( h, pp->minDb );
  251. // skip array
  252. cmSrWrStruct(h, kSkipSrFtId, pp->skipCnt );
  253. for(i=0; i<pp->skipCnt; ++i)
  254. {
  255. cmSrWrStructBegin(h, kSkipSrFtId );
  256. cmSrWrUInt( h, pp->skipArray[i].smpIdx);
  257. cmSrWrUInt( h, pp->skipArray[i].smpCnt);
  258. cmSrWrStructEnd(h);
  259. }
  260. // attr array
  261. cmSrWrStruct(h, kAttrSrFtId, pp->attrCnt );
  262. for(i=0; i<pp->attrCnt; ++i)
  263. {
  264. cmSrWrStructBegin( h, kAttrSrFtId );
  265. cmSrWrUInt( h, pp->attrArray[i].id );
  266. cmSrWrUInt( h, pp->attrArray[i].cnt );
  267. cmSrWrBool( h, pp->attrArray[i].normFl);
  268. cmSrWrStructEnd(h);
  269. }
  270. cmSrWrStructEnd(h); // end param
  271. cmSrWrStructEnd(h); // end info
  272. // write the status array
  273. cmSrWrStruct(h, kStatSrFtId, pp->attrCnt );
  274. for(i=0; i<pp->attrCnt; ++i)
  275. {
  276. assert( summArray[i].id == pp->attrArray[i].id );
  277. cmSrWrStructBegin(h,kStatSrFtId);
  278. cmSrWrUInt( h, summArray[i].id);
  279. cmSrWrUInt( h, summArray[i].cnt);
  280. cmSrWrRealV( h, summArray[i].rawMinV, pp->attrArray[i].cnt);
  281. cmSrWrRealV( h, summArray[i].rawMaxV, pp->attrArray[i].cnt);
  282. cmSrWrRealV( h, summArray[i].rawAvgV, pp->attrArray[i].cnt);
  283. cmSrWrRealV( h, summArray[i].rawSdvV, pp->attrArray[i].cnt);
  284. cmSrWrReal( h, summArray[i].rawMin );
  285. cmSrWrReal( h, summArray[i].rawMax );
  286. cmSrWrRealV( h, summArray[i].normMinV, pp->attrArray[i].cnt);
  287. cmSrWrRealV( h, summArray[i].normMaxV, pp->attrArray[i].cnt);
  288. cmSrWrRealV( h, summArray[i].normAvgV, pp->attrArray[i].cnt);
  289. cmSrWrRealV( h, summArray[i].normSdvV, pp->attrArray[i].cnt);
  290. cmSrWrReal( h, summArray[i].normMin );
  291. cmSrWrReal( h, summArray[i].normMax );
  292. cmSrWrStructEnd(h);
  293. }
  294. if( cmSrLastErrorCode(h) != kOkSrRC )
  295. {
  296. rc = _cmFtError( kSerialFailFtRC, p, "Header serialization failed.");
  297. goto errLabel;
  298. }
  299. if((*bufPtrPtr = cmSrWrAllocBuf(h,bufByteCntPtr)) == NULL )
  300. {
  301. rc = _cmFtError( kSerialFailFtRC, p, "Header serializer failed on write buffer allocation.");
  302. goto errLabel;
  303. }
  304. errLabel:
  305. return rc;
  306. }
  307. cmFtRC_t _cmDeserializeFileHdr( _cmFt_t* p, _cmFtFile_t* fp, void* buf, unsigned bufByteCnt )
  308. {
  309. cmFtRC_t rc = kOkFtRC;
  310. cmSrH_t h = p->srH;
  311. unsigned n,i;
  312. cmFtInfo_t* f = &fp->info;
  313. cmFtParam_t* pp = &fp->info.param;
  314. // do endian swap
  315. if( cmSrRdProcessBuffer(h, buf, bufByteCnt ) != kOkSrRC )
  316. {
  317. rc = _cmFtError( kSerialFailFtRC, p, "Deserializatoin buffer pre-process failed.");
  318. goto errLabel;
  319. }
  320. // duplciate the buffer - this will allow us to use memory in the buffer to hold header objects.
  321. fp->hdrBuf = cmMemResize( char, fp->hdrBuf, bufByteCnt );
  322. memcpy(fp->hdrBuf,buf,bufByteCnt);
  323. // setup the serializer reader
  324. if( cmSrRdSetup( h, fp->hdrBuf, bufByteCnt ) != kOkSrRC )
  325. {
  326. rc = _cmFtError( kSerialFailFtRC, p, "Deserialization buffer setup failed.");
  327. goto errLabel;
  328. }
  329. cmSrRdStructBegin(h, kHdrSrFtId );
  330. // info record
  331. cmSrReadStruct( h, kInfoSrFtId, &n ); assert(n==1);
  332. cmSrRdStructBegin(h, kInfoSrFtId );
  333. cmSrReadUInt( h, &f->frmCnt );
  334. cmSrReadReal( h, &f->srate );
  335. cmSrReadUInt( h, &f->fftSmpCnt );
  336. cmSrReadUInt( h, &f->hopSmpCnt );
  337. cmSrReadUInt( h, &f->binCnt );
  338. cmSrReadUInt( h, &f->skipFrmCnt );
  339. cmSrReadUInt( h, &f->floorFrmCnt );
  340. // param recd
  341. cmSrReadStruct( h, kParamSrFtId, &n ); assert(n==1);
  342. cmSrRdStructBegin(h, kParamSrFtId );
  343. cmSrReadCharCV(h, &pp->audioFn, &n );
  344. cmSrReadCharCV(h, &pp->featFn, &n );
  345. cmSrReadUInt( h, &pp->chIdx );
  346. cmSrReadReal( h, &pp->wndMs );
  347. cmSrReadUInt( h, &pp->hopFact);
  348. cmSrReadBool( h, &pp->normAudioFl);
  349. cmSrReadUChar( h, &pp->constQMinPitch);
  350. cmSrReadUChar( h, &pp->constQMaxPitch);
  351. cmSrReadUInt( h, &pp->constQBinsPerOctave);
  352. cmSrReadReal( h, &pp->minDb );
  353. // skip array
  354. cmSrReadStruct(h, kSkipSrFtId, &pp->skipCnt );
  355. pp->skipArray = cmMemResizeZ( cmFtSkip_t, pp->skipArray, pp->skipCnt );
  356. for(i=0; i<pp->skipCnt; ++i)
  357. {
  358. cmSrRdStructBegin(h, kSkipSrFtId );
  359. cmSrReadUInt( h, &pp->skipArray[i].smpIdx);
  360. cmSrReadUInt( h, &pp->skipArray[i].smpCnt);
  361. cmSrRdStructEnd(h);
  362. }
  363. // attr array
  364. cmSrReadStruct(h, kAttrSrFtId, &pp->attrCnt );
  365. pp->attrArray = cmMemResizeZ( cmFtAttr_t, pp->attrArray, pp->attrCnt );
  366. for(i=0; i<pp->attrCnt; ++i)
  367. {
  368. cmSrRdStructBegin( h, kAttrSrFtId );
  369. cmSrReadUInt( h, &pp->attrArray[i].id );
  370. cmSrReadUInt( h, &pp->attrArray[i].cnt );
  371. cmSrReadBool( h, &pp->attrArray[i].normFl);
  372. cmSrRdStructEnd(h);
  373. }
  374. cmSrRdStructEnd(h); // end param
  375. cmSrRdStructEnd(h); // end info
  376. // read the status array
  377. cmSrReadStruct(h, kStatSrFtId, &n );
  378. assert( n == pp->attrCnt );
  379. fp->info.summArray = cmMemResizeZ( cmFtSumm_t, fp->info.summArray, pp->attrCnt );
  380. for(i=0; i<pp->attrCnt; ++i)
  381. {
  382. cmSrRdStructBegin(h,kStatSrFtId);
  383. cmSrReadUInt( h, &fp->info.summArray[i].id);
  384. assert( fp->info.summArray[i].id == pp->attrArray[i].id );
  385. cmSrReadUInt( h, &fp->info.summArray[i].cnt);
  386. cmSrReadRealV( h, &fp->info.summArray[i].rawMinV, &pp->attrArray[i].cnt);
  387. cmSrReadRealV( h, &fp->info.summArray[i].rawMaxV, &pp->attrArray[i].cnt);
  388. cmSrReadRealV( h, &fp->info.summArray[i].rawAvgV, &pp->attrArray[i].cnt);
  389. cmSrReadRealV( h, &fp->info.summArray[i].rawSdvV, &pp->attrArray[i].cnt);
  390. cmSrReadReal( h, &fp->info.summArray[i].rawMin );
  391. cmSrReadReal( h, &fp->info.summArray[i].rawMax );
  392. cmSrReadRealV( h, &fp->info.summArray[i].normMinV, &pp->attrArray[i].cnt);
  393. cmSrReadRealV( h, &fp->info.summArray[i].normMaxV, &pp->attrArray[i].cnt);
  394. cmSrReadRealV( h, &fp->info.summArray[i].normAvgV, &pp->attrArray[i].cnt);
  395. cmSrReadRealV( h, &fp->info.summArray[i].normSdvV, &pp->attrArray[i].cnt);
  396. cmSrReadReal( h, &fp->info.summArray[i].normMin );
  397. cmSrReadReal( h, &fp->info.summArray[i].normMax );
  398. cmSrRdStructEnd(h);
  399. }
  400. if( cmSrLastErrorCode(h) != kOkSrRC )
  401. {
  402. rc = _cmFtError( kSerialFailFtRC, p, "Deserialization failed.");
  403. goto errLabel;
  404. }
  405. errLabel:
  406. return rc;
  407. }
  408. unsigned cmFtFeatLabelToId( const char* label )
  409. {
  410. unsigned i=0;
  411. for(i=0; _cmFtLabelArray[i].id != kInvalidFtId; ++i)
  412. if( strcmp(label,_cmFtLabelArray[i].label) == 0 )
  413. return _cmFtLabelArray[i].id;
  414. return kInvalidFtId;
  415. }
  416. const char* cmFtFeatIdToLabel( unsigned id )
  417. {
  418. unsigned i=0;
  419. for(i=0; _cmFtLabelArray[i].id != kInvalidFtId; ++i)
  420. if( _cmFtLabelArray[i].id == id )
  421. return _cmFtLabelArray[i].label;
  422. return NULL;
  423. }
  424. cmFtRC_t cmFtInitialize( cmFtH_t* hp, cmCtx_t* ctx )
  425. {
  426. cmFtRC_t rc;
  427. if((rc = cmFtFinalize(hp)) != kOkFtRC )
  428. return rc;
  429. _cmFt_t* p = cmMemAllocZ( _cmFt_t, 1 );
  430. cmErrSetup(&p->err,&ctx->rpt,"Feature file");
  431. p->ctx = *ctx;
  432. p->jsH = cmJsonNullHandle;
  433. p->progParamIdx = cmInvalidIdx;
  434. p->progPassIdx = 0;
  435. p->progSmpIdx = 0;
  436. p->progSmpCnt = 0;
  437. // initialize the serializer
  438. if( cmSrAlloc(&p->srH,ctx) != kOkSrRC )
  439. {
  440. rc = _cmFtError( kSerialFailFtRC, p, "The serializer allocation failed.");
  441. goto errLabel;
  442. }
  443. // setup the serializer format
  444. if((rc = _cmFtFormatFileHdr(p)) != kOkFtRC )
  445. goto errLabel;
  446. // create the proc context object
  447. if((p->ctxPtr = cmCtxAlloc(NULL,&p->ctx.rpt,cmLHeapNullHandle,cmSymTblNullHandle)) == NULL )
  448. {
  449. rc = _cmFtError(kDspProcFailFtRC,p, "The ctx compoenent allocation failed.");
  450. goto errLabel;
  451. }
  452. // create the audio file reader
  453. if((p->afRdPtr = cmAudioFileRdAlloc( p->ctxPtr, NULL, 0, NULL, cmInvalidIdx, 0, cmInvalidIdx )) == NULL )
  454. {
  455. rc = _cmFtError( kDspProcFailFtRC, p, "The audio file reader allocation failed.");
  456. goto errLabel;
  457. }
  458. // create the phase vocoder
  459. if((p->pvocPtr = cmPvAnlAlloc( p->ctxPtr, NULL, 0, 0, 0, 0, 0 )) == NULL )
  460. {
  461. rc = _cmFtError( kDspProcFailFtRC,p,"The phase vocoder allocation failed.");
  462. goto errLabel;
  463. }
  464. // create the BFCC transformer
  465. if((p->bfccPtr = cmBfccAlloc( p->ctxPtr, NULL, 0, 0, 0 )) == NULL )
  466. {
  467. rc = _cmFtError( kDspProcFailFtRC,p,"The BFCC generator allocation failed.");
  468. goto errLabel;
  469. }
  470. // create the MFCC generator
  471. if((p->mfccPtr = cmMfccAlloc( p->ctxPtr, NULL, 0, 0, 0, 0)) == NULL )
  472. {
  473. rc = _cmFtError( kDspProcFailFtRC,p,"The MFCC generator allocation failed.");
  474. goto errLabel;
  475. }
  476. // create the Cepstrum transformer
  477. if((p->cepsPtr = cmCepsAlloc( p->ctxPtr, NULL, 0, 0 )) == NULL )
  478. {
  479. rc = _cmFtError( kDspProcFailFtRC,p,"The Cepstrum generator allocation failed.");
  480. goto errLabel;
  481. }
  482. // create the Constant Q generator
  483. if((p->constqPtr = cmConstQAlloc( p->ctxPtr, NULL, 0, 0, 0, 0,0 )) == NULL )
  484. {
  485. rc = _cmFtError( kDspProcFailFtRC,p,"The Constant-Q generator allocation failed.");
  486. goto errLabel;
  487. }
  488. hp->h = p;
  489. errLabel:
  490. return rc;
  491. }
  492. cmFtRC_t cmFtFinalize( cmFtH_t* hp )
  493. {
  494. cmFtRC_t rc = kOkFsRC;
  495. unsigned i;
  496. assert( hp != NULL );
  497. if( hp->h == NULL )
  498. return kOkFsRC;
  499. _cmFt_t* p = _cmFtHandleToPtr(*hp);
  500. for(i=0; i<p->paramCnt; ++i)
  501. cmMemPtrFree(&p->paramArray[i].skipArray);
  502. cmMemPtrFree(&p->attrArray);
  503. p->attrCnt = 0;
  504. cmMemPtrFree(&p->paramArray);
  505. p->paramCnt = 0;
  506. if( cmConstQFree(&p->constqPtr) != cmOkRC )
  507. {
  508. rc = _cmFtError( kDspProcFailFtRC,p,"Constant-Q generator free failed.");
  509. goto errLabel;
  510. }
  511. if( cmCepsFree(&p->cepsPtr) != cmOkRC )
  512. {
  513. rc = _cmFtError( kDspProcFailFtRC,p,"Cepstrum generator free failed.");
  514. goto errLabel;
  515. }
  516. if( cmMfccFree(&p->mfccPtr) != cmOkRC )
  517. {
  518. rc = _cmFtError( kDspProcFailFtRC,p,"MFCC generator free failed.");
  519. goto errLabel;
  520. }
  521. if( cmBfccFree(&p->bfccPtr) != cmOkRC )
  522. {
  523. rc = _cmFtError( kDspProcFailFtRC,p,"BFCC generator free failed.");
  524. goto errLabel;
  525. }
  526. if( cmPvAnlFree(&p->pvocPtr) != cmOkRC )
  527. {
  528. rc = _cmFtError( kDspProcFailFtRC,p,"Phase voocoder free failed.");
  529. goto errLabel;
  530. }
  531. if( cmAudioFileRdFree(&p->afRdPtr) != cmOkRC )
  532. {
  533. rc = _cmFtError( kDspProcFailFtRC,p,"Audio file reader failed.");
  534. goto errLabel;
  535. }
  536. if( cmCtxFree(&p->ctxPtr) != cmOkRC )
  537. {
  538. rc = _cmFtError( kDspProcFailFtRC,p,"Context proc failed.");
  539. goto errLabel;
  540. }
  541. if( cmJsonFinalize(&p->jsH) != kOkJsRC )
  542. {
  543. rc = _cmFtError(kJsonFailFtRC, p, "The JSON system object finalization failed.");
  544. goto errLabel;
  545. }
  546. if( cmSrFree(&p->srH) != kOkSrRC )
  547. {
  548. rc = _cmFtError(kSerialFailFtRC, p, "The serializer free failed.");
  549. goto errLabel;
  550. }
  551. cmMemPtrFree(&p);
  552. hp->h = NULL;
  553. errLabel:
  554. return rc;
  555. }
  556. bool cmFtIsValid( cmFtH_t h )
  557. { return h.h != NULL; }
  558. cmFtRC_t cmFtParse( cmFtH_t h, const char* cfgFn )
  559. {
  560. cmFtRC_t rc = kOkFtRC;
  561. cmJsRC_t jsRC = kOkJsRC;
  562. cmJsonNode_t* rootPtr = NULL;
  563. const char* errLabelPtr = NULL;
  564. const char* outDir = NULL;
  565. cmReal_t wndMs = 0;
  566. unsigned hopFact = 0;
  567. bool normAudioFl = false;
  568. const char* constQMinPitchStr = NULL;
  569. const char* constQMaxPitchStr = NULL;
  570. unsigned constQBinsPerOctave = 0;
  571. cmMidiByte_t constQMinPitch = 0;
  572. cmMidiByte_t constQMaxPitch = 0;
  573. cmReal_t minDb = 0;
  574. cmReal_t floorThreshDb = 0;
  575. cmJsonNode_t* featArrayNodePtr = NULL;
  576. cmJsonNode_t* audioFnArrayNodePtr = NULL;
  577. _cmFt_t* p = _cmFtHandleToPtr(h);
  578. unsigned i,j;
  579. assert( cfgFn != NULL );
  580. // parse file
  581. if( cmJsonInitializeFromFile( &p->jsH, cfgFn, &p->ctx ) != kOkJsRC )
  582. {
  583. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. file parse failed on: '%s'", cfgFn );
  584. goto errLabel;
  585. }
  586. // get the json cfg root
  587. if( (rootPtr = cmJsonRoot( p->jsH )) == NULL )
  588. {
  589. rc = _cmFtError( kCfgParseFailFtRC, p, "The cfg. file '%s' appears to be empty.", cfgFn );
  590. goto errLabel;
  591. }
  592. // read the cfg file header
  593. if((jsRC = cmJsonMemberValues( rootPtr, &errLabelPtr,
  594. "outDir", kStringTId, &outDir,
  595. "wndMs", kRealTId, &wndMs,
  596. "hopFact", kIntTId, &hopFact,
  597. "normAudioFl", kTrueTId, &normAudioFl,
  598. "constQMinPitch", kStringTId, &constQMinPitchStr,
  599. "constQMaxPitch", kStringTId, &constQMaxPitchStr,
  600. "constQBinsPerOctave", kIntTId, &constQBinsPerOctave,
  601. "minDb", kRealTId, &minDb,
  602. "floorThreshDb", kRealTId, &floorThreshDb,
  603. "featArray", kArrayTId, &featArrayNodePtr,
  604. "audioFnArray", kArrayTId, &audioFnArrayNodePtr,
  605. NULL )) != kOkJsRC )
  606. {
  607. if( jsRC == kNodeNotFoundJsRC )
  608. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. field not found:'%s' in file:'%s'.",cmStringNullGuard(errLabelPtr),cmStringNullGuard(cfgFn));
  609. else
  610. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. header parse failed '%s'.",cmStringNullGuard(cfgFn) );
  611. goto errLabel;
  612. }
  613. // convert the min const-q sci pitch string to a midi pitch value
  614. if( (constQMinPitch = cmSciPitchToMidi( constQMinPitchStr )) == kInvalidMidiPitch )
  615. {
  616. rc = _cmFtError( kCfgParseFailFtRC, p, "The const-Q min. pitch ('%s') is invalid.", cmStringNullGuard(constQMinPitchStr));
  617. goto errLabel;
  618. }
  619. // convert the max const-q sci pitch string to a midi pitch value
  620. if( (constQMaxPitch = cmSciPitchToMidi( constQMaxPitchStr )) == kInvalidMidiPitch )
  621. {
  622. rc = _cmFtError( kCfgParseFailFtRC, p, "The const-Q max. pitch ('%s') is invalid.", cmStringNullGuard(constQMaxPitchStr));
  623. goto errLabel;
  624. }
  625. unsigned parseAttrCnt = cmJsonChildCount( featArrayNodePtr );
  626. p->attrArray = cmMemAllocZ( cmFtAttr_t, parseAttrCnt );
  627. // read the attribute array
  628. for(i=0,j=0; i<parseAttrCnt; ++i)
  629. {
  630. const char* featLabel;
  631. // set default values
  632. p->attrArray[j].cnt = 0;
  633. p->attrArray[j].enableFl = true;
  634. if((jsRC = cmJsonMemberValues( cmJsonArrayElement(featArrayNodePtr,i), &errLabelPtr,
  635. "feat", kStringTId, &featLabel,
  636. "cnt", kIntTId | kOptArgJsFl, &p->attrArray[j].cnt,
  637. "normFl", kTrueTId, &p->attrArray[j].normFl,
  638. "enableFl", kTrueTId | kOptArgJsFl, &p->attrArray[j].enableFl,
  639. NULL )) != kOkJsRC )
  640. {
  641. if( jsRC == kNodeNotFoundJsRC )
  642. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. feature attribute field:'%s' not found at index %i in file:'%s'.",cmStringNullGuard(errLabelPtr),i,cmStringNullGuard(cfgFn));
  643. else
  644. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. feature attribute parse failed at index %i in '%s'.",i,cmStringNullGuard(cfgFn) );
  645. goto errLabel;
  646. }
  647. if( p->attrArray[j].enableFl )
  648. {
  649. // convert the feature label to an id
  650. if( (p->attrArray[j].id = cmFtFeatLabelToId( featLabel)) == kInvalidFtId )
  651. {
  652. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. feature '%s' was not found at featArray index %i in '%s'.", featLabel, i, cmStringNullGuard(cfgFn));
  653. goto errLabel;
  654. }
  655. ++j;
  656. }
  657. }
  658. p->attrCnt = j;
  659. p->paramCnt = cmJsonChildCount( audioFnArrayNodePtr );
  660. p->paramArray = cmMemAllocZ( cmFtParam_t, p->paramCnt );
  661. // read the audio file array
  662. for(i=0; i<p->paramCnt; ++i)
  663. {
  664. cmJsonNode_t* skipArrayNodePtr = NULL;
  665. // read the audio file read
  666. if((jsRC = cmJsonMemberValues( cmJsonArrayElement(audioFnArrayNodePtr,i), &errLabelPtr,
  667. "audioFn", kStringTId, &p->paramArray[i].audioFn,
  668. "featFn", kStringTId, &p->paramArray[i].featFn,
  669. "skipArray",kArrayTId | kOptArgJsFl, &skipArrayNodePtr,
  670. "chIdx", kIntTId, &p->paramArray[i].chIdx,
  671. NULL)) != kOkJsRC )
  672. {
  673. if( jsRC == kNodeNotFoundJsRC )
  674. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. audio file field :'%s' not found at index %i in file:'%s'.",cmStringNullGuard(errLabelPtr),i,cmStringNullGuard(cfgFn));
  675. else
  676. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. audio file parse failed at index %i in '%s'.",i,cmStringNullGuard(cfgFn) );
  677. goto errLabel;
  678. }
  679. p->paramArray[i].wndMs = wndMs;
  680. p->paramArray[i].hopFact = hopFact;
  681. p->paramArray[i].normAudioFl = normAudioFl;
  682. p->paramArray[i].constQBinsPerOctave = constQBinsPerOctave;
  683. p->paramArray[i].constQMinPitch = constQMinPitch;
  684. p->paramArray[i].constQMaxPitch = constQMaxPitch;
  685. p->paramArray[i].minDb = minDb;
  686. p->paramArray[i].floorThreshDb = floorThreshDb;
  687. p->paramArray[i].attrArray = p->attrArray;
  688. p->paramArray[i].attrCnt = p->attrCnt;
  689. p->paramArray[i].skipCnt = skipArrayNodePtr==NULL ? 0 : cmJsonChildCount( skipArrayNodePtr );
  690. p->paramArray[i].skipArray = skipArrayNodePtr==NULL ? NULL : cmMemAllocZ( cmFtSkip_t, p->paramArray[i].skipCnt );
  691. // read the skip array in the audio file recd
  692. for(j=0; j<p->paramArray[i].skipCnt; ++j)
  693. {
  694. if((jsRC = cmJsonMemberValues( cmJsonArrayElement(skipArrayNodePtr,j), &errLabelPtr,
  695. "smpIdx", kIntTId, &p->paramArray[i].skipArray[j].smpIdx,
  696. "smpCnt", kIntTId, &p->paramArray[i].skipArray[j].smpCnt,
  697. NULL)) != kOkJsRC )
  698. {
  699. if( jsRC == kNodeNotFoundJsRC )
  700. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. audio file skip field '%s' not found at index %i in file:'%s'.",cmStringNullGuard(errLabelPtr),j,cmStringNullGuard(cfgFn));
  701. else
  702. rc = _cmFtError( kCfgParseFailFtRC, p, "Cfg. audio file skip parse failed at index %i in '%s'.",j, cmStringNullGuard(cfgFn) );
  703. goto errLabel;
  704. }
  705. }
  706. // if the audio file does not exist
  707. if( cmFsIsFile( p->paramArray[i].audioFn ) == false )
  708. {
  709. rc = _cmFtError( kFileNotFoundFtRC, p, "The audio file '%s' was not found.", p->paramArray[i].audioFn );
  710. goto errLabel;
  711. }
  712. // form the feature file name for this file
  713. if((p->paramArray[i].featFn = cmFsMakeFn( outDir, p->paramArray[i].featFn, NULL, NULL )) == NULL )
  714. {
  715. rc = _cmFtError( kFileSysFailFtRC, p, "The attempt to create the feature file name for '%s' failed.", cmStringNullGuard(p->paramArray[i].featFn));
  716. goto errLabel;
  717. }
  718. }
  719. // if the output directory does not exist then create it
  720. if( cmFsIsDir(outDir) == false )
  721. if( cmFsMkDir(outDir) != kOkFsRC )
  722. {
  723. rc = _cmFtError( kDirCreateFailFtRC, p, "The attempt to create the output directory '%s' failed.",outDir);
  724. goto errLabel;
  725. }
  726. errLabel:
  727. return rc;
  728. }
  729. bool _cmFtZeroSkipSamples( const cmFtParam_t* pp, cmSample_t* v, unsigned vn, unsigned begSmpIdx )
  730. {
  731. unsigned endSmpIdx = begSmpIdx + vn - 1;
  732. bool retFl = false;
  733. unsigned i = 0;
  734. const cmFtSkip_t* sp = pp->skipArray;
  735. // for each skipArray[] record
  736. for(i=0; i<pp->skipCnt; ++sp,++i)
  737. if( sp->smpCnt != 0 )
  738. {
  739. unsigned bi = 0;
  740. unsigned ei = vn-1;
  741. unsigned sp_endIdx;
  742. // if sp->smpCnt is negative then skip to end of file
  743. if( sp->smpCnt == -1 )
  744. sp_endIdx = endSmpIdx;
  745. else
  746. sp_endIdx = sp->smpIdx + sp->smpCnt - 1;
  747. // begSmpIdx:endSmpIdx indicate the index range of v[]
  748. // sp->smpIdx:sp_endIdx indicate the skip index range
  749. // if the skip range is entirely before or after v[]
  750. if( sp_endIdx < begSmpIdx || sp->smpIdx > endSmpIdx )
  751. continue;
  752. // if sp->smpIdx is inside v[]
  753. if( sp->smpIdx > begSmpIdx )
  754. bi = sp->smpIdx - begSmpIdx;
  755. // if sp_endIdx is inside v[]
  756. if( sp_endIdx < endSmpIdx )
  757. {
  758. assert( endSmpIdx - sp_endIdx <= ei );
  759. ei -= endSmpIdx - sp_endIdx;
  760. }
  761. assert( bi <= ei );
  762. assert( bi < vn && ei < vn );
  763. // zero the samples which are inside the skip range
  764. cmVOS_Zero(v+bi,(ei-bi)+1);
  765. retFl = true;
  766. }
  767. return retFl;
  768. }
  769. cmFtRC_t _cmFtProcInit( _cmFt_t* p, cmFtInfo_t* f, cmFtParam_t* pp, _cmFtAnl_t* anlArray )
  770. {
  771. cmFtRC_t rc = kOkFtRC;
  772. unsigned i;
  773. // initialize the phase vocoder
  774. if( cmPvAnlInit( p->pvocPtr, f->hopSmpCnt, f->srate, f->fftSmpCnt, f->hopSmpCnt, kNoCalcHzPvaFl ) != cmOkRC )
  775. {
  776. rc = _cmFtError(kDspProcFailFtRC,p," The phase vocoder initialization failed.");
  777. goto errLabel;
  778. }
  779. assert( f->binCnt == p->pvocPtr->binCnt );
  780. cmReal_t binHz = f->srate / f->fftSmpCnt;
  781. // initialize each requested feature extractor
  782. for(i=0; i<pp->attrCnt; ++i)
  783. {
  784. _cmFtAnl_t* a = anlArray + i;
  785. assert( a->lp != NULL );
  786. switch( a->ap->id )
  787. {
  788. case kAmplFtId:
  789. case kDbAmplFtId:
  790. case kPowFtId:
  791. case kDbPowFtId:
  792. case kPhaseFtId:
  793. if( a->ap->cnt > f->binCnt )
  794. {
  795. rc = _cmFtError(kParamRangeFtRC,p,"The '%s' cnt value: %i must be less than the bin count: %i.",a->lp->label,a->ap->cnt,f->binCnt+1);
  796. goto errLabel;
  797. }
  798. if( a->ap->cnt == 0 )
  799. a->ap->cnt = f->binCnt;
  800. break;
  801. case kBfccFtId: // initialize the BFCC generator
  802. if( a->ap->cnt > kDefaultBarkBandCnt )
  803. {
  804. rc = _cmFtError(kParamRangeFtRC,p,"The BFCC feature vector length (%i) must be less than (%i).", a->ap->cnt, kDefaultBarkBandCnt+1 );
  805. goto errLabel;
  806. }
  807. if( a->ap->cnt == 0 )
  808. a->ap->cnt = kDefaultBarkBandCnt;
  809. if( cmBfccInit( p->bfccPtr, kDefaultBarkBandCnt, p->pvocPtr->binCnt, binHz ) != cmOkRC )
  810. {
  811. rc = _cmFtError(kDspProcFailFtRC,p," The BFCC generator initialization failed.");
  812. goto errLabel;
  813. }
  814. break;
  815. case kMfccFtId: // initialize the MFCC generator
  816. if( a->ap->cnt > kDefaultMelBandCnt )
  817. {
  818. rc = _cmFtError(kParamRangeFtRC,p,"The MFCC feature vector length (%i) must be less than (%i).", a->ap->cnt, kDefaultMelBandCnt+1 );
  819. goto errLabel;
  820. }
  821. if( a->ap->cnt == 0 )
  822. a->ap->cnt = kDefaultMelBandCnt;
  823. if( cmMfccInit( p->mfccPtr, f->srate, kDefaultMelBandCnt, a->ap->cnt, p->pvocPtr->binCnt ) != cmOkRC )
  824. {
  825. rc = _cmFtError(kDspProcFailFtRC,p," The MFCC generator initialization failed.");
  826. goto errLabel;
  827. }
  828. break;
  829. case kCepsFtId: // initialize the cepstrum generator
  830. if( a->ap->cnt > f->binCnt )
  831. {
  832. rc = _cmFtError(kParamRangeFtRC,p,"The '%s' cnt value: %i must be less than the bin count: %i.",a->lp->label,a->ap->cnt,f->binCnt+1);
  833. goto errLabel;
  834. }
  835. if( a->ap->cnt == 0 )
  836. a->ap->cnt = f->binCnt;
  837. if( cmCepsInit( p->cepsPtr, p->pvocPtr->binCnt, a->ap->cnt ) != cmOkRC )
  838. {
  839. rc = _cmFtError(kDspProcFailFtRC,p," The Cepstrum generator initialization failed.");
  840. goto errLabel;
  841. }
  842. break;
  843. case kConstQFtId: // initialize the constant Q generator
  844. case kLogConstQFtId:
  845. if( cmConstQInit(p->constqPtr, f->srate, pp->constQMinPitch, pp->constQMaxPitch, pp->constQBinsPerOctave, kConstQThresh ) != cmOkRC )
  846. {
  847. rc = _cmFtError(kDspProcFailFtRC,p,"The constant-q generator initialization failed.");
  848. goto errLabel;
  849. }
  850. if( a->ap->cnt > p->constqPtr->constQBinCnt )
  851. {
  852. rc = _cmFtError(kParamRangeFtRC,p,"The '%s' cnt value: %i must be less than the bin count: %i.",a->lp->label,a->ap->cnt,p->constqPtr->constQBinCnt+1);
  853. goto errLabel;
  854. }
  855. if( a->ap->cnt == 0 )
  856. a->ap->cnt = p->constqPtr->constQBinCnt;
  857. break;
  858. case kRmsFtId:
  859. case kDbRmsFtId:
  860. a->ap->cnt = 1; // scalars must have a cnt == 1
  861. break;
  862. case kD1AmplFtId:
  863. case kD1DbAmplFtId:
  864. case kD1PowFtId:
  865. case kD1DbPowFtId:
  866. case kD1PhaseFtId:
  867. case kD1BfccFtId:
  868. case kD1MfccFtId:
  869. case kD1CepsFtId:
  870. case kD1ConstQFtId:
  871. case kD1LogConstQFtId:
  872. if( a->ap->cnt == 0 )
  873. a->ap->cnt = a->sp->ap->cnt;
  874. break;
  875. case kD1RmsFtId:
  876. case kD1DbRmsFtId:
  877. a->ap->cnt = 1;
  878. break;
  879. default:
  880. { assert(0); }
  881. } // end switch
  882. // setup the feature label record and allocate the feature vector
  883. if( a->ap->cnt )
  884. {
  885. // 2==cvp and pvp + kStatRecdVectCnt==count of summary vectors
  886. unsigned nn = a->ap->cnt * (2 + kStatRecdVectCnt);
  887. unsigned n = 0;
  888. assert(a->v == NULL);
  889. a->v = cmMemAllocZ( cmReal_t, nn );
  890. a->cvp = a->v + n; n += a->ap->cnt;
  891. a->pvp = a->v + n; n += a->ap->cnt;
  892. a->sr->cnt = a->ap->cnt;
  893. a->sr->rawMinV = a->v + n; n += a->ap->cnt;
  894. a->sr->rawMaxV = a->v + n; n += a->ap->cnt;
  895. a->sr->rawAvgV = a->v + n; n += a->ap->cnt;
  896. a->sr->rawSdvV = a->v + n; n += a->ap->cnt;
  897. a->sr->rawMin = cmReal_MAX;
  898. a->sr->rawMax = -cmReal_MAX;
  899. cmVOR_Fill( a->sr->rawMinV, a->ap->cnt, cmReal_MAX );
  900. cmVOR_Fill( a->sr->rawMaxV, a->ap->cnt, -cmReal_MAX );
  901. a->sr->normMinV = a->v + n; n += a->ap->cnt;
  902. a->sr->normMaxV = a->v + n; n += a->ap->cnt;
  903. a->sr->normAvgV = a->v + n; n += a->ap->cnt;
  904. a->sr->normSdvV = a->v + n; n += a->ap->cnt;
  905. a->sr->normMin = cmReal_MAX;
  906. a->sr->normMax = -cmReal_MAX;
  907. cmVOR_Fill( a->sr->normMinV, a->ap->cnt, cmReal_MAX );
  908. cmVOR_Fill( a->sr->normMaxV, a->ap->cnt, -cmReal_MAX );
  909. assert(n == nn);
  910. }
  911. if( a->sp != NULL )
  912. {
  913. if( a->sp->ap->cnt > a->ap->cnt )
  914. {
  915. rc = _cmFtError( kParamRangeFtRC,p,"The feature element count '%i' for '%s' is greater than the source vector '%s' '%i'.", a->ap->cnt, a->lp->label, a->sp->lp->label, a->sp->ap->cnt );
  916. goto errLabel;
  917. }
  918. }
  919. } // end for
  920. errLabel:
  921. return rc;
  922. }
  923. cmFtRC_t _cmFtProcExec( _cmFt_t* p, cmFtInfo_t* f, cmFtParam_t* pp, cmFrameFileH_t ffH, _cmFtAnl_t* anlArray, const cmSample_t* audV )
  924. {
  925. cmFtRC_t rc = kOkFtRC;
  926. unsigned i;
  927. for(i=0; i < pp->attrCnt; ++i)
  928. {
  929. _cmFtAnl_t* a = anlArray + i;
  930. // swap current and previous pointer
  931. cmReal_t* tp = a->cvp;
  932. a->cvp = a->pvp;
  933. a->pvp = tp;
  934. switch( a->lp->id )
  935. {
  936. case kAmplFtId:
  937. cmVOR_Copy(a->cvp, a->ap->cnt, p->pvocPtr->magV );
  938. break;
  939. case kDbAmplFtId:
  940. cmVOR_AmplToDbVV( a->cvp, a->ap->cnt, p->pvocPtr->magV, pp->minDb );
  941. break;
  942. case kPowFtId:
  943. cmVOR_PowVVS( a->cvp, a->ap->cnt, p->pvocPtr->magV, 2.0 );
  944. break;
  945. case kDbPowFtId:
  946. cmVOR_PowToDbVV( a->cvp, a->ap->cnt, a->sp->cvp, pp->minDb );
  947. break;
  948. case kPhaseFtId:
  949. cmVOR_Copy( a->cvp, a->ap->cnt, p->pvocPtr->phsV );
  950. break;
  951. case kBfccFtId:
  952. {
  953. cmBfccExec( p->bfccPtr, p->pvocPtr->magV, p->pvocPtr->binCnt );
  954. cmVOR_Copy(a->cvp, a->ap->cnt, p->bfccPtr->outV );
  955. }
  956. break;
  957. case kMfccFtId:
  958. {
  959. cmMfccExecAmplitude( p->mfccPtr, p->pvocPtr->magV, p->pvocPtr->binCnt );
  960. cmVOR_Copy( a->cvp, a->ap->cnt, p->mfccPtr->outV );
  961. }
  962. break;
  963. case kCepsFtId:
  964. {
  965. cmCepsExec( p->cepsPtr, p->pvocPtr->magV, p->pvocPtr->phsV, p->pvocPtr->binCnt );
  966. cmVOR_Copy(a->cvp, a->ap->cnt, p->cepsPtr->outV );
  967. }
  968. break;
  969. case kConstQFtId:
  970. {
  971. // convert from float complex to double complex
  972. cmComplexR_t tmp0[ p->pvocPtr->binCnt ];
  973. unsigned j;
  974. for(j=0; j<p->pvocPtr->binCnt; ++j)
  975. tmp0[j] = p->pvocPtr->ft.complexV[j];
  976. cmConstQExec( p->constqPtr, tmp0, p->pvocPtr->binCnt );
  977. cmVOR_Copy( a->cvp, a->ap->cnt, p->constqPtr->magV );
  978. }
  979. break;
  980. case kLogConstQFtId:
  981. cmVOR_LogV( a->cvp, a->ap->cnt, p->constqPtr->magV );
  982. break;
  983. case kRmsFtId:
  984. a->cvp[0] = cmVOS_RMS( audV, p->afRdPtr->outN, p->afRdPtr->outN );
  985. break;
  986. case kDbRmsFtId:
  987. cmVOR_AmplToDbVV( a->cvp, 1, a->sp->cvp, pp->minDb );
  988. break;
  989. case kD1AmplFtId:
  990. case kD1DbAmplFtId:
  991. case kD1PowFtId:
  992. case kD1DbPowFtId:
  993. case kD1PhaseFtId:
  994. case kD1BfccFtId:
  995. case kD1MfccFtId:
  996. case kD1CepsFtId:
  997. case kD1ConstQFtId:
  998. case kD1LogConstQFtId:
  999. case kD1RmsFtId:
  1000. case kD1DbRmsFtId:
  1001. cmVOR_SubVVV( a->cvp, a->ap->cnt, a->sp->pvp, a->sp->cvp );
  1002. break;
  1003. default:
  1004. assert(0);
  1005. break;
  1006. } // end switch
  1007. if( cmFrameFileWriteMtxReal( ffH, a->lp->ffMtxId, a->lp->ffUnitsId, a->cvp, a->ap->cnt, 1 ) != kOkFfRC )
  1008. {
  1009. rc = _cmFtError( kFrameWriteFailFtRC, p, "Matrix write failed (feature:%s size:%i).",a->lp->label,a->ap->cnt);
  1010. goto errLabel;
  1011. }
  1012. }
  1013. errLabel:
  1014. return rc;
  1015. }
  1016. unsigned _cmFtWriteField( char* buf, unsigned bufByteCnt, unsigned bufIdx, const void* s, unsigned srcByteCnt )
  1017. {
  1018. assert( bufIdx + srcByteCnt <= bufByteCnt );
  1019. memcpy(buf+bufIdx,s,srcByteCnt);
  1020. return bufIdx + srcByteCnt;
  1021. }
  1022. cmFtRC_t _cmFtWriteFileHdr( _cmFt_t* p, cmFtInfo_t* f, cmFtParam_t* pp, cmFrameFileH_t ffH, cmFtSumm_t* summArray, bool updateFl )
  1023. {
  1024. cmFtRC_t rc = kOkFtRC;
  1025. void* buf;
  1026. unsigned bufByteCnt;
  1027. // serialize the file header
  1028. if((rc = _cmFtSerializeFileHdr(p,f,pp,summArray,&buf,&bufByteCnt)) != kOkFtRC )
  1029. goto errLabel;
  1030. if( updateFl )
  1031. {
  1032. const cmFfMtx_t* mp = NULL;
  1033. void* hdrPtr = NULL;
  1034. if( (hdrPtr = cmFrameFileMtxBlob(ffH, kDataMId, kNoUnitsUId, &mp )) == NULL )
  1035. {
  1036. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file header read before update failed.");
  1037. goto errLabel;
  1038. }
  1039. assert( mp->rowCnt == bufByteCnt );
  1040. memcpy( hdrPtr, buf, bufByteCnt );
  1041. }
  1042. else
  1043. {
  1044. if( cmFrameFileWriteMtxBlob( ffH, kDataMId, kNoUnitsUId, buf, bufByteCnt, 1 ) != kOkFfRC )
  1045. {
  1046. rc = _cmFtError( kFrameWriteFailFtRC, p, "Header write failed.");
  1047. goto errLabel;
  1048. }
  1049. }
  1050. errLabel:
  1051. return rc;
  1052. }
  1053. // Interface to the _cmFtProcFile() user programmable process function.
  1054. // This function is called once per each feature vector in the feature file.
  1055. // v[fn] points to the feature file.
  1056. // Return true if the feature has been modified and should be written back to disk.
  1057. typedef bool (*_cmFtProcFunc_t)( _cmFt_t* p, _cmFtAnl_t* a, cmReal_t* v, unsigned vn );
  1058. // Iterate through each frame and each frame matrix call procFunc().
  1059. cmFtRC_t _cmFtProcFile( _cmFt_t* p, cmFrameFileH_t ffH, cmFtParam_t* pp, _cmFtAnl_t* anlArray, _cmFtProcFunc_t procFunc )
  1060. {
  1061. cmFtRC_t rc = kOkFtRC;
  1062. cmFfRC_t ffRC = kOkFfRC;
  1063. unsigned i,j;
  1064. ++p->progPassIdx;
  1065. p->progSmpIdx = 0;
  1066. p->progSmpCnt = cmFrameFileDesc( ffH )->frameCnt;
  1067. // rewind the frame file
  1068. if( cmFrameFileRewind( ffH ) != kOkFfRC )
  1069. {
  1070. rc = _cmFtError(kFrameFileFailFtRC,p,"Normalize rewind failed on '%s'.", cmStringNullGuard(pp->featFn));
  1071. goto errLabel;
  1072. }
  1073. // load the next data frame
  1074. for(i=0; (ffRC=cmFrameFileFrameLoadNext(ffH,kFrameTypeFtId,kFrameStreamFtId,NULL)) == kOkFfRC; ++i,++p->progSmpIdx)
  1075. {
  1076. bool updateFl = false;
  1077. // for each feature matrix
  1078. for(j=0; j<pp->attrCnt; ++j)
  1079. {
  1080. unsigned dn;
  1081. cmReal_t* dp;
  1082. const cmFfMtx_t* mtxDescPtr = NULL;
  1083. _cmFtAnl_t* a = anlArray + j;
  1084. // get a pointer to the matrix data
  1085. if((dp = cmFrameFileMtxReal( ffH, a->lp->ffMtxId, a->lp->ffUnitsId, &mtxDescPtr )) == NULL )
  1086. {
  1087. rc = _cmFtError(kFrameFileFailFtRC,p,"Data access failed during post processing on feature:'%s' in '%s'.", a->lp->label,cmStringNullGuard(pp->featFn));
  1088. goto errLabel;
  1089. }
  1090. // get the lenth of the feature vector
  1091. dn = mtxDescPtr->rowCnt*mtxDescPtr->colCnt;
  1092. // processes this feature
  1093. if( procFunc(p,a,dp,dn) )
  1094. updateFl = true;
  1095. }
  1096. // write the frame back to disk
  1097. if( updateFl )
  1098. if( cmFrameFileFrameUpdate(ffH) != kOkFfRC )
  1099. {
  1100. rc = _cmFtError(kFrameFileFailFtRC,p,"Post procssing failed on record index %i in '%s'.", i, cmStringNullGuard(pp->featFn));
  1101. goto errLabel;
  1102. }
  1103. }
  1104. if( ffRC != kEofFfRC && ffRC != kOkFfRC )
  1105. {
  1106. rc = _cmFtError( kFrameFileFailFtRC,p,"Post processing iterationg failed on record index %i in '%s'.",i,cmStringNullGuard(pp->featFn));
  1107. goto errLabel;
  1108. }
  1109. errLabel:
  1110. return rc;
  1111. }
  1112. // Sum the feature vector into a->sr->rawAvg and track the global min/max value.
  1113. bool _cmFtProcRawMinMaxSum( _cmFt_t* p, _cmFtAnl_t* a, cmReal_t* v, unsigned vn )
  1114. {
  1115. assert( vn == a->ap->cnt );
  1116. cmVOR_AddVV( a->sr->rawAvgV, vn, v ); // track vector sum for use in avg
  1117. cmVOR_MinVV( a->sr->rawMinV, vn, v ); // track min/max per vector dim
  1118. cmVOR_MaxVV( a->sr->rawMaxV, vn, v );
  1119. a->sr->rawMin = cmMin(a->sr->rawMin, cmVOR_Min(v,vn,1)); // track global min/max
  1120. a->sr->rawMax = cmMax(a->sr->rawMax, cmVOR_Max(v,vn,1));
  1121. return false;
  1122. }
  1123. // Sum the the squared diff. between feature value and feature avg into rawSdvV[]
  1124. bool _cmFtProcRawStdDev( _cmFt_t* p, _cmFtAnl_t* a, cmReal_t* v, unsigned vn )
  1125. {
  1126. cmReal_t t[ vn ];
  1127. assert( vn == a->ap->cnt );
  1128. cmVOR_SubVVV( t, a->ap->cnt, v, a->sr->rawAvgV );
  1129. cmVOR_PowVS( t, a->ap->cnt, 2.0 );
  1130. cmVOR_AddVV( a->sr->rawSdvV, a->ap->cnt, t );
  1131. return false;
  1132. }
  1133. bool _cmFtProcNormMinMaxSum( _cmFt_t* p, _cmFtAnl_t* a, cmReal_t* v, unsigned vn )
  1134. {
  1135. assert( a->ap->cnt == vn );
  1136. if( a->ap->normFl == false )
  1137. {
  1138. cmVOR_Zero( a->sr->normMaxV, vn );
  1139. cmVOR_Zero( a->sr->normMinV, vn );
  1140. a->sr->normMin = 0;
  1141. a->sr->normMax = 0;
  1142. }
  1143. else
  1144. {
  1145. if( a->lp->bipolarFl )
  1146. {
  1147. // subtract mean and divide by std-dev
  1148. cmVOR_SubVV(v, vn, a->sr->rawAvgV );
  1149. cmVOR_DivVVZ(v, vn, a->sr->rawSdvV );
  1150. }
  1151. else
  1152. {
  1153. // scale feature into unit range based on file wide min/max
  1154. cmVOR_SubVS(v, vn, a->sr->rawMin );
  1155. if( a->sr->rawMax - a->sr->rawMin > 0 )
  1156. cmVOR_DivVS(v, vn, a->sr->rawMax - a->sr->rawMin );
  1157. else
  1158. cmVOR_Zero(v,vn);
  1159. // convert to unit total energy (UTE)
  1160. // (this makes the vector sum to one (like a prob. distrib))
  1161. if( vn > 1 )
  1162. {
  1163. cmReal_t sum = cmVOR_Sum(v, vn );
  1164. if( sum > 0 )
  1165. cmVOR_DivVS(v, vn, sum );
  1166. else
  1167. cmVOR_Zero(v,vn);
  1168. }
  1169. }
  1170. cmVOR_AddVV( a->sr->normAvgV, a->ap->cnt, v ); // track norm sum
  1171. cmVOR_MinVV( a->sr->normMinV, vn, v ); // track norm min/max per dim
  1172. cmVOR_MaxVV( a->sr->normMaxV, vn, v );
  1173. a->sr->normMin = cmMin(a->sr->normMin, cmVOR_Min(v,vn,1)); // track norm global min/max
  1174. a->sr->normMax = cmMax(a->sr->normMax, cmVOR_Max(v,vn,1));
  1175. return true;
  1176. }
  1177. return false;
  1178. }
  1179. // calc squared diff into a->sr->normSdv[]
  1180. bool _cmFtNormStdDev( _cmFt_t* p, _cmFtAnl_t* a, cmReal_t* v, unsigned vn )
  1181. {
  1182. if( a->ap->normFl )
  1183. {
  1184. assert( a->ap->cnt == vn );
  1185. cmReal_t t[vn];
  1186. cmVOR_SubVVV( t, a->ap->cnt, v, a->sr->normAvgV );
  1187. cmVOR_PowVS( t, a->ap->cnt, 2.0 );
  1188. cmVOR_AddVV( a->sr->normSdvV, a->ap->cnt, t );
  1189. }
  1190. return false;
  1191. }
  1192. // anlArray[] sorting function
  1193. int _cmFtAnlCompare( const void* pp0, const void* pp1 )
  1194. {
  1195. const _cmFtAnl_t* p0 = (const _cmFtAnl_t*)pp0;
  1196. const _cmFtAnl_t* p1 = (const _cmFtAnl_t*)pp1;
  1197. assert( p0 != NULL && p0->lp !=NULL && p1!=NULL && p1->lp != NULL );
  1198. return p0->lp->order - p1->lp->order;
  1199. }
  1200. cmFtRC_t _cmFtValidateAttrArray( _cmFt_t* p )
  1201. {
  1202. cmFtRC_t rc = kOkFtRC;
  1203. unsigned i,j;
  1204. for(i=0; i<p->attrCnt; ++i)
  1205. {
  1206. _cmFtLabel_t* lp = _cmFtIdToLabelPtr(p->attrArray[i].id);
  1207. assert( lp != NULL );
  1208. // check for duplicate features
  1209. for(j=0; j<p->attrCnt; ++j)
  1210. if( i!=j && p->attrArray[i].id == p->attrArray[j].id )
  1211. {
  1212. rc = _cmFtError( kParamErrorFtRC, p, "The attribute '%s' has duplicate entries in the attribute array.", cmStringNullGuard(lp->label));
  1213. goto errLabel;
  1214. }
  1215. // verify that the source id for this secondary feature was specified
  1216. if( lp->srcId != kInvalidFtId )
  1217. {
  1218. for(j=0; j<p->attrCnt; ++j)
  1219. if( p->attrArray[j].id == lp->srcId )
  1220. break;
  1221. if( j == p->attrCnt )
  1222. {
  1223. rc = _cmFtError( kParamErrorFtRC, p, "The primary feature '%s' must be specified in order to use the secondary feature '%s'.",cmStringNullGuard(_cmFtIdToLabelPtr(lp->srcId)->label),lp->label);
  1224. goto errLabel;
  1225. }
  1226. }
  1227. }
  1228. errLabel:
  1229. return rc;
  1230. }
  1231. cmFtRC_t cmFtAnalyzeFile( cmFtH_t h, cmFtParam_t* pp)
  1232. {
  1233. cmFtRC_t rc = kOkFtRC;
  1234. _cmFt_t* p = _cmFtHandleToPtr(h);
  1235. cmSample_t minSmp,maxSmp,meanSmp;
  1236. cmReal_t audioSigNormFact;
  1237. cmFtInfo_t f;
  1238. unsigned frameIdx,sampleIdx;
  1239. cmFrameFileH_t ffH = cmFrameFileNullHandle;
  1240. cmAudioFileInfo_t afInfo;
  1241. _cmFtAnl_t* anlArray = NULL;
  1242. cmFtSumm_t* summArray = NULL;
  1243. unsigned i;
  1244. cmReal_t floorThreshAmpl;
  1245. if((rc = _cmFtValidateAttrArray(p)) != kOkFtRC )
  1246. goto errLabel;
  1247. cmVOR_DbToAmplVV(&floorThreshAmpl,1,&pp->floorThreshDb);
  1248. // get the audio file header information
  1249. if( cmAudioFileGetInfo(pp->audioFn, &afInfo, &p->ctx.rpt ) != kOkAfRC )
  1250. {
  1251. rc = _cmFtError(kDspProcFailFtRC,p, "The audio file open failed on '%s'.",cmStringNullGuard(pp->audioFn));
  1252. goto errLabel;
  1253. }
  1254. p->progSmpCnt = afInfo.frameCnt;
  1255. p->progSmpIdx = 0;
  1256. f.srate = afInfo.srate;
  1257. f.smpCnt = afInfo.frameCnt;
  1258. f.fftSmpCnt = cmNearPowerOfTwo( (unsigned)floor( pp->wndMs * f.srate / 1000 ) );
  1259. f.binCnt = f.fftSmpCnt / 2 + 1;
  1260. f.hopSmpCnt = f.fftSmpCnt / pp->hopFact;
  1261. f.frmCnt = 0;
  1262. f.skipFrmCnt = 0;
  1263. f.floorFrmCnt = 0;
  1264. // verify that the audio channel index is valid
  1265. if( pp->chIdx >= afInfo.chCnt )
  1266. {
  1267. rc = _cmFtError(kChIdxInvalidFtRC,p,"The channel index (%i) specified for audio file '%s' is greater than the audio file channel count.",pp->chIdx,pp->audioFn,afInfo.chCnt );
  1268. goto errLabel;
  1269. }
  1270. // initialize the audio file reader
  1271. if( cmAudioFileRdOpen( p->afRdPtr, f.hopSmpCnt, pp->audioFn, pp->chIdx, 0, cmInvalidIdx ) != cmOkRC )
  1272. {
  1273. rc = _cmFtError(kDspProcFailFtRC,p, "The audio file reader open failed.");
  1274. goto errLabel;
  1275. }
  1276. // get the range of sample values from this audio file for later normalization
  1277. if( cmAudioFileRdMinMaxMean( p->afRdPtr, pp->chIdx, &minSmp, &maxSmp, &meanSmp ) != cmOkRC )
  1278. {
  1279. rc = _cmFtError(kDspProcFailFtRC,p,"Audio file min/max/mean processing failed on the audio file:'%s'.",cmStringNullGuard(pp->audioFn));
  1280. goto errLabel;
  1281. }
  1282. audioSigNormFact = cmMax( fabs(minSmp), fabs(maxSmp) );
  1283. // allocate anlArray[]
  1284. anlArray = cmMemAllocZ( _cmFtAnl_t, pp->attrCnt );
  1285. summArray = cmMemAllocZ( cmFtSumm_t, pp->attrCnt );
  1286. // iniitalize anlArray[]
  1287. for(i=0; i<pp->attrCnt; ++i)
  1288. {
  1289. _cmFtAnl_t* a = anlArray + i;
  1290. a->ap = pp->attrArray + i;
  1291. a->lp = _cmFtIdToLabelPtr(a->ap->id);
  1292. a->sr = summArray + i;
  1293. a->sr->id = a->lp->id;
  1294. }
  1295. // sort anlArray[] into init and exec order
  1296. qsort( anlArray, pp->attrCnt, sizeof(anlArray[0]), _cmFtAnlCompare);
  1297. // set the anlArray[i] source attribute pointer for secondary features (feat's based on other feat's)
  1298. for(i=0; i<pp->attrCnt; ++i)
  1299. if( anlArray[i].lp->srcId != kInvalidFtId )
  1300. {
  1301. unsigned j;
  1302. for(j=0; j<pp->attrCnt; ++j)
  1303. if( i!=j && anlArray[j].lp->id == anlArray[i].lp->srcId )
  1304. {
  1305. anlArray[i].sp = anlArray + j;
  1306. break;
  1307. }
  1308. assert( j != pp->attrCnt );
  1309. }
  1310. // initialize the feature extractors and allocate feature vector memory
  1311. if((rc = _cmFtProcInit(p, &f, pp, anlArray)) != kOkFtRC )
  1312. goto errLabel;
  1313. // create the output frame file
  1314. if( cmFrameFileCreate(&ffH, pp->featFn, f.srate, &p->ctx ) != kOkFfRC )
  1315. {
  1316. rc = _cmFtError( kFrameFileFailFtRC, p, "The feature file '%s' could not be created.",cmStringNullGuard(pp->featFn));
  1317. goto errLabel;
  1318. }
  1319. // read the next block of samples from the audio file
  1320. for(frameIdx=0,sampleIdx=0; cmAudioFileRdRead(p->afRdPtr) != cmEofRC; sampleIdx+=f.hopSmpCnt )
  1321. {
  1322. cmSample_t aV[ p->afRdPtr->outN ];
  1323. cmSample_t* audV = aV;
  1324. cmSample_t rms;
  1325. p->progSmpIdx = sampleIdx;
  1326. // if this audio buffer is fully or paritally marked as 'skip'
  1327. if( _cmFtZeroSkipSamples( pp, p->afRdPtr->outV, p->afRdPtr->outN, p->afRdPtr->curFrmIdx - p->afRdPtr->lastReadFrmCnt ) )
  1328. {
  1329. ++f.skipFrmCnt;
  1330. continue;
  1331. }
  1332. // if the audio buffer is zero - skip it
  1333. if((rms = cmVOS_RMS( p->afRdPtr->outV, p->afRdPtr->outN, p->afRdPtr->outN )) < floorThreshAmpl )
  1334. {
  1335. ++f.floorFrmCnt;
  1336. continue;
  1337. }
  1338. // normalize the audio
  1339. if( pp->normAudioFl )
  1340. cmVOS_MultVVS( audV, p->afRdPtr->outN, p->afRdPtr->outV, audioSigNormFact );
  1341. else
  1342. audV = p->afRdPtr->outV;
  1343. // execute the phase vocoder
  1344. if( cmPvAnlExec(p->pvocPtr, audV, p->afRdPtr->outN )==false )
  1345. continue;
  1346. // create an empty frame
  1347. if( cmFrameFileFrameCreate( ffH, kFrameTypeFtId, kFrameStreamFtId, sampleIdx, 0 ) != kOkFfRC )
  1348. {
  1349. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame creation failed for frame index:%i on frame file:'%s'.",frameIdx,cmStringNullGuard(pp->featFn));
  1350. goto errLabel;
  1351. }
  1352. // include the incomplete file header record in the first frame
  1353. if( frameIdx == 0 )
  1354. if((rc = _cmFtWriteFileHdr( p, &f, pp, ffH, summArray, false )) != kOkFtRC )
  1355. goto errLabel;
  1356. // execute each of the feature extractors and store the result
  1357. if((rc = _cmFtProcExec(p, &f, pp, ffH, anlArray, audV )) != kOkFtRC )
  1358. goto errLabel;
  1359. // close and write the current frame
  1360. if( cmFrameFileFrameClose( ffH ) != kOkFfRC )
  1361. {
  1362. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame write failed for frame index:%i on frame file:'%s'.",frameIdx,cmStringNullGuard(pp->featFn));
  1363. goto errLabel;
  1364. }
  1365. ++frameIdx;
  1366. }
  1367. f.frmCnt = frameIdx;
  1368. // update the rawAvgV[] for each feature
  1369. if( f.frmCnt > 0 )
  1370. {
  1371. // sum feature value into a->sr->rawAvgV[]
  1372. if(( rc = _cmFtProcFile(p,ffH,pp,anlArray, _cmFtProcRawMinMaxSum )) != kOkFtRC )
  1373. goto errLabel;
  1374. // complete the a->sr->rawAvgV[] calc
  1375. for(i=0; i<pp->attrCnt; ++i)
  1376. cmVOR_DivVS( anlArray[i].sr->rawAvgV, anlArray[i].ap->cnt, f.frmCnt );
  1377. // calc sum of squared diff into a->sr->rawSdvV[]
  1378. if(( rc = _cmFtProcFile(p,ffH,pp,anlArray, _cmFtProcRawStdDev )) != kOkFtRC )
  1379. goto errLabel;
  1380. // complete calc of std-dev
  1381. for(i=0; i<pp->attrCnt; ++i)
  1382. {
  1383. _cmFtAnl_t* a = anlArray + i;
  1384. cmVOR_DivVS( a->sr->rawSdvV, a->ap->cnt, f.frmCnt );
  1385. cmVOR_PowVS( a->sr->rawSdvV, a->ap->cnt, 0.5 );
  1386. }
  1387. // make the initial normalized vector calculation (min/max/sum)
  1388. if(( rc = _cmFtProcFile(p,ffH,pp,anlArray, _cmFtProcNormMinMaxSum )) != kOkFtRC )
  1389. goto errLabel;
  1390. // complete the a->sr->normAvgV[] calculation
  1391. for(i=0; i<pp->attrCnt; ++i)
  1392. cmVOR_DivVS( anlArray[i].sr->normAvgV, anlArray[i].ap->cnt, f.frmCnt );
  1393. // calc squared of squared diff into a->sr->normSdvV[]
  1394. if(( rc = _cmFtProcFile(p,ffH,pp,anlArray, _cmFtNormStdDev )) != kOkFtRC )
  1395. goto errLabel;
  1396. // complete the calc of norm std-dev
  1397. for(i=0; i<pp->attrCnt; ++i)
  1398. {
  1399. _cmFtAnl_t* a = anlArray + i;
  1400. cmVOR_DivVS( a->sr->normSdvV, a->ap->cnt, f.frmCnt );
  1401. cmVOR_PowVS( a->sr->normSdvV, a->ap->cnt, 0.5 );
  1402. }
  1403. }
  1404. //-------------------------------------------------------------------------
  1405. //
  1406. // rewrite the updated feature file header into the first frame
  1407. //
  1408. // rewind to the first frame
  1409. if( cmFrameFileRewind( ffH ) != kOkFfRC )
  1410. {
  1411. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file rewind failed during header update on '%s'.", cmStringNullGuard(pp->featFn));
  1412. goto errLabel;
  1413. }
  1414. // make the first frame current and load it into the cmFrameFiles current frame buffer
  1415. if( cmFrameFileFrameLoadNext( ffH, kFrameTypeFtId, kFrameStreamFtId, NULL ) != kOkFfRC )
  1416. {
  1417. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file load next frme failed during header update on '%s'.", cmStringNullGuard(pp->featFn));
  1418. goto errLabel;
  1419. }
  1420. // copy the update header record into the current frame buffer
  1421. if((rc = _cmFtWriteFileHdr(p, &f, pp, ffH, summArray, true)) != kOkFtRC )
  1422. goto errLabel;
  1423. // write the updated frame back to disk
  1424. if( cmFrameFileFrameUpdate( ffH ) != kOkFfRC )
  1425. {
  1426. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file frame update failed during header update on '%s'.", cmStringNullGuard(pp->featFn));
  1427. goto errLabel;
  1428. }
  1429. errLabel:
  1430. if( anlArray != NULL )
  1431. for(i=0; i<pp->attrCnt; ++i)
  1432. cmMemPtrFree(&anlArray[i].v);
  1433. cmMemPtrFree(&anlArray);
  1434. cmMemPtrFree(&summArray);
  1435. cmFrameFileClose(&ffH);
  1436. return rc;
  1437. }
  1438. cmFtRC_t cmFtAnalyze( cmFtH_t h )
  1439. {
  1440. cmFtRC_t rc = kOkFtRC;
  1441. _cmFt_t* p = _cmFtHandleToPtr(h);
  1442. unsigned i;
  1443. for(i=0; i<p->paramCnt; ++i)
  1444. {
  1445. p->progParamIdx = i;
  1446. p->progPassIdx = 0;
  1447. if((rc = cmFtAnalyzeFile(h,p->paramArray+i)) != kOkFtRC )
  1448. break;
  1449. }
  1450. return rc;
  1451. }
  1452. const char* cmFtAnalyzeProgress( cmFtH_t h, unsigned* passPtr, cmReal_t* percentPtr )
  1453. {
  1454. _cmFt_t* p = _cmFtHandleToPtr(h);
  1455. if( percentPtr != NULL )
  1456. *percentPtr = 0;
  1457. if( passPtr != NULL)
  1458. *passPtr = 0;
  1459. if( p->progParamIdx == cmInvalidIdx )
  1460. return NULL;
  1461. if( percentPtr != NULL && p->progSmpCnt > 0 )
  1462. *percentPtr = 100.0 * p->progSmpIdx / p->progSmpCnt;
  1463. if( passPtr != NULL )
  1464. *passPtr = p->progPassIdx;
  1465. return p->paramArray[ p->progParamIdx ].audioFn;
  1466. }
  1467. cmFtRC_t _cmFtReaderClose( _cmFtFile_t* fp )
  1468. {
  1469. cmFtRC_t rc = kOkFtRC;
  1470. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1471. /*
  1472. unsigned i;
  1473. if( cmPlviewIsValid( p->plvH ) )
  1474. for(i=0; i<fp->info.param.attrCnt; ++i)
  1475. if( cmPlviewFreeSource( p->plvH, fp->descArray[i].ap->id ) != kOkPlvRC )
  1476. {
  1477. rc = _cmFtError( kPlviewFailFtRC, p, "Plview source free failed on feature '%s'.",fp->descArray[i].lp->label);
  1478. goto errLabel;
  1479. }
  1480. */
  1481. if( cmFrameFileClose( &fp->ffH ) != kOkFfRC )
  1482. {
  1483. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file close failed.");
  1484. goto errLabel;
  1485. }
  1486. cmMemPtrFree(&fp->descArray);
  1487. cmMemPtrFree(&fp->info.summArray);
  1488. cmMemPtrFree(&fp->info.param.skipArray);
  1489. cmMemPtrFree(&fp->info.param.attrArray);
  1490. cmMemPtrFree(&fp->hdrBuf);
  1491. cmMemPtrFree(&fp);
  1492. errLabel:
  1493. return rc;
  1494. }
  1495. /*
  1496. // Fill buf[rowCnt,colCnt] with data from the source submatrix located at rowIdx,colIdx.
  1497. // Return the count of elements actually copied into buf[].
  1498. unsigned cmFtPlviewSrcFunc( void* userPtr, unsigned srcId, unsigned binIdx, unsigned frmIdx, cmReal_t* buf, unsigned binCnt, unsigned frmCnt )
  1499. {
  1500. assert(userPtr != NULL );
  1501. _cmFtFile_t* fp = (_cmFtFile_t*)userPtr;
  1502. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1503. cmFfRC_t rc = kOkFfRC;
  1504. const cmFfFrame_t* frmDescPtr = NULL;
  1505. const cmFfMtx_t* mtxDescPtr = NULL;
  1506. unsigned i;
  1507. // seek to frmIdx
  1508. if((rc = cmFrameFileSeek( fp->ffH, frmIdx )) != kOkFfRC )
  1509. {
  1510. rc = _cmFtError( kFrameFileFailFtRC, p, "Seek failed on plot data cmcess.");
  1511. goto errLabel;
  1512. }
  1513. // load the frame
  1514. for(i=0; i<frmCnt && (rc=cmFrameFileFrameLoadNext(fp->ffH, kFrameTypeFtId, kFrameStreamFtId, &frmDescPtr))==kOkFfRC; ++i)
  1515. {
  1516. const cmReal_t* dp;
  1517. const _cmFtLabel_t* lp = _cmFtIdToLabelPtr(srcId);
  1518. assert(lp != NULL);
  1519. if((dp = cmFrameFileMtxReal( fp->ffH, lp->ffMtxId, lp->ffUnitsId, kRealFmtId, &mtxDescPtr)) == NULL )
  1520. {
  1521. rc = _cmFtError( kFrameFileFailFtRC, p, "Mtx data cmcess failed on plot data access.");
  1522. goto errLabel;
  1523. }
  1524. cmVOR_Copy( buf + (i*binCnt), binCnt, dp );
  1525. return binCnt;
  1526. }
  1527. errLabel:
  1528. return 0;
  1529. }
  1530. */
  1531. cmFtRC_t cmFtReaderOpen(cmFtH_t h, cmFtFileH_t* hp, const char* featFn, const cmFtInfo_t** infoPtrPtr )
  1532. {
  1533. cmFfRC_t ffRC = kOkFfRC;
  1534. const cmFfFile_t* fileDescPtr = NULL;
  1535. const cmFfFrame_t* frameDescPtr = NULL;
  1536. cmFtRC_t rc = kOkFtRC;
  1537. _cmFt_t* p = _cmFtHandleToPtr(h);
  1538. _cmFtFile_t* fp = cmMemAllocZ( _cmFtFile_t, 1 );
  1539. const cmFfMtx_t* mp = NULL;
  1540. void* buf = NULL;
  1541. unsigned i,j;
  1542. //cmPlvSrc_t plvSrc;
  1543. if( infoPtrPtr != NULL )
  1544. *infoPtrPtr = NULL;
  1545. fp->h = h;
  1546. fp->ffH = cmFrameFileNullHandle;
  1547. // open the frame file
  1548. if( cmFrameFileOpen(&fp->ffH, featFn, &p->ctx, &fileDescPtr ) != kOkFfRC )
  1549. {
  1550. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file open failed.");
  1551. goto errLabel;
  1552. }
  1553. // load the first frame
  1554. if((ffRC = cmFrameFileFrameLoadNext( fp->ffH, kFrameTypeFtId, kFrameStreamFtId, &frameDescPtr )) != kOkFfRC )
  1555. {
  1556. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file load failed.");
  1557. goto errLabel;
  1558. }
  1559. // read the file header
  1560. if((buf = cmFrameFileMtxBlob(fp->ffH, kDataMId, kNoUnitsUId, &mp )) == NULL )
  1561. {
  1562. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file header read failed.");
  1563. goto errLabel;
  1564. }
  1565. // parse the file header into fp->infoPtr
  1566. if((rc = _cmDeserializeFileHdr( p, fp, buf, mp->rowCnt*mp->colCnt )) != kOkFtRC )
  1567. goto errLabel;
  1568. fp->descArray = cmMemAllocZ( _cmFtDesc_t, fp->info.param.attrCnt );
  1569. // for each feature
  1570. for(i=0; i<fp->info.param.attrCnt; ++i)
  1571. {
  1572. // setup the desc array
  1573. fp->descArray[i].ap = fp->info.param.attrArray + i;
  1574. fp->descArray[i].lp = _cmFtIdToLabelPtr( fp->descArray[i].ap->id );
  1575. // sync descArray[] to summArray[] by matching the feature id's
  1576. for(j=0; j<fp->info.param.attrCnt; ++j)
  1577. if( fp->info.summArray[j].id == fp->descArray[i].lp->id )
  1578. {
  1579. fp->descArray[i].sr = fp->info.summArray + j;
  1580. break;
  1581. }
  1582. /*
  1583. plvSrc.id = fp->descArray[i].lp->id;
  1584. plvSrc.label = fp->descArray[i].lp->label;
  1585. plvSrc.rn = fp->descArray[i].ap->cnt;
  1586. plvSrc.cn = fp->info.frmCnt;
  1587. plvSrc.userPtr = fp;
  1588. plvSrc.srcFuncPtr = cmFtPlviewSrcFunc;
  1589. plvSrc.worldExts.xMin = 0;
  1590. plvSrc.worldExts.xMax = fp->info.frmCnt;
  1591. plvSrc.worldExts.yMin = fp->descArray[i].ap->cnt <= 1 ? fp->descArray[i].sr->rawMin : 0;
  1592. plvSrc.worldExts.yMax = fp->descArray[i].ap->cnt <= 1 ? fp->descArray[i].sr->rawMax : fp->descArray[i].ap->cnt;
  1593. if( cmPlviewIsValid( p->plvH ) )
  1594. if( cmPlviewAllocSource( p->plvH, &plvSrc ) != kOkPlvRC )
  1595. {
  1596. rc = _cmFtError( kPlviewFailFtRC, p, "Plview source allocattion failed for feature '%s'.",fp->descArray[i].lp->label);
  1597. goto errLabel;
  1598. }
  1599. */
  1600. }
  1601. // rewind to the frame file
  1602. if((ffRC = cmFrameFileRewind( fp->ffH )) != kOkFfRC )
  1603. {
  1604. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file rewind failed.");
  1605. goto errLabel;
  1606. }
  1607. hp->h = fp;
  1608. if( infoPtrPtr != NULL )
  1609. *infoPtrPtr = &fp->info;
  1610. errLabel:
  1611. if( rc != kOkFtRC )
  1612. _cmFtReaderClose(fp);
  1613. return rc;
  1614. }
  1615. cmFtRC_t cmFtReaderClose( cmFtFileH_t* hp )
  1616. {
  1617. cmFtRC_t rc = kOkFtRC;
  1618. if( cmFtReaderIsValid(*hp) == false )
  1619. return rc;
  1620. _cmFtFile_t* fp = _cmFtFileHandleToPtr(*hp);
  1621. if((rc = _cmFtReaderClose(fp)) != kOkFtRC )
  1622. goto errLabel;
  1623. hp->h = NULL;
  1624. errLabel:
  1625. return rc;
  1626. }
  1627. bool cmFtReaderIsValid( cmFtFileH_t h )
  1628. { return h.h != NULL; }
  1629. unsigned cmFtReaderFeatCount( cmFtFileH_t h )
  1630. {
  1631. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1632. return fp->info.param.attrCnt;
  1633. }
  1634. unsigned cmFtReaderFeatId( cmFtFileH_t h, unsigned index )
  1635. {
  1636. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1637. assert( index < fp->info.param.attrCnt );
  1638. return fp->descArray[index].lp->id;
  1639. }
  1640. cmFtRC_t cmFtReaderRewind( cmFtFileH_t h )
  1641. {
  1642. cmFtRC_t rc = kOkFtRC;
  1643. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1644. if(cmFrameFileRewind( fp->ffH ) != kOkFfRC )
  1645. {
  1646. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1647. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file advance failed.");
  1648. goto errLabel;
  1649. }
  1650. errLabel:
  1651. return rc;
  1652. }
  1653. cmFtRC_t cmFtReaderSeek( cmFtFileH_t h, unsigned frmIdx )
  1654. {
  1655. cmFtRC_t rc = kOkFtRC;
  1656. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1657. if( cmFrameFileSeek( fp->ffH, kFrameStreamFtId, frmIdx ) != kOkFtRC )
  1658. {
  1659. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1660. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file seek failed.");
  1661. goto errLabel;
  1662. }
  1663. errLabel:
  1664. return rc;
  1665. }
  1666. cmFtRC_t cmFtReaderAdvance( cmFtFileH_t h, cmFtFrameDesc_t* fdp )
  1667. {
  1668. cmFfRC_t ffRC = kOkFfRC;
  1669. const cmFfFrame_t* frameDescPtr = NULL;
  1670. cmFtRC_t rc = kOkFtRC;
  1671. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1672. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1673. if((ffRC = cmFrameFileFrameLoadNext( fp->ffH, kFrameTypeFtId, kFrameStreamFtId, &frameDescPtr )) != kOkFfRC )
  1674. {
  1675. if( ffRC == kEofFfRC )
  1676. rc = kEofFtRC;
  1677. else
  1678. {
  1679. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame file advance failed.");
  1680. goto errLabel;
  1681. }
  1682. }
  1683. errLabel:
  1684. if( fdp != NULL )
  1685. {
  1686. if( rc == kOkFtRC )
  1687. {
  1688. fdp->smpIdx = frameDescPtr->tm.sampleIdx;
  1689. fdp->frmIdx = cmFrameFileFrameLoadedIndex(fp->ffH);
  1690. }
  1691. else
  1692. {
  1693. fdp->smpIdx = cmInvalidIdx;
  1694. fdp->frmIdx = cmInvalidIdx;
  1695. }
  1696. }
  1697. return rc;
  1698. }
  1699. cmReal_t* cmFtReaderData( cmFtFileH_t h, unsigned id, unsigned* cntPtr )
  1700. {
  1701. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1702. cmReal_t* dp = NULL;
  1703. _cmFtLabel_t* lp = _cmFtIdToLabelPtr(id);
  1704. const cmFfMtx_t* mdp = NULL;
  1705. assert( lp != NULL );
  1706. if( cntPtr != NULL )
  1707. *cntPtr = 0;
  1708. if((dp = cmFrameFileMtxReal(fp->ffH,lp->ffMtxId,lp->ffUnitsId,&mdp)) == NULL )
  1709. return NULL;
  1710. if( cntPtr != NULL )
  1711. *cntPtr = mdp->rowCnt * mdp->colCnt;
  1712. return dp;
  1713. }
  1714. cmFtRC_t cmFtReaderCopy( cmFtFileH_t h, unsigned featId, unsigned frmIdx, cmReal_t* buf, unsigned frmCnt, unsigned elePerFrmCnt, unsigned* outEleCntPtr )
  1715. {
  1716. cmFtRC_t rc = kOkFtRC;
  1717. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1718. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1719. _cmFtLabel_t* lp = _cmFtIdToLabelPtr(featId);
  1720. assert( lp != NULL );
  1721. if( cmFrameFileMtxLoadReal( fp->ffH, kFrameStreamFtId, lp->ffMtxId, lp->ffUnitsId, frmIdx, frmCnt, buf, frmCnt*elePerFrmCnt, outEleCntPtr ) != kOkFfRC )
  1722. {
  1723. rc = _cmFtError( kFrameFileFailFtRC, p, "Frame load matrix failed.");
  1724. goto errLabel;
  1725. }
  1726. errLabel:
  1727. return rc;
  1728. }
  1729. cmFtRC_t cmFtReaderMultiSetup( cmFtFileH_t h, cmFtMulti_t* multiArray, unsigned multiCnt, unsigned* featVectEleCntPtr )
  1730. {
  1731. cmFtRC_t rc = kOkFtRC;
  1732. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1733. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1734. unsigned i,j;
  1735. assert( featVectEleCntPtr != NULL );
  1736. *featVectEleCntPtr = 0;
  1737. for(i=0; i<multiCnt; ++i)
  1738. {
  1739. const _cmFtLabel_t* lp;
  1740. // locate the static parameters assoc'd with this feature
  1741. if((lp = _cmFtIdToLabelPtr( multiArray[i].featId )) == NULL )
  1742. {
  1743. rc = _cmFtError( kInvalidFeatIdFtRC, p, "Invalid feature id %i.",multiArray[i].featId);
  1744. goto errLabel;
  1745. }
  1746. // locate the feature info assoc'd with this file
  1747. for(j=0; j<fp->info.param.attrCnt; ++j)
  1748. {
  1749. if( fp->info.param.attrArray[j].id == multiArray[i].featId )
  1750. {
  1751. // if the multi ele cnt is -1 then use all avail ele's
  1752. if( multiArray[i].cnt == -1 )
  1753. multiArray[i].cnt = fp->info.param.attrArray[j].cnt;
  1754. // verify the feature element count
  1755. if( fp->info.param.attrArray[j].cnt < multiArray[i].cnt )
  1756. {
  1757. rc = _cmFtError( kInvalidFeatIdFtRC, p, "The requested feature element count %i is greater than the actual feature count %i in feature file '%s'.",multiArray[i].cnt,fp->info.param.attrArray[j].cnt,fp->info.param.featFn);
  1758. goto errLabel;
  1759. }
  1760. break;
  1761. }
  1762. }
  1763. // verify that the feature attr recd was found
  1764. if( j >= fp->info.param.attrCnt )
  1765. {
  1766. rc = _cmFtError( kInvalidFeatIdFtRC, p, "The feature %i was not used in the feature file '%s'.",multiArray[i].featId,fp->info.param.featFn);
  1767. goto errLabel;
  1768. }
  1769. multiArray[i].id0 = lp->ffMtxId;
  1770. multiArray[i].id1 = lp->ffUnitsId;
  1771. *featVectEleCntPtr += multiArray[i].cnt;
  1772. }
  1773. errLabel:
  1774. return rc;
  1775. }
  1776. cmFtRC_t cmFtReaderMultiData( cmFtFileH_t h, const cmFtMulti_t* multiArray, unsigned multiCnt, cmReal_t* outV, unsigned outN )
  1777. {
  1778. cmFtRC_t rc = kOkFtRC;
  1779. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1780. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1781. unsigned i;
  1782. unsigned n = 0;
  1783. for(i=0; i<multiCnt; ++i)
  1784. {
  1785. const cmFfMtx_t* mdp = NULL;
  1786. const cmFtMulti_t* m = multiArray + i;
  1787. cmReal_t* dp = NULL;
  1788. if((dp = cmFrameFileMtxReal(fp->ffH,m->id0,m->id1,&mdp)) == NULL )
  1789. {
  1790. rc = _cmFtError( kFrameFileFailFtRC, p, "Matrix read failed on feature file '%s'.", fp->info.param.featFn);
  1791. goto errLabel;
  1792. }
  1793. assert(m->cnt <= mdp->rowCnt*mdp->colCnt);
  1794. assert(n + m->cnt <= outN );
  1795. cmVOR_Copy(outV, m->cnt, dp );
  1796. outV += m->cnt;
  1797. n += m->cnt;
  1798. }
  1799. errLabel:
  1800. return rc;
  1801. }
  1802. cmFtSumm_t* _cmFtReaderFindSummPtr( _cmFtFile_t* fp, unsigned featId )
  1803. {
  1804. unsigned i;
  1805. const cmFtParam_t* pp = &fp->info.param;
  1806. for(i=0; i<pp->attrCnt; ++i)
  1807. if( fp->info.summArray[i].id == featId )
  1808. return fp->info.summArray + i;
  1809. return NULL;
  1810. }
  1811. cmFtRC_t cmFtReaderReport( cmFtFileH_t h, unsigned featId )
  1812. {
  1813. cmFtRC_t rc = kOkFtRC;
  1814. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1815. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1816. const cmFtInfo_t* ip = &fp->info;
  1817. const cmFtParam_t* pp = &ip->param;
  1818. unsigned i;
  1819. cmFtSumm_t* s;
  1820. _cmFtPrint(p,"ch:%i audio:%s\n",pp->chIdx,pp->audioFn);
  1821. _cmFtPrint(p,"wndMs:%f hopFact:%i normAudioFl:%i \n",pp->wndMs,pp->hopFact,pp->normAudioFl);
  1822. _cmFtPrint(p,"skip:\n");
  1823. for(i=0; i<pp->skipCnt; ++i)
  1824. _cmFtPrint(p,"idx:%10i cnt:%10i \n",pp->skipArray[i].smpIdx,pp->skipArray[i].smpCnt);
  1825. _cmFtPrint(p,"attr:\n");
  1826. for(i=0; i<pp->attrCnt; ++i)
  1827. _cmFtPrint(p,"cnt:%4i normFl:%i raw min:%12f max:%12f norm min:%12f max:%12f %s\n",pp->attrArray[i].cnt,pp->attrArray[i].normFl,fp->descArray[i].sr->rawMin,fp->descArray[i].sr->rawMax,fp->descArray[i].sr->normMin,fp->descArray[i].sr->normMax,cmFtFeatIdToLabel(pp->attrArray[i].id));
  1828. _cmFtPrint(p,"frmCnt:%i skipFrmCnt:%i floorFrmCnt:%i srate:%f fftSmpCnt:%i hopSmpCnt:%i binCnt:%i binHz:%f\n",ip->frmCnt,ip->skipFrmCnt,ip->floorFrmCnt,ip->srate,ip->fftSmpCnt,ip->hopSmpCnt,ip->binCnt,ip->srate/ip->fftSmpCnt);
  1829. if( featId != kInvalidFtId )
  1830. {
  1831. if((s = _cmFtReaderFindSummPtr(fp,featId)) == NULL )
  1832. return _cmFtError( kInvalidFeatIdFtRC, p, "The feature id %i is not valid.",featId);
  1833. _cmFtPrint(p,"feature:%s \n",_cmFtIdToLabelPtr(featId)->label);
  1834. cmVOR_PrintLE("raw min: ", &p->ctx.rpt, 1, s->cnt, s->rawMinV );
  1835. cmVOR_PrintLE("raw max: ", &p->ctx.rpt, 1, s->cnt, s->rawMaxV );
  1836. cmVOR_PrintLE("raw avg: ", &p->ctx.rpt, 1, s->cnt, s->rawAvgV );
  1837. cmVOR_PrintLE("raw sdv: ", &p->ctx.rpt, 1, s->cnt, s->rawSdvV );
  1838. cmVOR_PrintLE("norm min:", &p->ctx.rpt, 1, s->cnt, s->normMinV );
  1839. cmVOR_PrintLE("norm max:", &p->ctx.rpt, 1, s->cnt, s->normMaxV );
  1840. cmVOR_PrintLE("norm avg:", &p->ctx.rpt, 1, s->cnt, s->normAvgV );
  1841. cmVOR_PrintLE("norm sdv:", &p->ctx.rpt, 1, s->cnt, s->normSdvV );
  1842. }
  1843. return rc;
  1844. }
  1845. cmFtRC_t cmFtReaderReportFn( cmFtH_t h, const cmChar_t* fn, unsigned featId )
  1846. {
  1847. cmFtRC_t rc0,rc1;
  1848. cmFtFileH_t fh = cmFtFileNullHandle;
  1849. if((rc0 = cmFtReaderOpen(h,&fh,fn,NULL)) != kOkFtRC )
  1850. return rc0;
  1851. rc0 = cmFtReaderReport(fh,featId);
  1852. rc1 = cmFtReaderClose(&fh);
  1853. return rc0 != kOkFtRC ? rc0 : rc1;
  1854. }
  1855. cmFtRC_t cmFtReaderReportFeature( cmFtFileH_t h, unsigned featId, unsigned frmIdx, unsigned frmCnt )
  1856. {
  1857. cmFtRC_t rc = kOkFtRC;
  1858. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1859. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1860. unsigned i;
  1861. cmFtFrameDesc_t ftFrameDesc;
  1862. if((rc = cmFtReaderSeek(h,frmIdx)) != kOkFtRC )
  1863. return rc;
  1864. for(i=0; i<frmCnt && (rc=cmFtReaderAdvance(h,&ftFrameDesc))==kOkFtRC; ++i)
  1865. {
  1866. cmReal_t* dp = NULL;
  1867. unsigned cnt = 0;
  1868. if(( dp = cmFtReaderData(h,featId,&cnt)) == NULL )
  1869. break;
  1870. // print first element
  1871. _cmFtPrint(p,"%f ",*dp);
  1872. }
  1873. return rc;
  1874. }
  1875. cmFtRC_t cmFtReaderToBinary(cmFtFileH_t h, unsigned featId, unsigned frmIdx, unsigned frmCnt, const cmChar_t* outFn )
  1876. {
  1877. cmFtRC_t rc = kOkFtRC;
  1878. _cmFtFile_t* fp = _cmFtFileHandleToPtr(h);
  1879. _cmFt_t* p = _cmFtHandleToPtr(fp->h);
  1880. unsigned i;
  1881. cmFtFrameDesc_t ftFrameDesc;
  1882. cmFileH_t fH;
  1883. unsigned hdr[] = {0,0,0};
  1884. unsigned maxCnt = 0;
  1885. // create the output file
  1886. if( cmFileOpen(&fH,outFn,kWriteFileFl,p->err.rpt) != kOkFileRC )
  1887. return _cmFtError( kFileFailFtRC, p, "Feature to binary file '%s' failed on output file creation.",outFn);
  1888. // if frmCnt is not valid then set it to all frames past frmIdx
  1889. if( frmCnt == cmInvalidCnt )
  1890. frmCnt = cmFrameFileFrameCount(fp->ffH,kFrameStreamFtId);
  1891. // validate frm idx
  1892. if( frmIdx > frmCnt )
  1893. {
  1894. rc = _cmFtError( kInvalidFrmIdxFtRC,p,"Frame index %i is invalid for frame count = %i.",frmIdx,frmCnt);
  1895. goto errLabel;
  1896. }
  1897. // seek to the location first output frame
  1898. if((rc = cmFtReaderSeek(h,frmIdx)) != kOkFtRC )
  1899. goto errLabel;
  1900. hdr[0] = frmCnt; // count of frames
  1901. hdr[1] = 0; // count of elements per frame
  1902. hdr[2] = sizeof(cmReal_t);
  1903. // write the file header
  1904. if( cmFileWrite(fH,hdr,sizeof(hdr)) != kOkFileRC )
  1905. {
  1906. rc = _cmFtError( kFileFailFtRC,p,"The output file header write failed.");
  1907. goto errLabel;
  1908. }
  1909. // iterate through each frame
  1910. for(i=0; i<frmCnt && (rc=cmFtReaderAdvance(h,&ftFrameDesc))==kOkFtRC; ++i)
  1911. {
  1912. cmReal_t* dp = NULL;
  1913. unsigned cnt = 0;
  1914. // get a pointer to the data for the requested feature
  1915. if(( dp = cmFtReaderData(h,featId,&cnt)) == NULL )
  1916. break;
  1917. // write the count of elements in this frame
  1918. if( cmFileWrite(fH,&cnt,sizeof(cnt)) != kOkFileRC )
  1919. {
  1920. rc = _cmFtError( kFileFailFtRC,p,"Output write failed on frame header at frame index %i.",i);
  1921. goto errLabel;
  1922. }
  1923. // write the data
  1924. if( cmFileWrite(fH,dp,sizeof(*dp)*cnt) != kOkFileRC )
  1925. {
  1926. rc = _cmFtError( kFileFailFtRC,p,"Output data write failed on frame index %i.",i);
  1927. goto errLabel;
  1928. }
  1929. if( cnt > maxCnt )
  1930. maxCnt = cnt;
  1931. }
  1932. // rewind to the beginning of the file
  1933. if( cmFileSeek(fH,kBeginFileFl,0) != kOkFileRC )
  1934. {
  1935. rc = _cmFtError( kFileFailFtRC,p,"Output file rewind failed.");
  1936. goto errLabel;
  1937. }
  1938. // rewrite the header
  1939. hdr[1] = maxCnt;
  1940. if( cmFileWrite(fH,hdr,sizeof(hdr)) != kOkFileRC )
  1941. {
  1942. rc = _cmFtError( kFileFailFtRC,p,"The output file header re-write failed.");
  1943. goto errLabel;
  1944. }
  1945. errLabel:
  1946. if( cmFileIsValid(fH) )
  1947. if( cmFileClose(&fH) != kOkFileRC )
  1948. _cmFtError( kFileFailFtRC,p,"Output file close failed.");
  1949. return rc;
  1950. }
  1951. cmFtRC_t cmFtReaderToBinaryFn(cmFtH_t h, const cmChar_t* fn, unsigned featId, unsigned frmIdx, unsigned frmCnt, const cmChar_t* outFn )
  1952. {
  1953. cmFtRC_t rc = kOkFtRC;
  1954. cmFtFileH_t fH = cmFtFileNullHandle;
  1955. if((rc = cmFtReaderOpen(h,&fH,fn,NULL)) != kOkFtRC )
  1956. return rc;
  1957. rc = cmFtReaderToBinary(fH,featId,frmIdx,frmCnt,outFn);
  1958. cmFtRC_t rc1 = cmFtReaderClose(&fH);
  1959. return rc==kOkFtRC ? rc1 : rc;
  1960. }