libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmSdb.c 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmLex.h"
  10. #include "cmCsv.h"
  11. #include "cmSdb.h"
  12. #include "cmText.h"
  13. #include "cmMath.h"
  14. #include "cmTime.h"
  15. #include "cmMidi.h"
  16. #include "cmVectOpsTemplateMain.h"
  17. #include "cmAudioFile.h"
  18. #include "cmFileSys.h"
  19. typedef enum
  20. {
  21. kUuidColIdx,
  22. kBaseUuidColIdx,
  23. kChIdxColIdx,
  24. kObiColIdx,
  25. kIbiColIdx,
  26. kIeiColIdx,
  27. kOeiColIdx,
  28. kSrcColIdx,
  29. kMidiColIdx,
  30. kInstrColIdx,
  31. kSrateColIdx,
  32. kChCntColIdx,
  33. kNotesColIdx,
  34. kAfnColIdx,
  35. kInvalidColIdx
  36. } cmSdbColIdx_t;
  37. struct cmSdb_str;
  38. typedef struct cmSdbSeqBlk_str
  39. {
  40. cmSdbSeqEvent_t* eV;
  41. unsigned cnt;
  42. struct cmSdbSeqBlk_str* link;
  43. } cmSdbSeqBlk_t;
  44. typedef struct cmSdbSeq_str
  45. {
  46. struct cmSdb_str* p;
  47. cmSdbSeqBlk_t* blocks;
  48. cmSdbSeqBlk_t* ebp;
  49. unsigned cnt; // total count of events in all blocks
  50. unsigned chCnt; // max(chIdx)+1 of all events
  51. double minDurSec; // min dur of all events
  52. double maxDurSec; // max dur of all events
  53. struct cmSdbSeq_str* link;
  54. } cmSdbSeq_t;
  55. typedef struct cmSdbRspBlk_str
  56. {
  57. unsigned* indexV; // indexV[ cmSdb_t.blkIdxAllocCnt ]
  58. unsigned cnt; // count of indexes used
  59. struct cmSdbRspBlk_str* link; // cmSdbRsp_t.blocks link
  60. } cmSdbRspBlk_t;
  61. typedef struct cmSdbRsp_str
  62. {
  63. struct cmSdb_str* p; //
  64. cmSdbRspBlk_t* blocks; // first block ptr
  65. cmSdbRspBlk_t* ebp; // end block ptr
  66. unsigned cnt; // total count of indexes
  67. struct cmSdbRsp_str* link; // cmSdb_t.responses link
  68. } cmSdbRsp_t;
  69. typedef struct cmSdb_str
  70. {
  71. cmCtx_t ctx;
  72. cmLHeapH_t lhH;
  73. cmCsvH_t csvH;
  74. cmSdbEvent_t* eV;
  75. unsigned eN;
  76. cmChar_t* audioDir;
  77. unsigned blkIdxAllocCnt;
  78. unsigned blkEvtAllocCnt;
  79. cmSdbRsp_t* responses;
  80. cmSdbSeq_t* seqs;
  81. } cmSdb_t;
  82. cmSdbH_t cmSdbNullHandle = cmSTATIC_NULL_HANDLE;
  83. cmSdbResponseH_t cmSdbResponseNullHandle = cmSTATIC_NULL_HANDLE;
  84. cmSdbSeqH_t cmSdbSeqNullHandle = cmSTATIC_NULL_HANDLE;
  85. cmSdb_t* _cmSdbHandleToPtr( cmSdbH_t h )
  86. {
  87. cmSdb_t* p = (cmSdb_t*)h.h;
  88. assert( p != NULL );
  89. return p;
  90. }
  91. void _cmSdbRspFree( cmSdbRsp_t* );
  92. cmSdbRC_t _cmSdbSeqFree( cmSdbSeq_t* );
  93. cmSdbRC_t _cmSdbDestroy( cmSdb_t* p )
  94. {
  95. cmSdbRC_t rc = kOkSdbRC;
  96. if( cmCsvFinalize(&p->csvH) != kOkCsvRC )
  97. rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file finalize failed.");
  98. while( p->responses != NULL )
  99. _cmSdbRspFree(p->responses);
  100. while( p->seqs != NULL )
  101. _cmSdbSeqFree(p->seqs);
  102. cmLHeapDestroy(&p->lhH);
  103. cmMemFree(p);
  104. return rc;
  105. }
  106. cmSdbRC_t cmSdbCreate( cmCtx_t* ctx, cmSdbH_t* hp, const cmChar_t* csvFn, const cmChar_t* audioDir )
  107. {
  108. cmSdbRC_t rc;
  109. if((rc = cmSdbDestroy(hp)) != kOkSdbRC )
  110. return rc;
  111. cmSdb_t* p = cmMemAllocZ(cmSdb_t,1);
  112. p->ctx = *ctx;
  113. p->blkIdxAllocCnt = 1024;
  114. p->blkEvtAllocCnt = 1024;
  115. cmErrSetup(&p->ctx.err,&ctx->rpt,"sdb");
  116. if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8192,ctx)) == false )
  117. {
  118. rc = cmErrMsg(&p->ctx.err,kLHeapFailSdbRC,"Linked heap mgr. allocation failed.");
  119. goto errLabel;
  120. }
  121. hp->h = p;
  122. if( csvFn != NULL )
  123. if((rc = cmSdbLoad(*hp,csvFn,audioDir)) != kOkSdbRC )
  124. goto errLabel;
  125. errLabel:
  126. if( rc != kOkSdbRC )
  127. _cmSdbDestroy(p);
  128. return rc;
  129. }
  130. cmSdbRC_t cmSdbDestroy( cmSdbH_t* hp )
  131. {
  132. cmSdbRC_t rc = kOkSdbRC;
  133. if( hp==NULL || cmSdbIsValid(*hp)==false )
  134. return rc;
  135. cmSdb_t* p = _cmSdbHandleToPtr(*hp);
  136. if((rc = _cmSdbDestroy(p)) != kOkSdbRC )
  137. return rc;
  138. hp->h = NULL;
  139. return rc;
  140. }
  141. bool cmSdbIsValid( cmSdbH_t h )
  142. { return h.h != NULL; }
  143. cmSdbRC_t _cmSdbSyntaxError(cmSdb_t* p, const cmChar_t* csvFn, unsigned rowIdx, unsigned colIdx, const cmChar_t* colLabel )
  144. {
  145. return cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"A syntax error was found at row %i col %i (label:%s) in '%s'.",rowIdx+1,colIdx+1,cmStringNullGuard(colLabel),cmStringNullGuard(csvFn));
  146. }
  147. cmSdbRC_t cmSdbLoad( cmSdbH_t h, const cmChar_t* csvFn, const cmChar_t* audioDir )
  148. {
  149. cmSdbRC_t rc = kOkSdbRC;
  150. unsigned i;
  151. cmSdb_t* p = _cmSdbHandleToPtr(h);
  152. if( cmCsvInitializeFromFile(&p->csvH, csvFn, 0, &p->ctx ) != kOkCsvRC )
  153. {
  154. rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file load fail on '%s'.",cmStringNullGuard(csvFn));
  155. goto errLabel;
  156. }
  157. p->eN = cmCsvRowCount(p->csvH)-1;
  158. // release all the memory held by the linked heap
  159. cmLHeapClear(p->lhH,true);
  160. p->eV = cmLhAllocZ(p->lhH,cmSdbEvent_t,p->eN);
  161. for(i=0; rc==kOkSdbRC && i<p->eN; ++i)
  162. {
  163. unsigned rowIdx = i+1;
  164. if((p->eV[i].uuid = cmCsvCellUInt(p->csvH,rowIdx,kUuidColIdx)) == UINT_MAX )
  165. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kUuidColIdx,"uuid");
  166. if((p->eV[i].baseUuid = cmCsvCellUInt(p->csvH,rowIdx,kBaseUuidColIdx)) == UINT_MAX )
  167. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kBaseUuidColIdx,"baseUuid");
  168. if((p->eV[i].chIdx = cmCsvCellUInt(p->csvH,rowIdx,kChIdxColIdx)) == UINT_MAX )
  169. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChIdxColIdx,"chIdx");
  170. else
  171. p->eV[i].chIdx -= 1; // CSV channel index is 1 based
  172. if((p->eV[i].obi = cmCsvCellUInt(p->csvH,rowIdx,kObiColIdx)) == UINT_MAX )
  173. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kObiColIdx,"obi");
  174. else
  175. p->eV[i].obi -= 1;
  176. if((p->eV[i].ibi = cmCsvCellUInt(p->csvH,rowIdx,kIbiColIdx)) == UINT_MAX )
  177. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIbiColIdx,"ibi");
  178. else
  179. p->eV[i].ibi -= 1;
  180. if((p->eV[i].iei = cmCsvCellUInt(p->csvH,rowIdx,kIeiColIdx)) == UINT_MAX )
  181. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIeiColIdx,"obi");
  182. else
  183. p->eV[i].iei -= 1;
  184. if((p->eV[i].oei = cmCsvCellUInt(p->csvH,rowIdx,kOeiColIdx)) == UINT_MAX )
  185. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kOeiColIdx,"ibi");
  186. else
  187. p->eV[i].oei -= 1;
  188. if((p->eV[i].src = cmCsvCellText(p->csvH,rowIdx,kSrcColIdx)) == NULL )
  189. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrcColIdx,"src");
  190. if((p->eV[i].midi = cmCsvCellInt(p->csvH,rowIdx,kMidiColIdx)) == INT_MAX )
  191. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kMidiColIdx,"midi");
  192. if((p->eV[i].instr = cmCsvCellText(p->csvH,rowIdx,kInstrColIdx)) == NULL )
  193. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kInstrColIdx,"instr");
  194. if((p->eV[i].srate = cmCsvCellUInt(p->csvH,rowIdx,kSrateColIdx)) == UINT_MAX )
  195. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrateColIdx,"srate");
  196. if((p->eV[i].chCnt = cmCsvCellUInt(p->csvH,rowIdx,kChCntColIdx)) == UINT_MAX )
  197. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChCntColIdx,"chCnt");
  198. cmCsvCell_t* c;
  199. if((c = cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx)) == NULL )
  200. {
  201. rc = cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"Syntax Error: No 'notes' or 'audio file name' field for row %i in '%s'.",rowIdx+1,cmStringNullGuard(csvFn));
  202. goto errLabel;
  203. }
  204. // count the number of 'notes'
  205. unsigned nn = 0;
  206. for(; c->rowPtr != NULL; c=c->rowPtr)
  207. ++nn;
  208. if( nn > 0 )
  209. {
  210. unsigned k = 0;
  211. // allocate the 'notes' ptr array - the last entry is set to NULL.
  212. p->eV[i].notesV = cmLhAllocZ(p->lhH,const cmChar_t*,nn+1);
  213. // read each note
  214. for(c=cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx); c!=NULL&&c->rowPtr!=NULL; c=c->rowPtr,++k)
  215. if(( p->eV[i].notesV[k] = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+k)) == NULL )
  216. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+k,"notes");
  217. assert(k==nn);
  218. }
  219. // read the audio file name
  220. if((p->eV[i].afn = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+nn)) == NULL )
  221. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+nn,"afn");
  222. }
  223. // store the audio directory
  224. if( cmTextLength(audioDir) )
  225. p->audioDir = cmLhAllocStr(p->lhH,audioDir);
  226. else
  227. {
  228. cmLhFree(p->lhH,&p->audioDir);
  229. p->audioDir = NULL;
  230. }
  231. errLabel:
  232. return rc;
  233. }
  234. cmSdbRC_t cmSdbSyncChPairs( cmSdbH_t h )
  235. {
  236. cmSdbRC_t rc = kOkSdbRC;
  237. cmSdb_t* p = _cmSdbHandleToPtr(h);
  238. unsigned i;
  239. // for each multi-channel event
  240. for(i=0; i<p->eN; ++i)
  241. if(p->eV[i].chCnt > 1 )
  242. {
  243. const cmSdbEvent_t* ep = p->eV + i;
  244. unsigned iV[ep->chCnt];
  245. unsigned j,k;
  246. // load iV[] with the event indexes of the channel pairs
  247. for(j=0,k=0; j<p->eN && k<ep->chCnt; ++j)
  248. if( p->eV[j].baseUuid == ep->baseUuid )
  249. {
  250. assert( p->eV[j].chIdx < ep->chCnt );
  251. iV[p->eV[j].chIdx] = j;
  252. ++k;
  253. }
  254. if( k != ep->chCnt )
  255. rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
  256. else
  257. {
  258. unsigned mobi = ep->obi;
  259. unsigned mibi = ep->ibi;
  260. unsigned miei = ep->iei;
  261. unsigned moei = ep->oei;
  262. // get the min onsets and max offsets
  263. for(j=0; j<ep->chCnt; ++j)
  264. {
  265. mobi = cmMin(mobi,p->eV[ iV[j] ].obi);
  266. mibi = cmMin(mibi,p->eV[ iV[j] ].ibi);
  267. miei = cmMax(miei,p->eV[ iV[j] ].iei);
  268. moei = cmMax(moei,p->eV[ iV[j] ].oei);
  269. }
  270. // set the onsets to the min onset / offsets to max offsets
  271. for(j=0; j<ep->chCnt; ++j)
  272. {
  273. p->eV[ iV[j] ].obi = mobi;
  274. p->eV[ iV[j] ].ibi = mibi;
  275. p->eV[ iV[j] ].iei = miei;
  276. p->eV[ iV[j] ].oei = moei;
  277. }
  278. }
  279. }
  280. return rc;
  281. }
  282. const cmSdbEvent_t* _cmSdbEvent( cmSdb_t* p, unsigned uuid )
  283. {
  284. unsigned i;
  285. for(i=0; i<p->eN; ++i)
  286. if( p->eV[i].uuid == uuid )
  287. return p->eV + i;
  288. return NULL;
  289. }
  290. const cmSdbEvent_t* cmSdbEvent( cmSdbH_t h, unsigned uuid )
  291. {
  292. cmSdb_t* p = _cmSdbHandleToPtr(h);
  293. return _cmSdbEvent(p,uuid);
  294. }
  295. //================================================================================================================================
  296. cmSdbRsp_t* _cmSdbRspHandleToPtr( cmSdbResponseH_t h )
  297. {
  298. cmSdbRsp_t* p = (cmSdbRsp_t*)h.h;
  299. assert( p != NULL );
  300. return p;
  301. }
  302. void _cmSdbRspBlkFree( cmSdb_t* p, cmSdbRspBlk_t* bp )
  303. {
  304. cmLhFree(p->lhH, bp->indexV);
  305. cmLhFree(p->lhH, bp);
  306. }
  307. cmSdbRspBlk_t* _cmSdbRspBlkUnlink( cmSdbRsp_t* rp, cmSdbRspBlk_t* bp )
  308. {
  309. cmSdbRspBlk_t* dp = rp->blocks;
  310. cmSdbRspBlk_t* pp = NULL;
  311. for(; dp!=NULL; dp=dp->link)
  312. {
  313. if( dp == bp )
  314. {
  315. if( pp == NULL )
  316. rp->blocks = dp->link;
  317. else
  318. pp->link = dp->link;
  319. return bp;
  320. }
  321. pp = dp;
  322. }
  323. assert(0);
  324. return NULL;
  325. }
  326. void _cmSdbRspInsertIndex( cmSdb_t* p, cmSdbRsp_t* rp, unsigned evtIndex )
  327. {
  328. if( rp->ebp == NULL || rp->ebp->cnt == p->blkIdxAllocCnt )
  329. {
  330. cmSdbRspBlk_t* bp = cmLhAllocZ(p->lhH,cmSdbRspBlk_t,1);
  331. bp->indexV = cmLhAllocZ(p->lhH,unsigned,p->blkIdxAllocCnt);
  332. if( rp->ebp != NULL )
  333. rp->ebp->link = bp;
  334. if( rp->blocks == NULL )
  335. rp->blocks = bp;
  336. rp->ebp = bp;
  337. }
  338. assert( rp->ebp!=NULL && rp->ebp->cnt < p->blkIdxAllocCnt );
  339. rp->ebp->indexV[ rp->ebp->cnt++ ] = evtIndex;
  340. rp->cnt += 1;
  341. }
  342. cmSdbRsp_t* _cmSdbRspUnlink( cmSdbRsp_t* rp )
  343. {
  344. cmSdb_t* p = rp->p;
  345. cmSdbRsp_t* dp = p->responses;
  346. cmSdbRsp_t* pp = NULL;
  347. for(; dp!=NULL; dp=dp->link)
  348. {
  349. if( dp == rp )
  350. {
  351. if( pp == NULL )
  352. p->responses = dp->link;
  353. else
  354. pp->link = dp->link;
  355. return rp;
  356. }
  357. pp = dp;
  358. }
  359. assert( 0 );
  360. return NULL;
  361. }
  362. void _cmSdbRspFree( cmSdbRsp_t* rp )
  363. {
  364. _cmSdbRspUnlink(rp);
  365. while( rp->blocks != NULL )
  366. {
  367. cmSdbRspBlk_t* np = rp->blocks->link;
  368. cmSdbRspBlk_t* bp;
  369. if((bp = _cmSdbRspBlkUnlink(rp,rp->blocks)) != NULL )
  370. _cmSdbRspBlkFree(rp->p,bp);
  371. rp->blocks = np;
  372. }
  373. cmLhFree(rp->p->lhH,rp);
  374. }
  375. cmSdbRsp_t* _cmSdbRspAlloc( cmSdb_t* p )
  376. {
  377. cmSdbRsp_t* rp = cmLhAllocZ(p->lhH,cmSdbRsp_t,1);
  378. rp->p = p;
  379. rp->link = p->responses;
  380. p->responses = rp;
  381. return rp;
  382. }
  383. // Compare 'label' to every string in tV[i] and return true if any comparision is a match.
  384. // If 'subFlV[i]' is set then 'label' must only contain tV[i] as a substring to match.
  385. // If 'negFlV[i]' is set then return true if any comparision is a mismatch.
  386. bool _cmSdbSelectText( const cmSdbEvent_t* r, const cmChar_t** tV, const bool* subFlV, const bool* negFlV, const cmChar_t* label )
  387. {
  388. unsigned i;
  389. if( label == NULL )
  390. return false;
  391. if( tV == NULL )
  392. return true;
  393. for(i=0; tV[i]!=NULL; ++i)
  394. {
  395. bool matchFl = false;
  396. if( subFlV[i] )
  397. matchFl = strstr(label,tV[i]) != NULL;
  398. else
  399. matchFl = strcmp(tV[i],label)==0;
  400. if( negFlV[i] )
  401. matchFl = !matchFl;
  402. if(matchFl)
  403. return true;
  404. }
  405. return false;
  406. }
  407. unsigned _cmSdbStrVectCnt( const cmChar_t** v )
  408. {
  409. unsigned n = 0;
  410. unsigned i = 0;
  411. if( v == NULL )
  412. return 0;
  413. for(i=0; v[i]!=NULL; ++i)
  414. ++n;
  415. return n;
  416. }
  417. void _cmSdbStrVectFlags( const cmChar_t** v, bool* sV, bool* nV )
  418. {
  419. unsigned i = 0;
  420. if( v == NULL )
  421. return;
  422. for(i=0; v[i]!=NULL; ++i)
  423. {
  424. nV[i] = false;
  425. sV[i] = false;
  426. if( strncmp(v[i],"*!",2)==0 || strncmp(v[i],"!*",2)==0)
  427. {
  428. sV[i] = nV[i] = true;
  429. v[i] += 2;
  430. }
  431. else
  432. {
  433. if( strncmp(v[i],"!",1)==0 )
  434. {
  435. nV[i] = true;
  436. v[i] += 1;
  437. }
  438. if( strncmp(v[i],"*",1)==0 )
  439. {
  440. sV[i] = true;
  441. v[i] += 1;
  442. }
  443. }
  444. }
  445. }
  446. cmSdbRC_t cmSdbSelect(
  447. cmSdbH_t h,
  448. double srate,
  449. const cmChar_t** instrV,
  450. const cmChar_t** srcV,
  451. const cmChar_t** notesV,
  452. const unsigned* pitchV,
  453. double minDurSec,
  454. double maxDurSec,
  455. unsigned minChCnt,
  456. cmSdbResponseH_t* rhp )
  457. {
  458. cmSdbRC_t rc;
  459. if((rc = cmSdbResponseFree(rhp)) != kOkSdbRC )
  460. return rc;
  461. cmSdb_t* p = _cmSdbHandleToPtr(h);
  462. cmSdbRsp_t* rp = _cmSdbRspAlloc(p);
  463. unsigned i;
  464. // get the length of each string vector
  465. unsigned srcN = _cmSdbStrVectCnt(srcV);
  466. unsigned insN = _cmSdbStrVectCnt(instrV);
  467. unsigned notN = _cmSdbStrVectCnt(notesV);
  468. // allocate flag vectors
  469. bool srcSubFlV[ srcN ];
  470. bool srcNegFlV[ srcN ];
  471. bool insSubFlV[ insN ];
  472. bool insNegFlV[ insN ];
  473. bool notSubFlV[ notN ];
  474. bool notNegFlV[ notN ];
  475. // fill the flag vectors
  476. _cmSdbStrVectFlags(srcV, srcSubFlV,srcNegFlV);
  477. _cmSdbStrVectFlags(instrV,insSubFlV,insNegFlV);
  478. _cmSdbStrVectFlags(notesV,notSubFlV,notNegFlV);
  479. for(i=0; i<p->eN; ++i)
  480. {
  481. const cmSdbEvent_t* r = p->eV + i;
  482. double durSec = (double)r->srate * (r->oei - r->obi);
  483. unsigned j;
  484. if( srate!=0 && srate!=r->srate )
  485. continue;
  486. if( durSec < minDurSec || (maxDurSec!=0 && maxDurSec < durSec) )
  487. continue;
  488. if( minChCnt!=0 && r->chCnt > minChCnt )
  489. continue;
  490. if( !_cmSdbSelectText(r,srcV,srcSubFlV,srcNegFlV,r->src) )
  491. continue;
  492. if( !_cmSdbSelectText(r,instrV,insSubFlV,insNegFlV,r->instr) )
  493. continue;
  494. if( pitchV != NULL )
  495. {
  496. for(j=0; pitchV[j]!=kInvalidMidiPitch; ++j)
  497. if( pitchV[j] == r->midi )
  498. break;
  499. if( pitchV[j] != r->midi )
  500. continue;
  501. }
  502. if( r->notesV != NULL )
  503. {
  504. for(j=0; r->notesV[j]!=NULL; ++j)
  505. if( _cmSdbSelectText(r,notesV,notSubFlV,notNegFlV,r->notesV[j]) == true )
  506. break;
  507. if( r->notesV[j]==NULL )
  508. continue;
  509. }
  510. _cmSdbRspInsertIndex(p,rp,i);
  511. }
  512. rhp->h = rp;
  513. if(rc != kOkSdbRC )
  514. _cmSdbRspFree(rp);
  515. return rc;
  516. }
  517. cmSdbRC_t _cmSdbSelectChPairs( cmSdb_t* p, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp )
  518. {
  519. cmSdbRC_t rc;
  520. if((rc = cmSdbResponseFree(rhp)) != kOkSdbRC )
  521. return rc;
  522. cmSdbRsp_t* rp = _cmSdbRspAlloc(p);
  523. unsigned i;
  524. // for each channel of this event
  525. for(i=0; i<ep->chCnt; ++i)
  526. {
  527. // if i channel is not the known events channel
  528. if( ep->chIdx != i )
  529. {
  530. unsigned j;
  531. // examine each record
  532. for(j=0; j<p->eN; ++j)
  533. // if eV[j] shares a baseUuid but is on a different channel than *ep ...
  534. if( p->eV[j].baseUuid == ep->baseUuid && p->eV[j].chIdx==i )
  535. {
  536. // .. then a match has been found
  537. _cmSdbRspInsertIndex(p,rp,j);
  538. break;
  539. }
  540. if( j== p->eN )
  541. {
  542. rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
  543. }
  544. }
  545. }
  546. rhp->h = rp;
  547. return rc;
  548. }
  549. cmSdbRC_t cmSdbSelectChPairs( cmSdbH_t h, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp )
  550. {
  551. cmSdb_t* p = _cmSdbHandleToPtr(h);
  552. return _cmSdbSelectChPairs( p, ep,rhp );
  553. }
  554. unsigned cmSdbResponseCount( cmSdbResponseH_t rh )
  555. {
  556. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  557. return rp->cnt;
  558. }
  559. const cmSdbEvent_t* cmSdbResponseEvent( cmSdbResponseH_t rh, unsigned index )
  560. {
  561. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  562. if( index >= rp->cnt )
  563. return NULL;
  564. cmSdbRspBlk_t* bp = rp->blocks;
  565. unsigned i;
  566. for(i=0; bp!=NULL; i+=bp->cnt,bp=bp->link)
  567. if( i <= index && index < (i + bp->cnt) )
  568. return rp->p->eV + bp->indexV[index-i];
  569. cmErrMsg(&rp->p->ctx.err,kInvalidRspIdxSdbRC,"Invalid query response index=%i.",index);
  570. return NULL;
  571. }
  572. bool cmSdbResponseIsValid( cmSdbResponseH_t rh )
  573. { return rh.h != NULL; }
  574. cmSdbRC_t cmSdbResponseFree( cmSdbResponseH_t* rhp )
  575. {
  576. cmSdbRC_t rc = kOkSdbRC;
  577. if( rhp == NULL || cmSdbResponseIsValid(*rhp)==false )
  578. return rc;
  579. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(*rhp);
  580. _cmSdbRspFree(rp);
  581. rhp->h = NULL;
  582. return rc;
  583. }
  584. void cmSdbResponsePrint( cmSdbResponseH_t rh, cmRpt_t* rpt )
  585. {
  586. unsigned n = cmSdbResponseCount(rh);
  587. unsigned i;
  588. for(i=0; i<n; ++i)
  589. {
  590. const cmSdbEvent_t* e = cmSdbResponseEvent(rh,i);
  591. if( e != NULL )
  592. cmRptPrintf(rpt,"%6i %6i %2i %12i %12i %12i %12i %2i %6i %2i %10s %15s\n",
  593. e->uuid,e->baseUuid,e->chIdx,e->obi,e->ibi,e->iei,e->oei,e->midi,e->srate,e->chCnt,
  594. cmStringNullGuard(e->src), cmStringNullGuard(e->instr) );
  595. }
  596. }
  597. //================================================================================================================================
  598. cmSdbSeq_t* _cmSdbSeqHandleToPtr( cmSdbSeqH_t sh )
  599. {
  600. cmSdbSeq_t* sp = (cmSdbSeq_t*)sh.h;
  601. assert(sp !=NULL );
  602. return sp;
  603. }
  604. void _cmSdbSeqInsertEvent( cmSdbSeq_t* sp, unsigned uuid, unsigned chIdx, double begSecs, double durSecs )
  605. {
  606. cmSdb_t* p = sp->p;
  607. // if no block has been allocated or the current block is full
  608. if( sp->ebp == NULL || sp->ebp->cnt >= p->blkEvtAllocCnt )
  609. {
  610. // allocate a new seq block recd
  611. cmSdbSeqBlk_t* bp = cmLhAllocZ(sp->p->lhH,cmSdbSeqBlk_t,1);
  612. // allocate a seq evt array
  613. bp->eV = cmLhAllocZ(sp->p->lhH,cmSdbSeqEvent_t,p->blkEvtAllocCnt);
  614. // link in the block recd
  615. if( sp->ebp != NULL )
  616. sp->ebp->link = bp;
  617. if( sp->blocks == NULL )
  618. {
  619. sp->blocks = bp;
  620. sp->minDurSec = durSecs;
  621. sp->maxDurSec = durSecs;
  622. }
  623. sp->ebp = bp;
  624. }
  625. assert( sp->ebp != NULL && sp->ebp->cnt < p->blkEvtAllocCnt );
  626. // get the next seq evt recd to fill
  627. cmSdbSeqEvent_t* ep = sp->ebp->eV + sp->ebp->cnt;
  628. // fill the seq evt recd
  629. ep->uuid = uuid;
  630. ep->begSec = begSecs;
  631. ep->durSec = durSecs;
  632. ep->outChIdx = chIdx;
  633. ep->gain = 1.0;
  634. // incr the seq evt cnt
  635. sp->ebp->cnt += 1;
  636. sp->cnt += 1;
  637. sp->chCnt = cmMax(sp->chCnt,chIdx+1);
  638. sp->minDurSec = cmMin(sp->minDurSec,durSecs);
  639. sp->maxDurSec = cmMax(sp->maxDurSec,durSecs);
  640. }
  641. // unlink a sequence record from p->seqs.
  642. cmSdbSeq_t* _cmSdbSeqUnlink( cmSdbSeq_t* sp )
  643. {
  644. cmSdb_t* p = sp->p;
  645. cmSdbSeq_t* cp = p->seqs;
  646. cmSdbSeq_t* pp = NULL;
  647. for(; cp!=NULL; cp=cp->link)
  648. {
  649. if( cp == sp )
  650. {
  651. if( pp == NULL )
  652. p->seqs = sp->link;
  653. else
  654. pp->link = sp->link;
  655. return sp;
  656. }
  657. pp = cp;
  658. }
  659. assert(0);
  660. return NULL;
  661. }
  662. // free a sequence record
  663. cmSdbRC_t _cmSdbSeqFree( cmSdbSeq_t* sp )
  664. {
  665. cmSdb_t* p = sp->p;
  666. // unlink this seq. record from p->seqs
  667. if( _cmSdbSeqUnlink(sp) == NULL )
  668. return cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"Sequence unlink failed.");
  669. // release the seq blocks held by the sequence
  670. while( sp->blocks != NULL )
  671. {
  672. cmSdbSeqBlk_t* np = sp->blocks->link;
  673. cmLhFree(p->lhH,sp->blocks->eV);
  674. cmLhFree(p->lhH,sp->blocks);
  675. sp->blocks = np;
  676. }
  677. cmLhFree(p->lhH,sp);
  678. return kOkSdbRC;
  679. }
  680. // allocate a sequence record
  681. cmSdbSeq_t* _cmSdbSeqAlloc( cmSdb_t* p )
  682. {
  683. cmSdbSeq_t* sp = cmLhAllocZ(p->lhH,cmSdbSeq_t,1);
  684. sp->p = p;
  685. sp->link = p->seqs;
  686. p->seqs = sp;
  687. return sp;
  688. }
  689. cmSdbRC_t _cmSdbStoreSeqEvent(
  690. cmSdb_t* p,
  691. cmSdbSeq_t* sp,
  692. cmSdbResponseH_t rh,
  693. unsigned ri,
  694. unsigned seqChCnt,
  695. double begSecs,
  696. double limitEvtDurSecs,
  697. double* durSecsRef )
  698. {
  699. cmSdbRC_t rc = kOkSdbRC;
  700. double maxEvtDurSecs = 0;
  701. // retrieve the event record
  702. const cmSdbEvent_t* ep;
  703. if((ep = cmSdbResponseEvent(rh,ri)) == NULL )
  704. {
  705. rc = cmErrMsg(&p->ctx.err,kRspEvtNotFoundSdbRC,"A response event could not be found during random sequence generation.");
  706. goto errLabel;
  707. }
  708. cmSdbResponseH_t rh0 = cmSdbResponseNullHandle;
  709. unsigned rn0 = 0;
  710. unsigned ci = 0;
  711. // locate the channel pairs for 'ep'.
  712. if( seqChCnt>1 && ep->chCnt>1 )
  713. {
  714. if( _cmSdbSelectChPairs(p, ep, &rh0 ) != kOkSdbRC )
  715. {
  716. rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"A response event could not find channel pairs during random sequence generation.");
  717. goto errLabel;
  718. }
  719. rn0 = cmSdbResponseCount(rh0);
  720. }
  721. while(1)
  722. {
  723. // calculate the event duration
  724. double durSecs = (double)(ep->oei - ep->obi)/ep->srate;
  725. // truncate the event if it is longer than limitEvtDurSecs
  726. if( limitEvtDurSecs!=0 && durSecs>limitEvtDurSecs )
  727. durSecs = cmMin(limitEvtDurSecs,durSecs);
  728. // track the longest event
  729. maxEvtDurSecs = cmMax(maxEvtDurSecs,durSecs);
  730. // store the sequence event
  731. _cmSdbSeqInsertEvent(sp,ep->uuid,ci,begSecs,durSecs);
  732. // incr the output ch index
  733. ++ci;
  734. // if all the out ch's are filled or the sample event has no more channels
  735. if( ci >= seqChCnt || ci-1 >= rn0 )
  736. break;
  737. // get the next channel pair
  738. if((ep = cmSdbResponseEvent(rh0,ci-1)) == NULL )
  739. {
  740. rc = cmErrMsg(&p->ctx.err,kRspEvtNotFoundSdbRC,"A channel pair response event could not be found during random sequence generation.");
  741. goto errLabel;
  742. }
  743. } // for each sample event pair
  744. errLabel:
  745. if( durSecsRef != NULL )
  746. *durSecsRef = maxEvtDurSecs;
  747. cmSdbResponseFree(&rh0);
  748. return rc;
  749. }
  750. cmSdbRC_t cmSdbSeqRand(
  751. cmSdbResponseH_t rh,
  752. unsigned seqDurSecs,
  753. unsigned seqChCnt,
  754. unsigned minEvtPerSec,
  755. unsigned maxEvtPerSec,
  756. cmSdbSeqH_t* shp )
  757. {
  758. cmSdbRC_t rc;
  759. if((rc = cmSdbSeqFree(shp)) != kOkSdbRC )
  760. return rc;
  761. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  762. cmSdb_t* p = rp->p;
  763. cmSdbSeq_t* sp = _cmSdbSeqAlloc(p);
  764. if( seqChCnt < 1 )
  765. return cmErrMsg(&p->ctx.err,kInvalidArgSdbRC,"The random sequence generator channel count parameter must be non-zero.");
  766. if( seqDurSecs <= 0 )
  767. return cmErrMsg(&p->ctx.err,kInvalidArgSdbRC,"The random sequence generator signal duration must be greater than 0.");
  768. if( maxEvtPerSec < minEvtPerSec )
  769. return cmErrMsg(&p->ctx.err,kInvalidArgSdbRC,"The random sequence generator max. events per second must be greater or equal to the min. events per second.");
  770. if((rc = cmSdbSeqFree(shp)) != kOkSdbRC )
  771. return rc;
  772. unsigned rn = cmSdbResponseCount(rh);
  773. unsigned sec;
  774. for(sec=0; sec<seqDurSecs; sec+=1 )
  775. {
  776. // calcuate the number of events to initiate during this second
  777. unsigned en = cmRandUInt(minEvtPerSec,maxEvtPerSec);
  778. unsigned ei;
  779. for(ei=0; ei<en; ++ei)
  780. {
  781. // select an event index
  782. unsigned ri = cmRandUInt(0,rn-1);
  783. // double select a start time for this event
  784. double begSecs = sec + cmRandDouble(0.0,1.0);
  785. double maxEvtDurSecs = 0;
  786. if((rc = _cmSdbStoreSeqEvent(p,sp,rh,ri,seqChCnt,begSecs,maxEvtDurSecs,NULL)) != kOkSdbRC )
  787. goto errLabel;
  788. } // for each event init'd during this second
  789. } // for each second
  790. shp->h = sp;
  791. errLabel:
  792. if( rc != kOkSdbRC )
  793. _cmSdbSeqFree(sp);
  794. return rc;
  795. }
  796. cmSdbRC_t cmSdbSeqSerial(
  797. cmSdbResponseH_t rh,
  798. unsigned seqChCnt,
  799. double gapSec,
  800. double maxEvtDurSec,
  801. cmSdbSeqH_t* shp )
  802. {
  803. cmSdbRC_t rc;
  804. if((rc = cmSdbSeqFree(shp)) != kOkSdbRC )
  805. return rc;
  806. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  807. cmSdb_t* p = rp->p;
  808. cmSdbSeq_t* sp = _cmSdbSeqAlloc(p);
  809. unsigned n = cmSdbResponseCount(rh);
  810. double begSecs = 0;
  811. unsigned ri;
  812. for(ri=0; ri<n; ++ri)
  813. {
  814. double durSecs = 0;
  815. if((rc = _cmSdbStoreSeqEvent(p,sp,rh,ri,seqChCnt,begSecs,maxEvtDurSec,&durSecs)) != kOkSdbRC )
  816. goto errLabel;
  817. // offset to next event
  818. begSecs += durSecs + gapSec;
  819. }
  820. shp->h = sp;
  821. errLabel:
  822. if(rc != kOkSdbRC )
  823. _cmSdbSeqFree(sp);
  824. return rc;
  825. }
  826. cmSdbRC_t cmSdbSeqChord(
  827. cmSdbResponseH_t* rhp,
  828. unsigned rn,
  829. unsigned seqChCnt,
  830. unsigned maxEvtDurSec,
  831. cmSdbSeqH_t* shp )
  832. {
  833. cmSdbRC_t rc = kOkSdbRC;
  834. assert( shp != NULL );
  835. if( rn == 0 )
  836. return rc;
  837. cmSdbResponseH_t rh = rhp[0];
  838. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  839. cmSdb_t* p = rp->p;
  840. cmSdbSeq_t* sp = _cmSdbSeqAlloc(p);
  841. unsigned i;
  842. if((rc = cmSdbSeqFree(shp)) != kOkSdbRC )
  843. return rc;
  844. // for each chord note
  845. for(i=0; i<rn; ++i)
  846. {
  847. // get the query response handle for this note
  848. rh = rhp[i];
  849. rp = _cmSdbRspHandleToPtr(rh);
  850. // verify that all query responses were drawn from the same cmSdbH_t handle.
  851. if( rp->p != p )
  852. {
  853. rc = cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"All chord query response handle must be derived from the same cmSdbH_t handle.");
  854. goto errLabel;
  855. }
  856. // pick one event at random from the response
  857. unsigned n = cmSdbResponseCount(rh);
  858. unsigned rei = cmRandUInt(0,n-1);
  859. // all notes start at time: 0.0.
  860. double begSecs = 0.0;
  861. // store the sequence event
  862. if((rc = _cmSdbStoreSeqEvent(p,sp,rh,rei,seqChCnt,begSecs,maxEvtDurSec,NULL)) != kOkSdbRC )
  863. goto errLabel;
  864. }
  865. shp->h = sp;
  866. errLabel:
  867. if(rc != kOkSdbRC )
  868. _cmSdbSeqFree(sp);
  869. return rc;
  870. }
  871. bool cmSdbSeqIsValid( cmSdbSeqH_t sh )
  872. { return sh.h != NULL; }
  873. cmSdbRC_t cmSdbSeqFree( cmSdbSeqH_t* shp )
  874. {
  875. cmSdbRC_t rc = kOkSdbRC;
  876. if( shp==NULL || cmSdbSeqIsValid(*shp)==false )
  877. return rc;
  878. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(*shp);
  879. if((rc = _cmSdbSeqFree(sp)) != kOkSdbRC )
  880. return rc;
  881. shp->h = NULL;
  882. return rc;
  883. }
  884. unsigned cmSdbSeqCount( cmSdbSeqH_t sh )
  885. {
  886. if( cmSdbSeqIsValid(sh)==false )
  887. return 0;
  888. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  889. return sp->cnt;
  890. }
  891. const cmSdbSeqEvent_t* cmSdbSeqEvent( cmSdbSeqH_t sh, unsigned index )
  892. {
  893. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  894. if( index >= sp->cnt )
  895. return NULL;
  896. cmSdbSeqBlk_t* bp = sp->blocks;
  897. unsigned i;
  898. for(i=0; bp!=NULL; i+=bp->cnt,bp=bp->link)
  899. if( i <= index && index < (i + bp->cnt) )
  900. return bp->eV + index-i;
  901. cmErrMsg(&sp->p->ctx.err,kInvalidSeqIdxSdbRC,"Invalid sequence event index=%i.",index);
  902. return NULL;
  903. }
  904. const cmSdbEvent_t* cmSdbSeqSdbEvent( cmSdbSeqH_t sh, unsigned index )
  905. {
  906. const cmSdbSeqEvent_t* ep;
  907. if((ep = cmSdbSeqEvent(sh,index)) == NULL )
  908. return NULL;
  909. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  910. return _cmSdbEvent(sp->p,ep->uuid);
  911. }
  912. double cmSdbSeqDurSeconds( cmSdbSeqH_t sh )
  913. {
  914. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  915. cmSdbSeqBlk_t* bp = sp->blocks;
  916. while( bp!=NULL && bp->link!=NULL )
  917. bp=bp->link;
  918. if( bp == NULL )
  919. return 0;
  920. cmSdbSeqEvent_t* ep = bp->eV + bp->cnt - 1;
  921. return ep->begSec + ep->durSec;
  922. }
  923. double cmSdbSeqSampleRate( cmSdbSeqH_t sh )
  924. {
  925. unsigned n = cmSdbSeqCount(sh);
  926. unsigned i;
  927. const cmSdbEvent_t* ep;
  928. for(i=0; i<n; ++i)
  929. if((ep = cmSdbSeqSdbEvent(sh,i)) != NULL && ep->srate != 0 )
  930. return ep->srate;
  931. return 0;
  932. }
  933. cmSdbRC_t cmSdbSeqToAudio(
  934. cmSdbSeqH_t sh,
  935. unsigned decayMs,
  936. double noiseDb,
  937. double normFact,
  938. cmSample_t** signalRef,
  939. unsigned* sigSmpCntRef )
  940. {
  941. assert( signalRef!=NULL && sigSmpCntRef!=NULL);
  942. *signalRef = NULL;
  943. *sigSmpCntRef = 0;
  944. cmSdbRC_t rc = kOkSdbRC;
  945. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  946. cmSdb_t* p = sp->p;
  947. unsigned qN = cmSdbSeqCount(sh);
  948. double durSecs = cmSdbSeqDurSeconds(sh);
  949. double srate = cmSdbSeqSampleRate(sh);
  950. assert(sp->maxDurSec>=sp->minDurSec);
  951. // verify that sequence events exist
  952. if( qN==0 || durSecs==0 || sp->chCnt==0 || sp->maxDurSec==0)
  953. return rc;
  954. // validate the sample rate
  955. if( srate == 0 )
  956. return cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"The sample rate of the sequence could not be determined.");
  957. unsigned sN = (unsigned)floor(srate * (durSecs + 0.25)); // output signal sample count + 1/4 second of silence
  958. unsigned dN = (unsigned)floor(srate * decayMs / 1000.0); // decay env. sample count
  959. unsigned tN = (unsigned)floor(srate * sp->maxDurSec); // length of longest audio event in samples
  960. cmSample_t* s = cmMemAllocZ(cmSample_t,sN*sp->chCnt); // allocate the outputsignal buffer
  961. cmSample_t* t = cmMemAllocZ(cmSample_t,tN*sp->chCnt); // audio event read buffer
  962. cmSample_t* d = NULL;
  963. cmSample_t* chBuf[ sp->chCnt ];
  964. unsigned i;
  965. // fill the channel buffers
  966. for(i=0; i<sp->chCnt; ++i)
  967. chBuf[i] = t + (i*tN);
  968. // if a decay rate was specified
  969. if( dN > 0 )
  970. {
  971. d = cmMemAllocZ(cmSample_t,dN); // allocate the decay env. buffer
  972. cmVOS_LinSpace(d,dN,1.0,0.0); // calc. a decay envelope
  973. cmVOS_PowVS(d,dN,4.0);
  974. }
  975. // if a noise floor was specified
  976. if( noiseDb != 0 )
  977. {
  978. // fill the signal with low level white noise
  979. cmVOS_Random(s,sN,-1.0,1.0);
  980. cmVOS_MultVS(s,sN,pow(10.0,-fabs(noiseDb)/20.0));
  981. }
  982. // for each sequence event
  983. for(i=0; rc==kOkSdbRC && i<qN; ++i)
  984. {
  985. const cmSdbSeqEvent_t* qep;
  986. const cmSdbEvent_t* ep;
  987. // get the sequence event record
  988. if((qep = cmSdbSeqEvent(sh,i)) == NULL )
  989. {
  990. rc = cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"Unable to retrieve the sequence event at index %i.",i);
  991. goto errLabel;
  992. }
  993. // get the audio event record
  994. if((ep = _cmSdbEvent(p,qep->uuid)) == NULL)
  995. {
  996. rc = cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"Unable to retrieve the sample event with uuid:%i.",qep->uuid);
  997. goto errLabel;
  998. }
  999. unsigned begFrmIdx = floor(srate * qep->begSec ); // dest. index into output signal
  1000. unsigned frmCnt = floor(srate * qep->durSec ); // seq. event dur in samples
  1001. const cmChar_t* afn = NULL; // audio event file name
  1002. unsigned actFrmCnt = 0; // actual count of samples read from the audio event file
  1003. cmAudioFileInfo_t afInfo; // audio file info. record
  1004. // form the audio event file name
  1005. if((afn = cmFsMakeFn(p->audioDir,ep->afn,NULL,NULL))==NULL)
  1006. {
  1007. rc = cmErrMsg(&p->ctx.err,kFileSysFailSdbRC,"Unable to form the file name for %s/%s.",cmStringNullGuard(p->audioDir),cmStringNullGuard(ep->afn));
  1008. goto errLabel;
  1009. }
  1010. assert(ep->oei-ep->obi>0 );
  1011. // read the audio event from the file into t[]
  1012. if( cmAudioFileGetSample(afn, ep->obi, cmMin(tN,cmMin(frmCnt,ep->oei-ep->obi)), 0, ep->chCnt, chBuf, &actFrmCnt, &afInfo, p->ctx.err.rpt ) != kOkAfRC )
  1013. {
  1014. rc = cmErrMsg(&p->ctx.err,kFileSysFailSdbRC,"Audio event read failed for event uuid:%i in '%s'.",qep->uuid,cmStringNullGuard(afn));
  1015. goto doneLabel;
  1016. }
  1017. // 'actFrmCnt' now holds the length of the event signal
  1018. // verify that the audio event sample rate matches the sequence srate
  1019. if( afInfo.srate != srate )
  1020. cmErrWarnMsg(&p->ctx.err,kAssertFailSdbRC,"The sample rate (%f) of audio event uuid:%i in '%s' does not match the sequence sample rate:%f.",afInfo.srate,qep->uuid,cmStringNullGuard(afn),srate);
  1021. // if a decay rate was specified
  1022. if( dN > 0 )
  1023. {
  1024. unsigned ti = 0; // start of decay in t[]
  1025. unsigned di = 0; // start of decay in d[]
  1026. if( actFrmCnt > dN )
  1027. ti = actFrmCnt - dN; // decay func is applied to end of audio event
  1028. else
  1029. di = dN - actFrmCnt; // decay func is longer than audio event (shorten it)
  1030. unsigned mn = dN - di; // decay function length
  1031. unsigned j;
  1032. // apply the decay function
  1033. for(j=0; j<sp->chCnt; ++j)
  1034. cmVOS_MultVV(t + (j*tN) +ti , mn, d+di);
  1035. }
  1036. // normalize the event signal
  1037. if( normFact != 0 )
  1038. cmVOS_NormToAbsMax(t,actFrmCnt,normFact);
  1039. // verify the the signal event falls inside the output signal
  1040. if( begFrmIdx >= sN )
  1041. rc = cmErrMsg(&p->ctx.err,kAssertFailSdbRC,"A sequence event start time falls after the end of the sequence signal. This should never happen.");
  1042. else
  1043. {
  1044. // if the event signal goes past the end of the signal - truncate the event
  1045. if( begFrmIdx + actFrmCnt > sN )
  1046. actFrmCnt = sN - begFrmIdx;
  1047. // sum the event signal into the output signal
  1048. cmVOS_AddVV(s + (qep->outChIdx*sN) + begFrmIdx,actFrmCnt,t);
  1049. }
  1050. doneLabel:
  1051. cmFsFreeFn(afn);
  1052. }
  1053. *signalRef = s;
  1054. *sigSmpCntRef = sN;
  1055. errLabel:
  1056. if( rc != kOkSdbRC )
  1057. cmMemFree(s);
  1058. cmMemFree(d);
  1059. cmMemFree(t);
  1060. return rc;
  1061. }
  1062. cmSdbRC_t cmSdbSeqToAudioFn(
  1063. cmSdbSeqH_t sh,
  1064. unsigned decayMs,
  1065. double noiseDb,
  1066. double evtNormFact,
  1067. double sigNormFact,
  1068. const cmChar_t* fn,
  1069. unsigned bitsPerSample
  1070. )
  1071. {
  1072. cmSdbRC_t rc = kOkSdbRC;
  1073. cmSample_t* s = NULL;
  1074. unsigned sN = 0;
  1075. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  1076. cmSdb_t* p = sp->p;
  1077. double srate = cmSdbSeqSampleRate(sh);
  1078. unsigned i;
  1079. // fill s[sN] with the sequence audio signal
  1080. if((rc = cmSdbSeqToAudio(sh,decayMs,noiseDb,evtNormFact,&s,&sN)) != kOkSdbRC )
  1081. return rc;
  1082. // if no audio signal was created there is nothing to do
  1083. if( sN == 0 )
  1084. return rc;
  1085. // the sample rate was already check by cmSdbSeqToAudio().
  1086. assert(srate != 0 && s != NULL);
  1087. // if requested normalize the signal
  1088. if( sigNormFact != 0 )
  1089. cmVOS_NormToAbsMax(s,sN*sp->chCnt,sigNormFact);
  1090. // fill the channel buffer
  1091. cmSample_t* chBuf[ sp->chCnt ];
  1092. for(i=0; i<sp->chCnt; ++i)
  1093. chBuf[i] = s + (i*sN);
  1094. // write the signal to an audio file
  1095. if((rc = cmAudioFileWriteFileFloat(fn, srate, bitsPerSample, sN, sp->chCnt, chBuf, p->ctx.err.rpt )) != kOkAfRC )
  1096. {
  1097. rc = cmErrMsg(&p->ctx.err,kAudioFileFailSdbRC,"The sequence audio file '%s' could not be created.",cmStringNullGuard(fn));
  1098. goto errLabel;
  1099. }
  1100. errLabel:
  1101. cmMemFree(s);
  1102. return rc;
  1103. }
  1104. void cmSdbSeqPrint( cmSdbSeqH_t sh, cmRpt_t* rpt )
  1105. {
  1106. unsigned i;
  1107. unsigned n = cmSdbSeqCount(sh);
  1108. cmSdbSeq_t* sp = _cmSdbSeqHandleToPtr(sh);
  1109. const cmSdbSeqEvent_t* ep;
  1110. cmRptPrintf(rpt,"evt cnt:%i ch cnt:%i dur min:%f max:%f \n",sp->cnt,sp->chCnt,sp->minDurSec,sp->maxDurSec);
  1111. cmRptPrintf(rpt," uuid ch beg dur gain \n");
  1112. cmRptPrintf(rpt,"------- --- ------- ------- -------\n");
  1113. for(i=0; i<n; ++i)
  1114. if((ep = cmSdbSeqEvent(sh,i)) != NULL )
  1115. cmRptPrintf(rpt,"%7i %3i %7.3f %7.3f %7.3f\n",ep->uuid,ep->outChIdx,ep->begSec,ep->durSec,ep->gain );
  1116. }
  1117. cmSdbRC_t cmSdbTest( cmCtx_t* ctx )
  1118. {
  1119. cmSdbRC_t rc = kOkSdbRC;
  1120. cmSdbH_t h = cmSdbNullHandle;
  1121. const cmChar_t* audioDir = "/home/kevin/media/audio";
  1122. const cmChar_t* csvFn = "/home/kevin/temp/sdb0/sdb_master.csv";
  1123. cmErr_t err;
  1124. cmErrSetup(&err,&ctx->rpt,"sdb test");
  1125. if((rc = cmSdbCreate(ctx, &h, csvFn, audioDir )) != kOkSdbRC )
  1126. {
  1127. rc = cmErrMsg(&err,rc,"sdb create failed.");
  1128. goto errLabel;
  1129. }
  1130. if((rc = cmSdbSyncChPairs(h)) != kOkSdbRC )
  1131. {
  1132. rc = cmErrMsg(&err,rc,"sdb sync-ch-pairs failed.");
  1133. goto errLabel;
  1134. }
  1135. if(1)
  1136. {
  1137. cmSdbResponseH_t rH = cmSdbResponseNullHandle;
  1138. cmSdbSeqH_t sH = cmSdbSeqNullHandle;
  1139. const cmChar_t* instrV[] = { "violin", NULL };
  1140. const cmChar_t* srcV[] = { "ui", NULL };
  1141. const cmChar_t* notesV[] = { "!vibrato", NULL };
  1142. if((rc = cmSdbSelect(h,0,instrV,srcV,notesV,NULL,0,0,0,&rH)) != kOkSdbRC )
  1143. {
  1144. rc = cmErrMsg(&err,rc,"sdb query failed.");
  1145. goto errLabel;
  1146. }
  1147. //cmSdbResponsePrint(rH,&ctx->rpt);
  1148. unsigned seqDurSecs = 15;
  1149. unsigned seqChCnt = 2;
  1150. unsigned sel = 2;
  1151. switch( sel )
  1152. {
  1153. case 0:
  1154. {
  1155. unsigned minEvtPerSec = 1;
  1156. unsigned maxEvtPerSec = 5;
  1157. if((rc = cmSdbSeqRand(rH,seqDurSecs,seqChCnt,minEvtPerSec,maxEvtPerSec,&sH)) != kOkSdbRC )
  1158. {
  1159. rc = cmErrMsg(&err,rc,"sdb random sequence generation failed.");
  1160. goto errLabel;
  1161. }
  1162. }
  1163. break;
  1164. case 1:
  1165. {
  1166. double gapSec = 0.1;
  1167. double maxEvtDurSec = 1.0;
  1168. if((rc = cmSdbSeqSerial(rH,seqChCnt,gapSec,maxEvtDurSec,&sH)) != kOkSdbRC )
  1169. {
  1170. rc = cmErrMsg(&err,rc,"sdb serial sequence generation failed.");
  1171. goto errLabel;
  1172. }
  1173. }
  1174. break;
  1175. case 2:
  1176. {
  1177. cmSdbResponseH_t rhV[] = { rH, rH, rH };
  1178. unsigned rN = sizeof(rhV)/sizeof(rhV[0]);
  1179. double maxEvtDurSec = 1.0;
  1180. if((rc = cmSdbSeqChord(rhV,rN,seqChCnt,maxEvtDurSec,&sH)) != kOkSdbRC )
  1181. {
  1182. rc = cmErrMsg(&err,rc,"sdb chord sequence generation failed.");
  1183. goto errLabel;
  1184. }
  1185. }
  1186. break;
  1187. }
  1188. cmSdbSeqPrint(sH,&ctx->rpt);
  1189. const cmChar_t* afn = "/home/kevin/temp/aaa.aif";
  1190. unsigned decayMs = 50;
  1191. double noiseDb = -70.0;
  1192. double evtNormFact = 0; //0.7;
  1193. double sigNormFact = 0.7; //0.7;
  1194. unsigned bitsPerSample = 16;
  1195. if((rc = cmSdbSeqToAudioFn(sH,decayMs,noiseDb,evtNormFact,sigNormFact,afn,bitsPerSample)) != kOkSdbRC )
  1196. {
  1197. rc = cmErrMsg(&err,rc,"sdb sequence audio file generation failed.");
  1198. goto errLabel;
  1199. }
  1200. cmSdbSeqFree(&sH);
  1201. cmSdbResponseFree(&rH);
  1202. }
  1203. errLabel:
  1204. if((rc = cmSdbDestroy(&h)) != kOkSdbRC )
  1205. rc = cmErrMsg(&err,rc,"sdb destroy failed.");
  1206. return rc;
  1207. }