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

cmDspKr.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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 "cmFile.h"
  12. #include "cmSymTbl.h"
  13. #include "cmJson.h"
  14. #include "cmPrefs.h"
  15. #include "cmDspValue.h"
  16. #include "cmMsgProtocol.h"
  17. #include "cmThread.h"
  18. #include "cmUdpPort.h"
  19. #include "cmUdpNet.h"
  20. #include "cmAudioSys.h"
  21. #include "cmDspCtx.h"
  22. #include "cmDspClass.h"
  23. #include "cmDspUi.h"
  24. #include "cmOp.h"
  25. #include "cmMath.h"
  26. #include "cmAudioFile.h"
  27. #include "cmFileSys.h"
  28. #include "cmProcObj.h"
  29. #include "cmProcTemplateMain.h"
  30. #include "cmProc.h"
  31. #include "cmMidi.h"
  32. #include "cmProc2.h"
  33. #include "cmVectOpsTemplateMain.h"
  34. #include "cmAudioFile.h"
  35. #include "cmMidiFile.h"
  36. #include "cmTimeLine.h"
  37. enum
  38. {
  39. kWndSmpCntKrId,
  40. kHopFactKrId,
  41. kModeKrId,
  42. kThreshKrId,
  43. kLwrSlopeKrId,
  44. kUprSlopeKrId,
  45. kOffsetKrId,
  46. kInvertKrId,
  47. kAudioInKrId,
  48. kAudioOutKrId
  49. };
  50. typedef struct
  51. {
  52. cmDspInst_t inst;
  53. cmCtx* ctx;
  54. cmSpecDist_t* sdp;
  55. } cmDspKr_t;
  56. cmDspClass_t _cmKrDC;
  57. //==========================================================================================================================================
  58. cmDspInst_t* _cmDspKrAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  59. {
  60. cmDspVarArg_t args[] =
  61. {
  62. { "wndn", kWndSmpCntKrId, 0, 0, kInDsvFl | kUIntDsvFl | kReqArgDsvFl, "Window sample count" },
  63. { "hopf", kHopFactKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Hop factor" },
  64. { "mode", kModeKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Mode 0=bypass 1=basic 2=spec cnt 3=amp env" },
  65. { "thrh", kThreshKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Threshold" },
  66. { "lwrs", kLwrSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Lower Slope"},
  67. { "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
  68. { "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"},
  69. { "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"},
  70. { "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
  71. { "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
  72. { NULL, 0, 0, 0, 0 }
  73. };
  74. cmDspKr_t* p = cmDspInstAlloc(cmDspKr_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  75. unsigned defWndSmpCnt = cmDspDefaultUInt(&p->inst,kWndSmpCntKrId);
  76. unsigned wndSmpCnt = cmNextPowerOfTwo( defWndSmpCnt );
  77. cmDspSetDefaultUInt( ctx,&p->inst, kWndSmpCntKrId, defWndSmpCnt, wndSmpCnt );
  78. cmDspSetDefaultUInt( ctx,&p->inst, kHopFactKrId, 0, 4 );
  79. cmDspSetDefaultUInt( ctx,&p->inst, kModeKrId, 0, kBasicModeSdId );
  80. cmDspSetDefaultDouble( ctx,&p->inst, kThreshKrId, 0, 60.0 );
  81. cmDspSetDefaultDouble( ctx,&p->inst, kLwrSlopeKrId, 0, 2.0 );
  82. cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 );
  83. cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0);
  84. cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 );
  85. //_cmDspKrCmInit(ctx,p); // initialize the cm library
  86. p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
  87. return &p->inst;
  88. }
  89. cmDspRC_t _cmDspKrFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  90. {
  91. cmDspRC_t rc = kOkDspRC;
  92. cmDspKr_t* p = (cmDspKr_t*)inst;
  93. cmSpecDistFree(&p->sdp);
  94. cmCtxFree(&p->ctx);
  95. //_cmDspKrCmFinal(ctx,p); // finalize the cm library
  96. return rc;
  97. }
  98. cmDspRC_t _cmDspKrSetup(cmDspCtx_t* ctx, cmDspKr_t* p )
  99. {
  100. cmDspRC_t rc = kOkDspRC;
  101. unsigned wndSmpCnt = cmDspUInt(&p->inst,kWndSmpCntKrId);
  102. unsigned hopFact = cmDspUInt(&p->inst,kHopFactKrId);
  103. unsigned olaWndTypeId = kHannWndId;
  104. cmSpecDistFree(&p->sdp);
  105. p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
  106. assert(p->sdp != NULL );
  107. if((rc = cmDspZeroAudioBuf(ctx,&p->inst,kAudioOutKrId)) != kOkDspRC )
  108. return rc;
  109. return rc;
  110. }
  111. cmDspRC_t _cmDspKrReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  112. {
  113. cmDspKr_t* p = (cmDspKr_t*)inst;
  114. cmDspRC_t rc;
  115. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  116. return rc;
  117. return _cmDspKrSetup(ctx,p);
  118. }
  119. cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  120. {
  121. cmDspKr_t* p = (cmDspKr_t*)inst;
  122. cmDspRC_t rc = kOkDspRC;
  123. unsigned iChIdx = 0;
  124. const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKrId,iChIdx);
  125. unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKrId);
  126. unsigned oChIdx = 0;
  127. cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKrId,oChIdx);
  128. unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
  129. const cmSample_t* sp;
  130. cmSpecDistExec(p->sdp,ip,iSmpCnt);
  131. if((sp = cmSpecDistOut(p->sdp)) != NULL )
  132. vs_Copy(op,sp,oSmpCnt);
  133. return rc;
  134. }
  135. cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  136. {
  137. cmDspKr_t* p = (cmDspKr_t*)inst;
  138. cmDspRC_t rc = kOkDspRC;
  139. cmDspSetEvent(ctx,inst,evt);
  140. switch( evt->dstVarId )
  141. {
  142. case kWndSmpCntKrId:
  143. case kHopFactKrId:
  144. _cmDspKrSetup(ctx,p);
  145. printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
  146. break;
  147. case kModeKrId:
  148. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  149. printf("mode:%i\n",p->sdp->mode);
  150. break;
  151. case kThreshKrId:
  152. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  153. break;
  154. case kUprSlopeKrId:
  155. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  156. printf("upr slope:%f\n",p->sdp->uprSlope);
  157. break;
  158. case kLwrSlopeKrId:
  159. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  160. printf("upr slope:%f\n",p->sdp->lwrSlope);
  161. break;
  162. case kOffsetKrId:
  163. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  164. break;
  165. case kInvertKrId:
  166. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  167. break;
  168. default:
  169. { assert(0); }
  170. }
  171. return rc;
  172. }
  173. struct cmDspClass_str* cmKrClassCons( cmDspCtx_t* ctx )
  174. {
  175. cmDspClassSetup(&_cmKrDC,ctx,"Kr",
  176. NULL,
  177. _cmDspKrAlloc,
  178. _cmDspKrFree,
  179. _cmDspKrReset,
  180. _cmDspKrExec,
  181. _cmDspKrRecv,
  182. NULL,NULL,
  183. "Fourier based non-linear transformer.");
  184. return &_cmKrDC;
  185. }
  186. //==========================================================================================================================================
  187. enum
  188. {
  189. kTlFileTlId,
  190. kAudPathTlId,
  191. kSelTlId,
  192. kAudFnTlId,
  193. kMidiFnTlId,
  194. kBegSmpIdxTlId,
  195. kEndSmpIdxTlId
  196. };
  197. cmDspClass_t _cmTimeLineDC;
  198. typedef struct
  199. {
  200. cmDspInst_t inst;
  201. cmTlH_t tlH;
  202. } cmDspTimeLine_t;
  203. cmDspInst_t* _cmDspTimeLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  204. {
  205. cmDspVarArg_t args[] =
  206. {
  207. { "tlfile", kTlFileTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line file." },
  208. { "path", kAudPathTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Audio path" },
  209. { "sel", kSelTlId, 0, 0, kInDsvFl | kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected marker id."},
  210. { "afn", kAudFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected Audio file." },
  211. { "mfn", kMidiFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected MIDI file." },
  212. { "bsi", kBegSmpIdxTlId, 0, 0, kOutDsvFl | kUIntDsvFl, "Begin audio sample index."},
  213. { "esi", kEndSmpIdxTlId, 0, 0, kOutDsvFl | kUIntDsvFl, "End audio sample index."},
  214. { NULL, 0, 0, 0, 0 }
  215. };
  216. cmDspTimeLine_t* p = cmDspInstAlloc(cmDspTimeLine_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  217. cmDspSetDefaultUInt( ctx, &p->inst, kSelTlId, 0, cmInvalidId);
  218. cmDspSetDefaultStrcz( ctx, &p->inst, kAudFnTlId, NULL, "");
  219. cmDspSetDefaultStrcz( ctx, &p->inst, kMidiFnTlId, NULL, "");
  220. cmDspSetDefaultUInt( ctx, &p->inst, kBegSmpIdxTlId, 0, cmInvalidIdx);
  221. cmDspSetDefaultUInt( ctx, &p->inst, kEndSmpIdxTlId, 0, cmInvalidIdx);
  222. // create the UI control
  223. cmDspUiTimeLineCreate(ctx,&p->inst,kTlFileTlId,kAudPathTlId,kSelTlId);
  224. p->tlH = cmTimeLineNullHandle;
  225. return &p->inst;
  226. }
  227. cmDspRC_t _cmDspTimeLineFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  228. {
  229. cmDspRC_t rc = kOkDspRC;
  230. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  231. if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
  232. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Time-line finalize failed.");
  233. return rc;
  234. }
  235. cmDspRC_t _cmDspTimeLineReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  236. {
  237. cmDspRC_t rc = kOkDspRC;
  238. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  239. cmDspApplyAllDefaults(ctx,inst);
  240. const cmChar_t* tlFn;
  241. if((tlFn = cmDspStrcz(inst, kTlFileTlId )) != NULL )
  242. if( cmTimeLineInitializeFromFile(ctx->cmCtx, &p->tlH, NULL, NULL, tlFn ) != kOkTlRC )
  243. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Time-line file open failed.");
  244. return rc;
  245. }
  246. cmDspRC_t _cmDspTimeLineRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  247. {
  248. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  249. switch( evt->dstVarId )
  250. {
  251. case kSelTlId:
  252. {
  253. unsigned markerId;
  254. cmDspSetEvent(ctx,inst,evt);
  255. // get the id of the selected marker
  256. if((markerId = cmDspUInt(inst,kSelTlId)) != cmInvalidId )
  257. {
  258. // get the marker object
  259. cmTlObj_t* op;
  260. if((op = cmTimeLineIdToObj(p->tlH, cmInvalidId, markerId )) != NULL )
  261. {
  262. assert(op->typeId == kMarkerTlId);
  263. cmDspSetUInt(ctx, inst, kBegSmpIdxTlId, op->begSmpIdx );
  264. cmDspSetUInt(ctx, inst, kEndSmpIdxTlId, op->begSmpIdx + op->durSmpCnt );
  265. // locate the audio file assoc'd with the marker
  266. cmTlAudioFile_t* afp;
  267. if((afp = cmTimeLineAudioFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL)
  268. cmDspSetStrcz(ctx, inst, kAudFnTlId, afp->fn );
  269. // locate the midi file assoc'd with the marker
  270. cmTlMidiFile_t* mfp;
  271. if((mfp = cmTimeLineMidiFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL )
  272. cmDspSetStrcz(ctx, inst, kMidiFnTlId, mfp->fn );
  273. }
  274. }
  275. }
  276. break;
  277. default:
  278. {assert(0);}
  279. }
  280. return kOkDspRC;
  281. }
  282. struct cmDspClass_str* cmTimeLineClassCons( cmDspCtx_t* ctx )
  283. {
  284. cmDspClassSetup(&_cmTimeLineDC,ctx,"TimeLine",
  285. NULL,
  286. _cmDspTimeLineAlloc,
  287. _cmDspTimeLineFree,
  288. _cmDspTimeLineReset,
  289. NULL,
  290. _cmDspTimeLineRecv,
  291. NULL,NULL,
  292. "Time Line control.");
  293. return &_cmTimeLineDC;
  294. }
  295. //==========================================================================================================================================
  296. //
  297. //
  298. // Read files created by this object with the Octave function cmTextFile().
  299. //
  300. //
  301. enum
  302. {
  303. kFnMfId,
  304. kSelMfId,
  305. kBsiMfId,
  306. kEsiMfId,
  307. kStatusMfId,
  308. kD0MfId,
  309. kD1MfId
  310. };
  311. cmDspClass_t _cmMidiFilePlayDC;
  312. typedef struct
  313. {
  314. cmDspInst_t inst;
  315. cmMidiFileH_t mfH;
  316. unsigned msgIdx; // current midi file msg index
  317. unsigned bsi;
  318. unsigned esi;
  319. unsigned startSymId;
  320. unsigned stopSymId;
  321. unsigned contSymId;
  322. } cmDspMidiFilePlay_t;
  323. /*
  324. 'bsi' and 'esi' give the starting and ending sample for MIDI file playback.
  325. These indexes are relative to the start of the file.
  326. When the player recieves a 'start' msg it sets the current sample index
  327. 'si' to 'bsi' and begins scanning for the next note to play.
  328. On each call to the _cmDspMidiFilePlayExec() msgs that fall in the interval
  329. si:si+sPc-1 will be transmitted. (where sPc are the number of samples per DSP cycle).
  330. */
  331. cmDspInst_t* _cmDspMidiFilePlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  332. {
  333. cmDspVarArg_t args[] =
  334. {
  335. { "fn", kFnMfId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "File name"},
  336. { "sel", kSelMfId, 0, 0, kInDsvFl | kSymDsvFl, "start | stop | continue" },
  337. { "bsi", kBsiMfId, 0, 0, kInDsvFl | kUIntDsvFl, "Starting sample." },
  338. { "esi", kEsiMfId, 0, 0, kInDsvFl | kUIntDsvFl, "Ending sample."},
  339. { "status", kStatusMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Status value output" },
  340. { "d0", kD0MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 0" },
  341. { "d1", kD1MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 1" },
  342. { NULL, 0, 0, 0, 0 }
  343. };
  344. cmDspMidiFilePlay_t* p = cmDspInstAlloc(cmDspMidiFilePlay_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  345. cmDspSetDefaultUInt( ctx, &p->inst, kStatusMfId, 0, 0);
  346. cmDspSetDefaultUInt( ctx, &p->inst, kD0MfId, 0, 0);
  347. cmDspSetDefaultUInt( ctx, &p->inst, kD1MfId, 0, 0);
  348. p->startSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"start");
  349. p->stopSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"stop");
  350. p->contSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"continue");
  351. p->mfH = cmMidiFileNullHandle;
  352. return &p->inst;
  353. }
  354. cmDspRC_t _cmDspMidiFilePlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  355. {
  356. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  357. if( cmMidiFileClose(&p->mfH) )
  358. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "MIDI file close failed.");
  359. return kOkDspRC;
  360. }
  361. // return the index of the msg following smpIdx
  362. unsigned _cmDspMidiFilePlaySeekMsgIdx( cmDspCtx_t* ctx, cmDspMidiFilePlay_t* p, unsigned smpIdx )
  363. {
  364. unsigned i;
  365. unsigned n = cmMidiFileMsgCount(p->mfH);
  366. const cmMidiTrackMsg_t** a = cmMidiFileMsgArray(p->mfH);
  367. double srate = cmDspSampleRate(ctx);
  368. for(i=0; i<n; ++i)
  369. if( floor(a[i]->dtick*srate) > smpIdx )
  370. break;
  371. return i==n ? cmInvalidIdx : i;
  372. }
  373. cmDspRC_t _cmDspMidiFilePlayOpen(cmDspCtx_t* ctx, cmDspInst_t* inst )
  374. {
  375. cmDspRC_t rc = kOkDspRC;
  376. const cmChar_t* fn = cmDspStrcz(inst,kFnMfId);
  377. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  378. if( cmMidiFileOpen( fn, &p->mfH, ctx->cmCtx ) != kOkFileRC )
  379. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "MIDI file open failed.");
  380. else
  381. {
  382. p->msgIdx = 0;
  383. p->bsi = cmDspUInt(inst,kBsiMfId);
  384. p->esi = cmDspUInt(inst,kEsiMfId);
  385. cmMidiFileTickToMicros(p->mfH);
  386. }
  387. return rc;
  388. }
  389. cmDspRC_t _cmDspMidiFilePlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  390. {
  391. cmDspApplyAllDefaults(ctx,inst);
  392. return _cmDspMidiFilePlayOpen(ctx,inst);
  393. }
  394. cmDspRC_t _cmDspMidiFilePlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  395. {
  396. cmDspRC_t rc = kOkDspRC;
  397. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  398. double srate = cmDspSampleRate(ctx);
  399. unsigned sPc = cmDspSamplesPerCycle(ctx);
  400. return rc;
  401. }
  402. cmDspRC_t _cmDspMidiFilePlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  403. {
  404. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  405. cmDspSetEvent(ctx,inst,evt);
  406. switch(evt->dstVarId)
  407. {
  408. case kFnMfId:
  409. _cmDspMidiFilePlayOpen(ctx, inst );
  410. break;
  411. case kSelMfId:
  412. {
  413. if( cmDspSymbol(inst,kSelMfId)==p->startSymId )
  414. {
  415. _cmDspMidiFilePlaySeekMsgIdx(ctx, p, cmDspUInt(inst,kBsiMfId) );
  416. }
  417. break;
  418. }
  419. }
  420. return kOkDspRC;
  421. }
  422. struct cmDspClass_str* cmMidiFilePlayClassCons( cmDspCtx_t* ctx )
  423. {
  424. cmDspClassSetup(&_cmMidiFilePlayDC,ctx,"MidiFilePlay",
  425. NULL,
  426. _cmDspMidiFilePlayAlloc,
  427. _cmDspMidiFilePlayFree,
  428. _cmDspMidiFilePlayReset,
  429. _cmDspMidiFilePlayExec,
  430. _cmDspMidiFilePlayRecv,
  431. NULL,NULL,
  432. "Time tagged text file.");
  433. return &_cmMidiFilePlayDC;
  434. }