libcm is a C development framework with an emphasis on audio signal processing applications.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmCtx.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmLinkedHeap.h"
  10. #include "cmJson.h"
  11. #include "cmTime.h"
  12. #include "cmMidi.h"
  13. #include "cmMidiFile.h"
  14. #include "cmAudioFile.h"
  15. #include "cmTimeLine.h"
  16. #include "cmSymTbl.h"
  17. #include "cmScore.h"
  18. #include "cmTakeSeqBldr.h"
  19. typedef struct cmNoteTsb_str
  20. {
  21. unsigned mni; // midi note index as an offset from the take marker
  22. unsigned scEvtIdx; // score event index this not is assoc'd with or -1 if it did not match
  23. unsigned flags; // flags from cmScMatcherResult_t
  24. } cmNoteTsb_t;
  25. typedef struct cmTakeTsb_str
  26. {
  27. unsigned markerUid; // marker time line uid assoc'd with this take
  28. cmNoteTsb_t* noteV; // noteV[noteN] score to midi file map recd. array.
  29. unsigned noteN;
  30. bool failFl;
  31. } cmTakeTsb_t;
  32. typedef struct
  33. {
  34. cmCtx_t ctx;
  35. cmErr_t err;
  36. cmJsonH_t jsH;
  37. const cmChar_t* tlFn;
  38. const cmChar_t* scFn;
  39. const cmChar_t* tlPrefixPath;
  40. cmTakeTsb_t* takeV; // takeV[ takeN ]
  41. unsigned takeN;
  42. cmTlH_t tlH;
  43. cmScH_t scH;
  44. } cmTsb_t;
  45. cmTakeSeqBldrH_t cmTakeSeqBldrNullHandle = cmSTATIC_NULL_HANDLE;
  46. cmTsb_t* _cmTsbHandleToPtr( cmTakeSeqBldrH_t h )
  47. {
  48. cmTsb_t* p = (cmTsb_t*)h.h;
  49. return p;
  50. }
  51. cmTsbRC_t _cmTsbScoreTrkFree( cmTsb_t* p )
  52. {
  53. cmTsbRC_t rc = kOkTsbRC;
  54. unsigned i;
  55. if( cmJsonFinalize(&p->jsH) != kOkJsRC )
  56. {
  57. rc = cmErrMsg(&p->err,kJsonFailTsbRC,"JSON object finalize failed.");
  58. goto errLabel;
  59. }
  60. for(i=0; i<p->takeN; ++i)
  61. cmMemPtrFree(&p->takeV[i].noteV);
  62. cmMemPtrFree(&p->takeV);
  63. if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
  64. rc = cmErrMsg(&p->err,kTimeLineFailTsbRC,"Time line object finalize failed.");
  65. if( cmScoreFinalize(&p->scH) != kOkScRC )
  66. rc = cmErrMsg(&p->err,kScoreFailTsbRC,"Score finalize failed.");
  67. errLabel:
  68. return rc;
  69. }
  70. cmTsbRC_t _cmTsbFree( cmTsb_t* p )
  71. {
  72. cmTsbRC_t rc = kOkTsbRC;
  73. if((rc = _cmTsbScoreTrkFree(p)) != kOkTsbRC )
  74. goto errLabel;
  75. cmMemFree(p);
  76. errLabel:
  77. return rc;
  78. }
  79. cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
  80. {
  81. cmTsbRC_t rc = kOkTsbRC;
  82. cmJsonNode_t* tkArrObj = NULL;
  83. cmJsRC_t jsRC = kOkJsRC;
  84. const cmChar_t* errMsg = NULL;
  85. unsigned i;
  86. // initialize the TSB json object
  87. if(( rc = cmJsonInitializeFromFile(&p->jsH,scoreTrkFn,&p->ctx)) != kOkJsRC )
  88. {
  89. rc = cmErrMsg(&p->err,kJsonFailTsbRC,"The Take Sequence Builder JSON file object could not be initialized from '%s'.",cmStringNullGuard(scoreTrkFn));
  90. goto errLabel;
  91. }
  92. // parse the header
  93. if((jsRC = cmJsonMemberValues( cmJsonRoot(p->jsH), &errMsg,
  94. "timeLineFn", kStringTId, &p->tlFn,
  95. "scoreFn", kStringTId, &p->scFn,
  96. "tlPrefixPath", kStringTId, &p->tlPrefixPath,
  97. "takeArray", kArrayTId | kOptArgJsFl, &tkArrObj,
  98. 0 )) != kOkJsRC )
  99. {
  100. if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
  101. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file header parse failed missing required field:'%s'",errMsg);
  102. else
  103. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file header parse failed.");
  104. goto errLabel;
  105. }
  106. // count of take records
  107. p->takeN = cmJsonChildCount(tkArrObj);
  108. // array of take records
  109. p->takeV = cmMemAllocZ(cmTakeTsb_t,p->takeN);
  110. // for each take record
  111. for(i=0; i<p->takeN; ++i)
  112. {
  113. cmJsonNode_t* takeObj = NULL;
  114. cmJsonNode_t* noteArrObj = NULL;
  115. unsigned j;
  116. // get a pointer to the take record JSON object
  117. if((takeObj = cmJsonArrayElement(tkArrObj,i)) == NULL )
  118. {
  119. rc = cmErrMsg(&p->err,kParseFailTsbRC,"Take record header at index %i access failed.",i);
  120. goto errLabel;
  121. }
  122. // parse the take record
  123. if((jsRC = cmJsonMemberValues( takeObj, &errMsg,
  124. "markerUid",kIntTId, &p->takeV[i].markerUid,
  125. "failFl", kIntTId, &p->takeV[i].failFl,
  126. "array", kArrayTId, &noteArrObj,
  127. 0)) != kOkJsRC )
  128. {
  129. if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
  130. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file take record parse failed missing required field:'%s'",errMsg);
  131. else
  132. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file take record parse failed.");
  133. goto errLabel;
  134. }
  135. // get the count of note records
  136. p->takeV[i].noteN = cmJsonChildCount(noteArrObj);
  137. // allocate a note record array for this take
  138. p->takeV[i].noteV = cmMemAllocZ(cmNoteTsb_t, p->takeV[i].noteN);
  139. // for each note record
  140. for(j=0; j<p->takeV[i].noteN; ++j)
  141. {
  142. cmJsonNode_t* noteObj = NULL;
  143. // get the note record JSON object
  144. if((noteObj = cmJsonArrayElement(noteArrObj,j)) == NULL )
  145. {
  146. rc = cmErrMsg(&p->err,kParseFailTsbRC,"Access failed for note record at index %i at take index %i.",j,i);
  147. goto errLabel;
  148. }
  149. // parse the note record
  150. if((jsRC = cmJsonMemberValues( noteObj, &errMsg,
  151. "mni", kIntTId, &p->takeV[i].noteV[j].mni,
  152. "scEvtIdx", kIntTId, &p->takeV[i].noteV[j].scEvtIdx,
  153. "flags", kIntTId, &p->takeV[i].noteV[j].flags,
  154. 0)) != kOkJsRC )
  155. {
  156. if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
  157. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file note record parse failed missing required field:'%s'",errMsg);
  158. else
  159. rc = cmErrMsg(&p->err,kParseFailTsbRC,"JSON file note record parse failed.");
  160. goto errLabel;
  161. }
  162. }
  163. }
  164. errLabel:
  165. if( rc != kOkTsbRC )
  166. rc = _cmTsbScoreTrkFree(p);
  167. return rc;
  168. }
  169. cmTsbRC_t cmTakeSeqBldrAlloc( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp )
  170. {
  171. cmTsbRC_t rc;
  172. if((rc = cmTakeSeqBldrFree(hp)) != kOkTsbRC )
  173. return kOkTsbRC;
  174. cmTsb_t* p = cmMemAllocZ(cmTsb_t,1);
  175. cmErrSetup(&p->err,&ctx->rpt,"TakeSeqBldr");
  176. p->ctx = *ctx;
  177. hp->h = p;
  178. return rc;
  179. }
  180. cmTsbRC_t cmTakeSeqBldrAllocFn( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp, const cmChar_t* scoreTrkFn )
  181. {
  182. cmTsbRC_t rc;
  183. if((rc = cmTakeSeqBldrAlloc(ctx,hp)) != kOkTsbRC )
  184. return rc;
  185. if((rc = cmTakeSeqBldrInitialize(*hp,scoreTrkFn)) != kOkTsbRC )
  186. return rc;
  187. return rc;
  188. }
  189. cmTsbRC_t cmTakeSeqBldrFree( cmTakeSeqBldrH_t* hp )
  190. {
  191. cmRC_t rc = kOkTsbRC;
  192. if( hp == NULL || cmTakeSeqBldrIsValid(*hp)==false )
  193. return kOkTsbRC;
  194. cmTsb_t* p = _cmTsbHandleToPtr(*hp);
  195. if((rc = _cmTsbFree(p)) != kOkTsbRC )
  196. return rc;
  197. hp->h = NULL;
  198. return rc;
  199. }
  200. bool cmTakeSeqBldrIsValid( cmTakeSeqBldrH_t h )
  201. { return h.h != NULL; }
  202. cmTsbRC_t cmTakeSeqBldrInitialize( cmTakeSeqBldrH_t h, const cmChar_t* scoreTrkFn )
  203. {
  204. cmTsbRC_t rc = kOkTsbRC;
  205. cmTsb_t* p = _cmTsbHandleToPtr(h);
  206. if(( rc = _cmTsbLoadScoreTrkFile( p, scoreTrkFn )) != kOkTsbRC )
  207. return rc;
  208. if( cmTimeLineInitializeFromFile(&p->ctx, &p->tlH, NULL, NULL, p->tlFn, p->tlPrefixPath ) != kOkTlRC )
  209. {
  210. rc = cmErrMsg(&p->err,kTimeLineFailTsbRC,"The time-line file '%s' could not be loaded.",p->tlFn);
  211. goto errLabel;
  212. }
  213. if( cmScoreInitialize(&p->ctx, &p->scH, p->scFn, 0, NULL, 0, NULL, NULL, cmSymTblNullHandle ) != kOkScRC )
  214. {
  215. rc = cmErrMsg(&p->err,kScoreFailTsbRC,"The score file '%s' could not be loaded.",p->scFn);
  216. goto errLabel;
  217. }
  218. errLabel:
  219. if( rc != kOkTsbRC )
  220. _cmTsbScoreTrkFree(p);
  221. return rc;
  222. }
  223. cmTsbRC_t cmTakeSeqBldrLoadTake( cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL )
  224. {
  225. cmTsbRC_t rc = kOkTsbRC;
  226. return rc;
  227. }
  228. cmTsbRC_t cmTakeSeqBldrUnloadTake( cmTakeSeqBldrH_t h, unsigned tlMarkUid )
  229. {
  230. cmTsbRC_t rc = kOkTsbRC;
  231. return rc;
  232. }
  233. cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId )
  234. {
  235. cmTsbRC_t rc = kOkTsbRC;
  236. return rc;
  237. }
  238. cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId )
  239. {
  240. cmTsbRC_t rc = kOkTsbRC;
  241. return rc;
  242. }
  243. cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl )
  244. {
  245. cmTsbRC_t rc = kOkTsbRC;
  246. return rc;
  247. }
  248. cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl )
  249. {
  250. cmTsbRC_t rc = kOkTsbRC;
  251. return rc;
  252. }
  253. cmTsbRC_t cmTakeSeqBldrMoveNote( cmTakeSeqBldrH_t h, unsigned ssqId, int deltaSmpIdx )
  254. {
  255. cmTsbRC_t rc = kOkTsbRC;
  256. return rc;
  257. }
  258. cmTsbRC_t cmTakeSeqBldrWriteMidiFile( cmTakeSeqBldrH_t h, const char* fn )
  259. {
  260. cmTsbRC_t rc = kOkTsbRC;
  261. return rc;
  262. }
  263. cmTsbRC_t cmTakeSeqBldrTest( cmCtx_t* ctx )
  264. {
  265. const cmChar_t* scoreTrkFn = "/home/kevin/src/cmkc/src/kc/data/assoc0.js";
  266. cmTakeSeqBldrH_t tsbH = cmTakeSeqBldrNullHandle;
  267. cmTsbRC_t tsbRC = kOkTsbRC;
  268. if((tsbRC = cmTakeSeqBldrAllocFn(ctx, &tsbH, scoreTrkFn )) != kOkTsbRC )
  269. return cmErrMsg(&ctx->err,tsbRC,"TSB Allocate and parse '%s' failed.",scoreTrkFn);
  270. if((tsbRC = cmTakeSeqBldrFree(&tsbH)) != kOkTsbRC )
  271. return cmErrMsg(&ctx->err,tsbRC,"TSB Free failed.");
  272. return tsbRC;
  273. }