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

cmFeatFile.c 73KB

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