libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }