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

cmFeatFile.c 73KB

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