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.

cmFeatFile.c 73KB

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