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.

cmSdb.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. #include "cmGlobal.h"
  2. #include "cmRpt.h"
  3. #include "cmErr.h"
  4. #include "cmCtx.h"
  5. #include "cmMem.h"
  6. #include "cmMallocDebug.h"
  7. #include "cmLinkedHeap.h"
  8. #include "cmLex.h"
  9. #include "cmCsv.h"
  10. #include "cmSdb.h"
  11. #include "cmText.h"
  12. typedef enum
  13. {
  14. kUuidColIdx,
  15. kBaseUuidColIdx,
  16. kChIdxColIdx,
  17. kObiColIdx,
  18. kIbiColIdx,
  19. kIeiColIdx,
  20. kOeiColIdx,
  21. kSrcColIdx,
  22. kMidiColIdx,
  23. kInstrColIdx,
  24. kSrateColIdx,
  25. kChCntColIdx,
  26. kNotesColIdx,
  27. kAfnColIdx,
  28. kInvalidColIdx
  29. } cmSdbColIdx_t;
  30. struct cmSdb_str;
  31. typedef struct cmSdbRspBlk_str
  32. {
  33. unsigned* indexV; // indexV[ cmSdb_t.blkIdxAllocCnt ]
  34. unsigned cnt; // count of indexes used
  35. struct cmSdbRspBlk_str* link; // cmSdbRsp_t.blocks link
  36. } cmSdbRspBlk_t;
  37. typedef struct cmSdbRsp_str
  38. {
  39. struct cmSdb_str* p; //
  40. cmSdbRspBlk_t* blocks; // first block ptr
  41. cmSdbRspBlk_t* ebp; // end block ptr
  42. unsigned cnt; // total count of indexes
  43. struct cmSdbRsp_str* link; // cmSdb_t.responses link
  44. } cmSdbRsp_t;
  45. typedef struct cmSdb_str
  46. {
  47. cmCtx_t ctx;
  48. cmLHeapH_t lhH;
  49. cmCsvH_t csvH;
  50. cmSdbEvent_t* eV;
  51. unsigned eN;
  52. unsigned blkIdxAllocCnt;
  53. struct cmSdbRsp_str* responses;
  54. } cmSdb_t;
  55. cmSdbH_t cmSdbNullHandle = cmSTATIC_NULL_HANDLE;
  56. cmSdbResponseH_t cmSdbResponseNullHandle = cmSTATIC_NULL_HANDLE;
  57. cmSdb_t* _cmSdbHandleToPtr( cmSdbH_t h )
  58. {
  59. cmSdb_t* p = (cmSdb_t*)h.h;
  60. assert( p != NULL );
  61. return p;
  62. }
  63. cmSdbRsp_t* _cmSdbRspHandleToPtr( cmSdbResponseH_t h )
  64. {
  65. cmSdbRsp_t* p = (cmSdbRsp_t*)h.h;
  66. assert( p != NULL );
  67. return p;
  68. }
  69. void _cmSdbRspBlkFree( cmSdb_t* p, cmSdbRspBlk_t* bp )
  70. {
  71. cmLhFree(p->lhH, bp->indexV);
  72. cmLhFree(p->lhH, bp);
  73. }
  74. cmSdbRspBlk_t* _cmSdbRspBlkUnlink( cmSdbRsp_t* rp, cmSdbRspBlk_t* bp )
  75. {
  76. cmSdbRspBlk_t* dp = rp->blocks;
  77. cmSdbRspBlk_t* pp = NULL;
  78. for(; dp!=NULL; dp=dp->link)
  79. {
  80. if( dp == bp )
  81. {
  82. if( pp == NULL )
  83. rp->blocks = dp->link;
  84. else
  85. pp->link = dp->link;
  86. return bp;
  87. }
  88. pp = dp;
  89. }
  90. assert(0);
  91. return NULL;
  92. }
  93. void _cmSdbRspInsertIndex( cmSdb_t* p, cmSdbRsp_t* rp, unsigned evtIndex )
  94. {
  95. if( rp->ebp == NULL || rp->ebp->cnt == p->blkIdxAllocCnt )
  96. {
  97. cmSdbRspBlk_t* bp = cmLhAllocZ(p->lhH,cmSdbRspBlk_t,1);
  98. bp->indexV = cmLhAllocZ(p->lhH,unsigned,p->blkIdxAllocCnt);
  99. if( rp->ebp != NULL )
  100. rp->ebp->link = bp;
  101. if( rp->blocks == NULL )
  102. rp->blocks = bp;
  103. rp->ebp = bp;
  104. }
  105. assert( rp->ebp!=NULL && rp->ebp->cnt < p->blkIdxAllocCnt );
  106. rp->ebp->indexV[ rp->ebp->cnt++ ] = evtIndex;
  107. rp->cnt += 1;
  108. }
  109. void _cmSdbRspRelease( cmSdbRsp_t* rp )
  110. {
  111. while( rp->blocks != NULL )
  112. {
  113. cmSdbRspBlk_t* np = rp->blocks->link;
  114. cmSdbRspBlk_t* bp;
  115. if((bp = _cmSdbRspBlkUnlink(rp,rp->blocks)) != NULL )
  116. _cmSdbRspBlkFree(rp->p,bp);
  117. rp->blocks = np;
  118. }
  119. cmLhFree(rp->p->lhH,rp);
  120. }
  121. cmSdbRsp_t* _cmSdbRspUnlink( cmSdbRsp_t* rp )
  122. {
  123. cmSdb_t* p = rp->p;
  124. cmSdbRsp_t* dp = p->responses;
  125. cmSdbRsp_t* pp = NULL;
  126. for(; dp!=NULL; dp=dp->link)
  127. {
  128. if( dp == rp )
  129. {
  130. if( pp == NULL )
  131. p->responses = dp->link;
  132. else
  133. pp->link = dp->link;
  134. return rp;
  135. }
  136. pp = dp;
  137. }
  138. assert( 0 );
  139. return NULL;
  140. }
  141. void _cmSdbRspFree( cmSdbRsp_t* rp )
  142. {
  143. _cmSdbRspUnlink(rp);
  144. _cmSdbRspRelease(rp);
  145. }
  146. cmSdbRsp_t* _cmSdbRspAlloc( cmSdb_t* p, cmSdbResponseH_t* rhp )
  147. {
  148. if( cmSdbResponseFree(rhp) != kOkSdbRC )
  149. return NULL;
  150. cmSdbRsp_t* rp = cmLhAllocZ(p->lhH,cmSdbRsp_t,1);
  151. rp->p = p;
  152. rp->link = p->responses;
  153. p->responses = rp;
  154. rhp->h = rp;
  155. return rp;
  156. }
  157. cmSdbRC_t _cmSdbDestroy( cmSdb_t* p )
  158. {
  159. cmSdbRC_t rc = kOkSdbRC;
  160. if( cmCsvFinalize(&p->csvH) != kOkCsvRC )
  161. rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file finalize failed.");
  162. while( p->responses != NULL )
  163. _cmSdbRspRelease(p->responses);
  164. cmLHeapDestroy(&p->lhH);
  165. cmMemFree(p);
  166. return rc;
  167. }
  168. cmSdbRC_t cmSdbCreate( cmCtx_t* ctx, cmSdbH_t* hp, const cmChar_t* audioDir, const cmChar_t* csvFn )
  169. {
  170. cmSdbRC_t rc;
  171. if((rc = cmSdbDestroy(hp)) != kOkSdbRC )
  172. return rc;
  173. cmSdb_t* p = cmMemAllocZ(cmSdb_t,1);
  174. p->ctx = *ctx;
  175. p->blkIdxAllocCnt = 1024;
  176. cmErrSetup(&p->ctx.err,&ctx->rpt,"sdb");
  177. if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8192,ctx)) == false )
  178. {
  179. rc = cmErrMsg(&p->ctx.err,kLHeapFailSdbRC,"Linked heap mgr. allocation failed.");
  180. goto errLabel;
  181. }
  182. hp->h = p;
  183. if( csvFn != NULL )
  184. if((rc = cmSdbLoad(*hp,csvFn)) != kOkSdbRC )
  185. goto errLabel;
  186. errLabel:
  187. if( rc != kOkSdbRC )
  188. _cmSdbDestroy(p);
  189. return rc;
  190. }
  191. cmSdbRC_t cmSdbDestroy( cmSdbH_t* hp )
  192. {
  193. cmSdbRC_t rc = kOkSdbRC;
  194. if( hp==NULL || cmSdbIsValid(*hp)==false )
  195. return rc;
  196. cmSdb_t* p = _cmSdbHandleToPtr(*hp);
  197. if((rc = _cmSdbDestroy(p)) != kOkSdbRC )
  198. return rc;
  199. hp->h = NULL;
  200. return rc;
  201. }
  202. bool cmSdbIsValid( cmSdbH_t h )
  203. { return h.h != NULL; }
  204. cmSdbRC_t _cmSdbSyntaxError(cmSdb_t* p, const cmChar_t* csvFn, unsigned rowIdx, unsigned colIdx, const cmChar_t* colLabel )
  205. {
  206. 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));
  207. }
  208. cmSdbRC_t cmSdbLoad( cmSdbH_t h, const cmChar_t* csvFn )
  209. {
  210. cmSdbRC_t rc = kOkSdbRC;
  211. unsigned i;
  212. cmSdb_t* p = _cmSdbHandleToPtr(h);
  213. if( cmCsvInitializeFromFile(&p->csvH, csvFn, 0, &p->ctx ) != kOkCsvRC )
  214. {
  215. rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file load fail on '%s'.",cmStringNullGuard(csvFn));
  216. goto errLabel;
  217. }
  218. p->eN = cmCsvRowCount(p->csvH)-1;
  219. // release all the memory held by the linked heap
  220. cmLHeapClear(p->lhH,true);
  221. p->eV = cmLhAllocZ(p->lhH,cmSdbEvent_t,p->eN);
  222. for(i=0; rc==kOkSdbRC && i<p->eN; ++i)
  223. {
  224. unsigned rowIdx = i+1;
  225. if((p->eV[i].uuid = cmCsvCellUInt(p->csvH,rowIdx,kUuidColIdx)) == UINT_MAX )
  226. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kUuidColIdx,"uuid");
  227. if((p->eV[i].baseUuid = cmCsvCellUInt(p->csvH,rowIdx,kBaseUuidColIdx)) == UINT_MAX )
  228. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kBaseUuidColIdx,"baseUuid");
  229. if((p->eV[i].chIdx = cmCsvCellUInt(p->csvH,rowIdx,kChIdxColIdx)) == UINT_MAX )
  230. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChIdxColIdx,"chIdx");
  231. else
  232. p->eV[i].chIdx -= 1; // CSV channel index is 1 based
  233. if((p->eV[i].obi = cmCsvCellUInt(p->csvH,rowIdx,kObiColIdx)) == UINT_MAX )
  234. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kObiColIdx,"obi");
  235. else
  236. p->eV[i].obi -= 1;
  237. if((p->eV[i].ibi = cmCsvCellUInt(p->csvH,rowIdx,kIbiColIdx)) == UINT_MAX )
  238. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIbiColIdx,"ibi");
  239. else
  240. p->eV[i].ibi -= 1;
  241. if((p->eV[i].iei = cmCsvCellUInt(p->csvH,rowIdx,kIeiColIdx)) == UINT_MAX )
  242. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIeiColIdx,"obi");
  243. else
  244. p->eV[i].iei -= 1;
  245. if((p->eV[i].oei = cmCsvCellUInt(p->csvH,rowIdx,kOeiColIdx)) == UINT_MAX )
  246. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kOeiColIdx,"ibi");
  247. else
  248. p->eV[i].oei -= 1;
  249. if((p->eV[i].src = cmCsvCellText(p->csvH,rowIdx,kSrcColIdx)) == NULL )
  250. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrcColIdx,"src");
  251. if((p->eV[i].midi = cmCsvCellInt(p->csvH,rowIdx,kMidiColIdx)) == INT_MAX )
  252. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kMidiColIdx,"midi");
  253. if((p->eV[i].instr = cmCsvCellText(p->csvH,rowIdx,kInstrColIdx)) == NULL )
  254. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kInstrColIdx,"instr");
  255. if((p->eV[i].srate = cmCsvCellUInt(p->csvH,rowIdx,kSrateColIdx)) == UINT_MAX )
  256. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrateColIdx,"srate");
  257. if((p->eV[i].chCnt = cmCsvCellUInt(p->csvH,rowIdx,kChCntColIdx)) == UINT_MAX )
  258. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChCntColIdx,"chCnt");
  259. cmCsvCell_t* c;
  260. if((c = cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx)) == NULL )
  261. {
  262. rc = cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"Syntax Error: No 'notes' or 'audio file name' field for row %i in '%s'.",rowIdx+1,cmStringNullGuard(csvFn));
  263. goto errLabel;
  264. }
  265. // count the number of 'notes'
  266. unsigned nn = 0;
  267. for(; c->rowPtr != NULL; c=c->rowPtr)
  268. ++nn;
  269. if( nn > 0 )
  270. {
  271. unsigned k = 0;
  272. // allocate the 'notes' ptr array - the last entry is set to NULL.
  273. p->eV[i].notesV = cmLhAllocZ(p->lhH,const cmChar_t*,nn+1);
  274. // read each note
  275. for(c=cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx); c!=NULL&&c->rowPtr!=NULL; c=c->rowPtr,++k)
  276. if(( p->eV[i].notesV[k] = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+k)) == NULL )
  277. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+k,"notes");
  278. assert(k==nn);
  279. }
  280. // read the audio file name
  281. if((p->eV[i].afn = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+nn)) == NULL )
  282. rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+nn,"afn");
  283. }
  284. errLabel:
  285. return rc;
  286. }
  287. // Compare 'label' to every string in tV[i] and return true if any comparision is a match.
  288. // If 'subFlV[i]' is set then 'label' must only contain tV[i] as a substring to match.
  289. // If 'negFlV[i]' is set then return true if any comparision is a mismatch.
  290. bool _cmSdbSelectText( const cmSdbEvent_t* r, const cmChar_t** tV, const bool* subFlV, const bool* negFlV, const cmChar_t* label )
  291. {
  292. unsigned i;
  293. if( label == NULL )
  294. return false;
  295. if( tV == NULL )
  296. return true;
  297. for(i=0; tV[i]!=NULL; ++i)
  298. {
  299. bool matchFl = false;
  300. if( subFlV[i] )
  301. matchFl = strstr(label,tV[i]) != NULL;
  302. else
  303. matchFl = strcmp(tV[i],label)==0;
  304. if( negFlV[i] )
  305. matchFl = !matchFl;
  306. if(matchFl)
  307. return true;
  308. }
  309. return false;
  310. }
  311. unsigned _cmSdbStrVectCnt( const cmChar_t** v )
  312. {
  313. unsigned n = 0;
  314. unsigned i = 0;
  315. if( v == NULL )
  316. return 0;
  317. for(i=0; v[i]!=NULL; ++i)
  318. ++n;
  319. return n;
  320. }
  321. void _cmSdbStrVectFlags( const cmChar_t** v, bool* sV, bool* nV )
  322. {
  323. unsigned i = 0;
  324. if( v == NULL )
  325. return;
  326. for(i=0; v[i]!=NULL; ++i)
  327. {
  328. nV[i] = false;
  329. sV[i] = false;
  330. if( strncmp(v[i],"*!",2)==0 || strncmp(v[i],"!*",2)==0)
  331. {
  332. sV[i] = nV[i] = true;
  333. v[i] += 2;
  334. }
  335. else
  336. {
  337. if( strncmp(v[i],"!",1)==0 )
  338. {
  339. nV[i] = true;
  340. v[i] += 1;
  341. }
  342. if( strncmp(v[i],"*",1)==0 )
  343. {
  344. sV[i] = true;
  345. v[i] += 1;
  346. }
  347. }
  348. }
  349. }
  350. cmSdbRC_t cmSdbSelect(
  351. cmSdbH_t h,
  352. double srate,
  353. const cmChar_t** instrV,
  354. const cmChar_t** srcV,
  355. const cmChar_t** notesV,
  356. double minDurSec,
  357. double maxDurSec,
  358. unsigned minChCnt,
  359. cmSdbResponseH_t* rhp )
  360. {
  361. cmSdbRC_t rc = kOkSdbRC;
  362. cmSdb_t* p = _cmSdbHandleToPtr(h);
  363. unsigned i;
  364. cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
  365. // get the length of each string vector
  366. unsigned srcN = _cmSdbStrVectCnt(srcV);
  367. unsigned insN = _cmSdbStrVectCnt(instrV);
  368. unsigned notN = _cmSdbStrVectCnt(notesV);
  369. // allocate flag vectors
  370. bool srcSubFlV[ srcN ];
  371. bool srcNegFlV[ srcN ];
  372. bool insSubFlV[ insN ];
  373. bool insNegFlV[ insN ];
  374. bool notSubFlV[ notN ];
  375. bool notNegFlV[ notN ];
  376. // fill the flag vectors
  377. _cmSdbStrVectFlags(srcV, srcSubFlV,srcNegFlV);
  378. _cmSdbStrVectFlags(instrV,insSubFlV,insNegFlV);
  379. _cmSdbStrVectFlags(notesV,notSubFlV,notNegFlV);
  380. for(i=0; i<p->eN; ++i)
  381. {
  382. const cmSdbEvent_t* r = p->eV + i;
  383. double durSec = (double)r->srate * (r->oei - r->obi);
  384. unsigned j;
  385. if( srate!=0 && srate!=r->srate )
  386. continue;
  387. if( durSec < minDurSec || (maxDurSec!=0 && maxDurSec < durSec) )
  388. continue;
  389. if( minChCnt!=0 && r->chCnt > minChCnt )
  390. continue;
  391. if( !_cmSdbSelectText(r,srcV,srcSubFlV,srcNegFlV,r->src) )
  392. continue;
  393. if( !_cmSdbSelectText(r,instrV,insSubFlV,insNegFlV,r->instr) )
  394. continue;
  395. if( r->notesV != NULL )
  396. for(j=0; r->notesV[j]!=NULL; ++j)
  397. if( _cmSdbSelectText(r,notesV,notSubFlV,notNegFlV,r->notesV[j]) == true )
  398. break;
  399. if( r->notesV[j]==NULL )
  400. continue;
  401. _cmSdbRspInsertIndex(p,rp,i);
  402. }
  403. return rc;
  404. }
  405. cmSdbRC_t cmSdbSelectChPairs( cmSdbH_t h, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp )
  406. {
  407. cmSdbRC_t rc = kOkSdbRC;
  408. cmSdb_t* p = _cmSdbHandleToPtr(h);
  409. cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
  410. unsigned i;
  411. // for each channel of this event
  412. for(i=0; i<ep->chCnt; ++i)
  413. {
  414. // if i channel is not the known events channel
  415. if( ep->chIdx != i )
  416. {
  417. unsigned j;
  418. // examine each record
  419. for(j=0; j<p->eN; ++j)
  420. // if eV[j] shares a baseUuid but is on a different channel than *ep ...
  421. if( p->eV[j].baseUuid == ep->baseUuid && p->eV[j].chIdx==i )
  422. {
  423. // .. then a match has been found
  424. _cmSdbRspInsertIndex(p,rp,j);
  425. break;
  426. }
  427. if( j== p->eN )
  428. {
  429. 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);
  430. }
  431. }
  432. }
  433. return rc;
  434. }
  435. unsigned cmSdbResponseCount( cmSdbResponseH_t rh )
  436. {
  437. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  438. return rp->cnt;
  439. }
  440. const cmSdbEvent_t* cmSdbResponseEvent( cmSdbResponseH_t rh, unsigned index )
  441. {
  442. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
  443. if( index >= rp->cnt )
  444. return NULL;
  445. cmSdbRspBlk_t* bp = rp->blocks;
  446. unsigned i;
  447. for(i=0; bp!=NULL; i+=bp->cnt,bp=bp->link)
  448. if( i <= index && index < (i + bp->cnt) )
  449. return rp->p->eV + bp->indexV[index-i];
  450. cmErrMsg(&rp->p->ctx.err,kInvalidRspIdxSdbRC,"Invalid query response index=%i.",index);
  451. return NULL;
  452. }
  453. bool cmSdbResponseIsValid( cmSdbResponseH_t rh )
  454. { return rh.h != NULL; }
  455. cmSdbRC_t cmSdbResponseFree( cmSdbResponseH_t* rhp )
  456. {
  457. cmSdbRC_t rc = kOkSdbRC;
  458. if( rhp == NULL || cmSdbResponseIsValid(*rhp)==false )
  459. return rc;
  460. cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(*rhp);
  461. _cmSdbRspFree(rp);
  462. rhp->h = NULL;
  463. return rc;
  464. }
  465. void cmSdbResponsePrint( cmSdbResponseH_t rh, cmRpt_t* rpt )
  466. {
  467. unsigned n = cmSdbResponseCount(rh);
  468. unsigned i;
  469. for(i=0; i<n; ++i)
  470. {
  471. const cmSdbEvent_t* e = cmSdbResponseEvent(rh,i);
  472. if( e != NULL )
  473. cmRptPrintf(rpt,"%6i %6i %2i %12i %12i %12i %12i %2i %6i %2i %10s %15s\n",
  474. e->uuid,e->baseUuid,e->chIdx,e->obi,e->ibi,e->iei,e->oei,e->midi,e->srate,e->chCnt,
  475. cmStringNullGuard(e->src), cmStringNullGuard(e->instr) );
  476. }
  477. }
  478. cmSdbRC_t cmSdbSyncChPairs( cmSdbH_t h )
  479. {
  480. cmSdbRC_t rc = kOkSdbRC;
  481. cmSdb_t* p = _cmSdbHandleToPtr(h);
  482. unsigned i;
  483. // for each multi-channel event
  484. for(i=0; i<p->eN; ++i)
  485. if(p->eV[i].chCnt > 1 )
  486. {
  487. const cmSdbEvent_t* ep = p->eV + i;
  488. unsigned iV[ep->chCnt];
  489. unsigned j,k;
  490. // load iV[] with the event indexes of the channel pairs
  491. for(j=0,k=0; j<p->eN && k<ep->chCnt; ++j)
  492. if( p->eV[j].baseUuid == ep->baseUuid )
  493. {
  494. assert( p->eV[j].chIdx < ep->chCnt );
  495. iV[p->eV[j].chIdx] = j;
  496. ++k;
  497. }
  498. if( k != ep->chCnt )
  499. 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);
  500. else
  501. {
  502. unsigned mobi = ep->obi;
  503. unsigned mibi = ep->ibi;
  504. unsigned miei = ep->iei;
  505. unsigned moei = ep->oei;
  506. // get the min onsets and max offsets
  507. for(j=0; j<ep->chCnt; ++j)
  508. {
  509. mobi = cmMin(mobi,p->eV[ iV[j] ].obi);
  510. mibi = cmMin(mibi,p->eV[ iV[j] ].ibi);
  511. miei = cmMax(miei,p->eV[ iV[j] ].iei);
  512. moei = cmMax(moei,p->eV[ iV[j] ].oei);
  513. }
  514. // set the onsets to the min onset / offsets to max offsets
  515. for(j=0; j<ep->chCnt; ++j)
  516. {
  517. p->eV[ iV[j] ].obi = mobi;
  518. p->eV[ iV[j] ].ibi = mibi;
  519. p->eV[ iV[j] ].iei = miei;
  520. p->eV[ iV[j] ].oei = moei;
  521. }
  522. }
  523. }
  524. return rc;
  525. }
  526. cmSdbRC_t cmSdbTest( cmCtx_t* ctx )
  527. {
  528. cmSdbRC_t rc = kOkSdbRC;
  529. cmSdbH_t h = cmSdbNullHandle;
  530. const cmChar_t* audioDir = "/home/kevin/media/audio";
  531. const cmChar_t* csvFn = "/home/kevin/temp/sdb0/sdb_master.csv";
  532. cmErr_t err;
  533. cmErrSetup(&err,&ctx->rpt,"sdb test");
  534. if((rc = cmSdbCreate(ctx, &h, audioDir, csvFn )) != kOkSdbRC )
  535. {
  536. rc = cmErrMsg(&err,rc,"sdb create failed.");
  537. goto errLabel;
  538. }
  539. if((rc = cmSdbSyncChPairs(h)) != kOkSdbRC )
  540. {
  541. rc = cmErrMsg(&err,rc,"sdb sync-ch-pairs failed.");
  542. goto errLabel;
  543. }
  544. if(0)
  545. {
  546. cmSdbResponseH_t rH = cmSdbResponseNullHandle;
  547. const cmChar_t* instrV[] = { "*viol", NULL };
  548. if((rc = cmSdbSelect(h,0,instrV,NULL,NULL,0,0,0,&rH)) != kOkSdbRC )
  549. {
  550. rc = cmErrMsg(&err,rc,"sdb query failed.");
  551. goto errLabel;
  552. }
  553. cmSdbResponsePrint(rH,&ctx->rpt);
  554. cmSdbResponseFree(&rH);
  555. }
  556. errLabel:
  557. if((rc = cmSdbDestroy(&h)) != kOkSdbRC )
  558. rc = cmErrMsg(&err,rc,"sdb destroy failed.");
  559. return rc;
  560. }