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.

cmProc4.h 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #ifndef cmProc4_h
  4. #define cmProc4_h
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. //( { file_desc:"Processor Library 4" kw:[proclib]}
  9. //)
  10. //( { label:cmEditDist file_desc:"Simplified string alignment function based on Levenshtein edit distance." kw:[proc] }
  11. enum { kEdMinIdx, kEdSubIdx, kEdDelIdx, kEdInsIdx, kEdCnt };
  12. typedef struct
  13. {
  14. unsigned v[kEdCnt];
  15. bool matchFl;
  16. bool transFl;
  17. } ed_val;
  18. typedef struct ed_path_str
  19. {
  20. unsigned code;
  21. unsigned ri;
  22. unsigned ci;
  23. bool matchFl;
  24. bool transFl;
  25. struct ed_path_str* next;
  26. } ed_path;
  27. /*
  28. Backtracking:
  29. m[rn,cn] is organized to indicate the mutation operations
  30. on s0[0:rn-1] or s1[0:cn-1] during backtracking.
  31. Backtracking begins at cell m[rn-1,cn-1] and proceeds
  32. up and left toward m[0,0]. The action to perform during
  33. backtracking is determined by examinging which values
  34. int m[].v[1:3] match m[].v[0].
  35. Match Next Cell
  36. Index Operation Location
  37. ----- ------------------------ ------------------------
  38. 1 Substitute char s0[ri-1] move diagonally; up-left
  39. 2 Delete char s0[ri-1] move up.
  40. 3 Delete char s1[ci-1] move left.
  41. (same as inserting blank
  42. into after s[ri-1]
  43. Note that more than one value in m[].v[1:3] may match
  44. m[].v[0]. In this case the candidate solution branches
  45. at this point in the candidate selection processes.
  46. */
  47. typedef struct
  48. {
  49. const char* s0; // forms rows of m[] - mutate to match s1 - rn=strlen(s0)
  50. const char* s1; // forms columns of m[] - target string - cn=strlen(s1)
  51. unsigned rn; // length of s0 + 1
  52. unsigned cn; // length of s1 + 1
  53. ed_val* m; // m[rn,cn]
  54. unsigned pn; // rn+cn
  55. ed_path* p_mem; // pmem[ 2*pn ];
  56. ed_path* p_avl; // available path record linked list
  57. ed_path* p_cur; // current path linked list
  58. ed_path* p_opt; // p_opt[pn] current best alignment
  59. double s_opt; // score of the current best alignment
  60. } ed_r;
  61. // print the DP matrix ed_r.m[rn,cn].
  62. void ed_print_mtx( ed_r* r );
  63. // Initialize ed_r.
  64. void ed_init( ed_r* r, const char* s0, const char* s1 );
  65. // Fill in the DP matrix.
  66. void ed_calc_mtx( ed_r* r );
  67. // Traverse the possible alignments in the DP matrix and determine the optimal alignment.
  68. void ed_align( ed_r* r );
  69. // Print the optimal alignment p_opt[]
  70. void ed_print_opt( ed_r* r );
  71. // Free resource allocated by ed_init().
  72. void ed_free(ed_r* r);
  73. // Main test function.
  74. void ed_main();
  75. //------------------------------------------------------------------------------------------------------------
  76. //)
  77. //( { label:cmScoreMatch file_desc:"Event oriented local score matching algorithm based on edit distance." kw:[proc] }
  78. enum
  79. {
  80. kSmMinIdx, //
  81. kSmSubIdx, // 'substitute' - may or may not match
  82. kSmDelIdx, // 'delete' - delete a MIDI note
  83. kSmInsIdx, // 'insert' - insert a space in the score
  84. kSmCnt
  85. };
  86. enum
  87. {
  88. kSmMatchFl = 0x01,
  89. kSmTransFl = 0x02,
  90. kSmTruePosFl = 0x04,
  91. kSmFalsePosFl = 0x08,
  92. kSmBarFl = 0x10,
  93. kSmNoteFl = 0x20
  94. };
  95. // Dynamic Programming (DP) matrix element
  96. typedef struct
  97. {
  98. unsigned v[kSmCnt]; // cost for each operation
  99. unsigned flags; // cmSmMatchFl | cmSmTransFl
  100. unsigned scEvtIdx;
  101. } cmScMatchVal_t;
  102. // List record used to track a path through the DP matrix p->m[,]
  103. typedef struct cmScMatchPath_str
  104. {
  105. unsigned code; // kSmXXXIdx
  106. unsigned ri; // matrix row index
  107. unsigned ci; // matrix col index
  108. unsigned flags; // cmSmMatchFl | cmSmTransFl
  109. unsigned locIdx; // p->loc index or cmInvalidIdx
  110. unsigned scEvtIdx; // scScore event index
  111. struct cmScMatchPath_str* next; //
  112. } cmScMatchPath_t;
  113. typedef struct cmScMatchEvt_str
  114. {
  115. unsigned pitch; //
  116. unsigned scEvtIdx; // scScore event index
  117. } cmScMatchEvt_t;
  118. // Score location record.
  119. typedef struct
  120. {
  121. unsigned evtCnt; // count of score events at this location (i.e. a chord will have more than one event at a given location)
  122. cmScMatchEvt_t* evtV; // evtV[evtCnt]
  123. unsigned scLocIdx; // scH score location index
  124. int barNumb; // bar number of this location
  125. } cmScMatchLoc_t;
  126. typedef struct
  127. {
  128. unsigned mni; // unique identifier for this MIDI note - used to recognize when the cmScMatcher backtracks.
  129. unsigned muid; // MIDI file event msg unique id (See cmMidiTrackMsg_t.uid)
  130. unsigned smpIdx; // time stamp of this event
  131. unsigned pitch; // MIDI note pitch
  132. unsigned vel; // " " velocity
  133. unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a matching or non-matching 'substitute')
  134. unsigned scEvtIdx; // cmScore event index assoc'd with this event
  135. } cmScMatchMidi_t;
  136. typedef struct
  137. {
  138. cmObj obj; //
  139. cmScH_t scH; // cmScore handle
  140. unsigned locN; //
  141. cmScMatchLoc_t* loc; // loc[locN]
  142. unsigned mrn; // max m[] row count (midi)
  143. unsigned rn; // cur m[] row count
  144. unsigned mcn; // max m[] column count (score)
  145. unsigned cn; // cur m[] column count
  146. unsigned mmn; // max length of midiBuf[] (mrn-1)
  147. unsigned msn; // max length of score window (mcn-1)
  148. cmScMatchVal_t* m; // m[mrn,mcn] DP matrix
  149. unsigned pn; // mrn+mcn
  150. cmScMatchPath_t* p_mem; // pmem[ 2*pn ] - path memory
  151. cmScMatchPath_t* p_avl; // available path record linked list
  152. cmScMatchPath_t* p_cur; // current path linked list
  153. cmScMatchPath_t* p_opt; // p_opt[pn] - current best alignment as a linked list
  154. double opt_cost; // last p_opt cost set by cmScMatchExec()
  155. } cmScMatch;
  156. /*
  157. 1) This matcher cannot handle multiple instances of the same pitch occuring
  158. at the same 'location'.
  159. 2) Because each note of a chord is spread out over multiple locations, and
  160. there is no way to indicate that a note in the chord is already 'in-use'.
  161. If a MIDI note which is part of the chord is repeated, in error, it will
  162. appear to be correct (a positive match will be assigned to
  163. the second (and possible successive notes)).
  164. */
  165. cmScMatch* cmScMatchAlloc( cmCtx* c, cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
  166. cmRC_t cmScMatchFree( cmScMatch** pp );
  167. cmRC_t cmScMatchInit( cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
  168. cmRC_t cmScMatchFinal( cmScMatch* p );
  169. // Locate the position in p->loc[locIdx:locIdx+locN-1] which bests
  170. // matches midiV[midiN].
  171. // The result of this function is to update p_opt[]
  172. // The optimal path p_opt[] will only be updated if the edit_cost associated 'midiV[midiN]'.
  173. // with the best match is less than 'min_cost'.
  174. // Set 'min_cost' to DBL_MAX to force p_opt[] to be updated.
  175. // Returns cmEofRC if locIdx + locN > p->locN - note that this is not
  176. // necessarily an error.
  177. cmRC_t cmScMatchExec( cmScMatch* p, unsigned locIdx, unsigned locN, const cmScMatchMidi_t* midiV, unsigned midiN, double min_cost );
  178. //------------------------------------------------------------------------------------------------------------
  179. //)
  180. //( { label:cmScoreMatcher file_desc:"MIDI score following algorithm based cmScoreMatch." kw:[proc] }
  181. typedef struct
  182. {
  183. unsigned locIdx; // index into cmScMatch_t.loc[]
  184. unsigned scEvtIdx; // score event index
  185. unsigned mni; // index of the performed MIDI event associated with this score location
  186. unsigned smpIdx; // sample time index of performed MIDI event
  187. unsigned muid; // MIDI file event msg unique id (See cmMidiTrackMsg_t.uid)
  188. unsigned pitch; // performed pitch
  189. unsigned vel; // performed velocity
  190. unsigned flags; // smTruePosFl | smFalsePosFl
  191. } cmScMatcherResult_t;
  192. struct cmScMatcher_str;
  193. typedef void (*cmScMatcherCb_t)( struct cmScMatcher_str* p, void* arg, cmScMatcherResult_t* rp );
  194. typedef struct cmScMatcher_str
  195. {
  196. cmObj obj;
  197. cmScMatcherCb_t cbFunc;
  198. void* cbArg;
  199. cmScMatch* mp;
  200. unsigned mn;
  201. cmScMatchMidi_t* midiBuf; // midiBuf[mn]
  202. cmScMatcherResult_t* res; // res[rn]
  203. unsigned rn; // length of res[] (set to 2*score event count)
  204. unsigned ri; // next avail res[] recd.
  205. double s_opt; //
  206. unsigned missCnt; // current count of consecutive trailing non-matches
  207. unsigned ili; // index into loc[] to start scan following reset
  208. unsigned eli; // index into loc[] of the last positive match.
  209. unsigned mni; // current count of MIDI events since the last call to cmScMatcherReset()
  210. unsigned mbi; // index of oldest MIDI event in midiBuf[]; stays at 0 when the buffer is full.
  211. unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan
  212. unsigned initHopCnt; // max window hops during the initial (when the MIDI buffer fills for first time) sync scan
  213. unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
  214. unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan.
  215. unsigned scanCnt; // current count of times a resync-scan was executed during cmScMatcherStep()
  216. bool printFl;
  217. } cmScMatcher;
  218. cmScMatcher* cmScMatcherAlloc(
  219. cmCtx* c, // Program context.
  220. cmScMatcher* p, // Existing cmScMatcher to reallocate or NULL to allocate a new cmScMatcher.
  221. double srate, // System sample rate.
  222. cmScH_t scH, // Score handle. See cmScore.h.
  223. unsigned scWndN, // Length of the scores active search area. ** See Notes.
  224. unsigned midiWndN, // Length of the MIDI active note buffer. ** See Notes.
  225. cmScMatcherCb_t cbFunc, // A cmScMatcherCb_t function to be called to notify the recipient of changes in the score matcher status.
  226. void* cbArg ); // User argument to 'cbFunc'.
  227. // Notes:
  228. // The cmScMatcher maintains an internal cmScMatch object which is used to attempt to find the
  229. // best match between the current MIDI active note buffer and the current score search area.
  230. // 'scWndN' is used to set the cmScMatch 'locN' argument.
  231. // 'midiWndN' sets the length of the MIDI FIFO which is used to match to the score with
  232. // each recceived MIDI note.
  233. // 'midiWndN' must be <= 'scWndN'.
  234. cmRC_t cmScMatcherFree( cmScMatcher** pp );
  235. cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg );
  236. cmRC_t cmScMatcherFinal( cmScMatcher* p );
  237. // 'scLocIdx' is a score index as used by cmScoreLoc(scH) not into p->mp->loc[].
  238. cmRC_t cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx );
  239. // Slide a score window 'hopCnt' times, beginning at 'bli' (an
  240. // index into p->mp->loc[]) looking for the best match to p->midiBuf[].
  241. // The score window contain scWndN (p->mp->mcn-1) score locations.
  242. // Returns the index into p->mp->loc[] of the start of the best
  243. // match score window. The score associated
  244. // with this match is stored in s_opt.
  245. unsigned cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned hopCnt );
  246. // Step forward/back by p->stepCnt from p->eli.
  247. // p->eli must therefore be valid prior to calling this function.
  248. // If more than p->maxMissCnt consecutive MIDI events are
  249. // missed then automatically run cmScAlignScan().
  250. // Return cmEofRC if the end of the score is encountered.
  251. // Return cmSubSysFailRC if an internal scan resync. failed.
  252. cmRC_t cmScMatcherStep( cmScMatcher* p );
  253. // This function calls cmScMatcherScan() and cmScMatcherStep() internally.
  254. // If 'status' is not kNonMidiMdId then the function returns without changing the
  255. // state of the object. In other words the matcher only recognizes MIDI note-on messages.
  256. // If the MIDI note passed by the call results in a successful match then
  257. // p->eli will be updated to the location in p->mp->loc[] of the latest
  258. // match, the MIDI note in p->midiBuf[] associated with this match
  259. // will be assigned a valid locIdx and scLocIdx values, and *scLocIdxPtr
  260. // will be set with the matched scLocIdx of the match.
  261. // If this call does not result in a successful match *scLocIdxPtr is set
  262. // to cmInvalidIdx.
  263. // 'muid' is the unique id associated with this MIDI event under the circumstances
  264. // that the event came from a MIDI file. See cmMidiFile.h cmMidiTrackMsg_t.uid.
  265. // Return:
  266. // cmOkRC - Continue processing MIDI events.
  267. // cmEofRC - The end of the score was encountered.
  268. // cmInvalidArgRC - scan failed or the object was in an invalid state to attempt a match.
  269. // cmSubSysFailRC - a scan resync failed in cmScMatcherStep().
  270. cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned muid, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1, unsigned* scLocIdxPtr );
  271. void cmScMatcherPrint( cmScMatcher* p );
  272. //------------------------------------------------------------------------------------------------------------
  273. //)
  274. //( { label:cmScMeas file_desc:"Measure and report some differences between the score and the performance." kw:[proc] }
  275. typedef struct
  276. {
  277. cmScoreSet_t* sp; // ptr to this set in the score
  278. unsigned bsei; // begin score event index
  279. unsigned esei; // end score event index
  280. unsigned bsli; // beg score loc index
  281. unsigned esli; // end score loc index
  282. unsigned bli; // index into the cmScMatch.loc[] array of bsli
  283. unsigned eli; // index into the cmScMatch.loc[] array of esli
  284. double value; // DBL_MAX if the value has not yet been set
  285. double tempo; //
  286. double match_cost; // cost of the match to the performance divided by sp->eleCnt
  287. } cmScMeasSet_t;
  288. typedef struct
  289. {
  290. cmObj obj;
  291. double srate; //
  292. cmScMatch* mp; //
  293. unsigned mii; // next avail recd in midiBuf[]
  294. unsigned mn; // length of of midiBuf[] (init. to 2*cmScoreEvtCount())
  295. cmScMatchMidi_t* midiBuf; // midiBuf[mn]
  296. unsigned sn; // length of set[] (init. to cmScoreSetCount())
  297. cmScMeasSet_t* set; // set[sn]
  298. unsigned dn; // length of dynRef[]
  299. unsigned* dynRef; // dynRef[dn]
  300. unsigned nsi; // next set index to fill (this is the set[] we are waiting to complete)
  301. unsigned nsli; // next score location index we are expecting to receive
  302. unsigned vsi; // set[vsi:nsi-1] indicates sets with new values following a call to cmScMeasExec()
  303. unsigned vsli; // vsli:nsli-1 indicates cmScore loc's to check for section triggers following a call to cmScMeasExec()
  304. } cmScMeas;
  305. //
  306. // Notes:
  307. //
  308. // 1) midiBuf[] stores all MIDI notes for the duration of the performance
  309. // it is initialized to 2*score_event_count.
  310. //
  311. // 2) dynRef[] is the gives the MIDI velocity range for each dynamics
  312. // category: pppp-fff
  313. //
  314. // 3) See a cmDspKr.c _cmScFolMatcherCb() for an example of how
  315. // cmScMeas.vsi and cmScMeas.vsli are used to act on the results of
  316. // a call to cmMeasExec().
  317. cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
  318. cmRC_t cmScMeasFree( cmScMeas** pp );
  319. cmRC_t cmScMeasInit( cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
  320. cmRC_t cmScMeasFinal( cmScMeas* p );
  321. // Empty MIDI buffer and set the next set nsi and nsli to zero.
  322. cmRC_t cmScMeasReset( cmScMeas* p );
  323. // This function is called for each input MIDI note which is assigned a
  324. // score location by cmScMatcher.
  325. // 'mni' is the MIDI event index which uniquely identifies this MIDI event.
  326. // 'locIdx' is the location index into cmScMatcher.mp->loc[] associated with
  327. // this event.
  328. cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtIdx, unsigned flags, unsigned smpIdx, unsigned pitch, unsigned vel );
  329. //=======================================================================================================================
  330. unsigned cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
  331. // Given a score, a time-line, and a marker on the time line scan the
  332. // entire score looking for the best match between the first 'midiN'
  333. // notes in each marker region and the score.
  334. void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
  335. //------------------------------------------------------------------------------------------------------------
  336. //)
  337. //( { label:cmScMod file_desc:"Store and recall parameter information under score follower control." kw:[proc] }
  338. /*
  339. File format:
  340. {
  341. entry_group_label :
  342. [
  343. <loc> <mod> <var> <type> <params> // entry record
  344. ]
  345. }
  346. Syntax: <loc> <mod> <var> <type> <params>
  347. <loc> - score location
  348. <mod> - name of the modulator
  349. <var> - variable name
  350. <type> - type of operation (see Types: note below)
  351. <params>
  352. <min> - set a variable min value
  353. <max> - set a variable max value
  354. <rate> - limit how often a variable is transmitted while it is ramping
  355. <val> - type dependent value - see 'Types' below.
  356. <end> - ending value for a ramping variable
  357. <dur> - determines the length of time to get to the ending value
  358. <in> - set to '1' to indicate that this is an input variable
  359. The value of parameters may be literal numeric values or may refer to
  360. variables by their name.
  361. Types:
  362. set = set <var> to <val> which may be a literal or another variable.
  363. line = ramp from its current value to <val> over <dur> seconds
  364. sline = set <var> to <val> and ramp to <end> over <dur> seconds
  365. post = send a 'post' msg after each transmission (can be used to change the cross-fader after each msg)
  366. exec = execute the entry group <val>
  367. input = declare an 'input' variable and set its <min> and <max>.
  368. cross = generate an output value by interpolating between two preset values.
  369. */
  370. enum
  371. {
  372. kInvalidModTId,
  373. kDeclModTId, // declare a variable but do not associate a value with it (allows a variable to be connected to w/o sending a value)
  374. kSetModTId, // set variable to parray[0] at scLocIdx
  375. kLineModTId, // linear ramp variable to parray[0] over parray[1] seconds
  376. kSetLineModTId, // set variable to parray[0] and ramp to parray[1] over parray[2] seconds
  377. kPostModTId, //
  378. kExecModTId, // execute an entry group
  379. kInputModTId, // This is an 'input' variable.
  380. kCrossModTId // generate an output value by interpolating between two preset variable values
  381. };
  382. enum
  383. {
  384. kActiveModFl = 0x01, // this variable is on the 'active' list
  385. kCalcModFl = 0x02, // when this variable is used as a parameter it's value must be calculated rather than used directly.
  386. kInputModFl = 0x04 // this is an input variable
  387. };
  388. struct cmScModEntry_str;
  389. typedef enum
  390. {
  391. kInvalidModPId,
  392. kLiteralModPId, // this is a literal value
  393. kSymbolModPId //
  394. } cmScModPId_t;
  395. typedef struct cmScModParam_str
  396. {
  397. cmScModPId_t pid; // parameter type: literal or symbol
  398. unsigned symId; // symbol of external and internal variables
  399. double val; // value of literals
  400. } cmScModParam_t;
  401. // cmScModVar_t is used to track the value of a variable.
  402. typedef struct cmScModVar_str
  403. {
  404. unsigned flags; // see kXXXModFl flags above.
  405. unsigned varSymId; // variable name
  406. unsigned varId; // var id
  407. double value; // current value of this variable
  408. double v0; // reserved internal variable
  409. unsigned phase; // cycle phase since activation
  410. double min;
  411. double max;
  412. double rate; // output rate in milliseconds (use
  413. struct cmScModEntry_str* entry; // last entry assoc'd with this value
  414. struct cmScModVar_str* vlink; // p->vlist link
  415. struct cmScModVar_str* alink; // p->alist link
  416. } cmScModVar_t;
  417. // Each entry gives a time tagged location and some parameters
  418. // for an algorthm which is used to set/modulate a value.
  419. typedef struct cmScModEntry_str
  420. {
  421. unsigned scLocIdx; // entry start time
  422. unsigned typeId; // variable type
  423. cmScModParam_t beg; // parameter values
  424. cmScModParam_t end; //
  425. cmScModParam_t dur; //
  426. cmScModParam_t min; // min value for this variable
  427. cmScModParam_t max; // max value for this variable
  428. cmScModParam_t rate; // update rate in milliseconds (DBL_MAX to disable)
  429. cmScModParam_t arg; // cross input variable
  430. cmScModVar_t* varPtr; // target variable
  431. } cmScModEntry_t;
  432. typedef struct cmScModEntryGroup_str
  433. {
  434. unsigned symId; // this groups label
  435. cmScModEntry_t* earray; // entries associated with this group
  436. unsigned en; // earray[en]
  437. struct cmScModEntryGroup_str* link;
  438. } cmScModEntryGroup_t;
  439. typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value, bool postFl );
  440. typedef struct
  441. {
  442. cmObj obj;
  443. cmChar_t* fn; // modulator score file
  444. unsigned modSymId; // modulator name
  445. cmSymTblH_t stH; // symbol table used by this modulator
  446. cmScModCb_t cbFunc; // active value callback function
  447. void* cbArg; // first arg to cbFunc()
  448. unsigned samplesPerCycle; // interval in samples between calls to cmScModulatorExec()
  449. double srate; // system sample rate
  450. cmScModVar_t* vlist; // variable list
  451. cmScModVar_t* alist; // active variable list
  452. cmScModVar_t* elist; // last element on the active list
  453. unsigned nei; // next entry index in xlist->earray[] to examine for activation
  454. unsigned outVarCnt; // count of unique vars that are targets of entry recds
  455. unsigned inVarCnt;
  456. bool postFl; // send a 'post' msg after each transmission
  457. cmScModEntryGroup_t* xlist; // entry group to execute
  458. cmScModEntryGroup_t* glist; // entry group list
  459. } cmScModulator;
  460. cmScModulator* cmScModulatorAlloc( cmCtx* c, cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, double srate, unsigned samplesPerCycle, const cmChar_t* fn, const cmChar_t* modLabel, cmScModCb_t cbFunc, void* cbArg );
  461. cmRC_t cmScModulatorFree( cmScModulator** pp );
  462. cmRC_t cmScModulatorInit( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, double srate, unsigned samplesPerCycle, const cmChar_t* fn, const cmChar_t* modLabel, cmScModCb_t cbFunc, void* cbArg );
  463. cmRC_t cmScModulatorFinal( cmScModulator* p );
  464. // Return count of variables.
  465. unsigned cmScModulatorOutVarCount( cmScModulator* p );
  466. // Return a pointer to the variable at vlist[idx].
  467. cmScModVar_t* cmScModulatorOutVar( cmScModulator* p, unsigned idx );
  468. unsigned cmScModulatorInVarCount( cmScModulator* p );
  469. cmScModVar_t* cmScModulatorInVar( cmScModulator* p, unsigned idx );
  470. cmRC_t cmScModulatorSetValueMinMax( cmScModulator* p, unsigned varSymId, double value, double min, double max );
  471. cmRC_t cmScModulatorSetValue( cmScModulator* p, unsigned varSymId, double value );
  472. cmRC_t cmScModulatorReset( cmScModulator* p, cmCtx_t* ctx, unsigned scLocIdx, unsigned entryGroupSymId );
  473. cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx );
  474. cmRC_t cmScModulatorDump( cmScModulator* p );
  475. //------------------------------------------------------------------------------------------------------------
  476. //)
  477. //( { label:cmRecdPlay file_desc:"Record fragments of audio, store them,and play them back at a later time." kw:[proc] }
  478. //
  479. // Record fragments of audio, store them, and play them back at a later time.
  480. //
  481. typedef struct cmRecdPlayFrag_str
  482. {
  483. unsigned labelSymId; // this fragments label
  484. cmSample_t** chArray; // record buffer chArray[cmRecdPlay.chCnt][allocCnt]
  485. unsigned allocCnt; // count of samples allocated to each channel
  486. unsigned playIdx; // index of next sample to play
  487. unsigned recdIdx; // index of next sample to receieve audio (count of full samples)
  488. double fadeDbPerSec; // fade rate in dB per second
  489. unsigned fadeSmpIdx;
  490. struct cmRecdPlayFrag_str* rlink; // cmRecdPlay.rlist link
  491. struct cmRecdPlayFrag_str* plink; // cmRecdPlay.plist link
  492. } cmRecdPlayFrag;
  493. typedef struct
  494. {
  495. cmObj obj;
  496. cmRecdPlayFrag* frags; // frags[fragCnt] fragment array
  497. unsigned fragCnt; // count of fragments
  498. double srate; // system sample rate
  499. unsigned chCnt; // count of input and output audio channels
  500. double initFragSecs; // size initial memory allocated to each frag in seconds
  501. unsigned maxLaSmpCnt; // samples allocated to each channel of the look-ahead buffers.
  502. unsigned curLaSmpCnt; // current look-ahead time in samples (curLaSmpCnt<=maxLaSmpCnt)
  503. cmSample_t** laChs; // laChs[chCnt][maxLaSmpCnt] - look-ahead buffers
  504. int laSmpIdx; // next look-ahead buffer index to receive a sample
  505. cmRecdPlayFrag* plist; // currently playing frags
  506. cmRecdPlayFrag* rlist; // currently recording frags
  507. } cmRecdPlay;
  508. // srate - system sample rate
  509. // fragCnt - total count of samples to record
  510. // chCnt - count of input and output audio channels.
  511. // initFragSecs - amount of memory to pre-allocate for each fragment.
  512. // maxLaSecs - maximum value for curLaSecs
  513. // curLaSecs - current duration of look-ahead buffer
  514. //
  515. // The look-ahead buffer is a circular buffer which hold the previous 'curLaSecs' seconds
  516. // of incoming audio. When recording is enabled with via cmRecdPlayBeginRecord() the
  517. // look ahead buffer is automatically prepended to the fragment.
  518. cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
  519. cmRC_t cmRecdPlayFree( cmRecdPlay** pp );
  520. cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
  521. cmRC_t cmRecdPlayFinal( cmRecdPlay* p );
  522. cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId );
  523. cmRC_t cmRecdPlaySetLaSecs( cmRecdPlay* p, double curLaSecs );
  524. // Deactivates all active recorders and players, zeros the look-ahead buffer and
  525. // rewinds all fragment play positions. This function does not clear the audio from
  526. // frabments that have already been recorded.
  527. cmRC_t cmRecdPlayRewind( cmRecdPlay* p );
  528. cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId );
  529. cmRC_t cmRecdPlayEndRecord( cmRecdPlay* p, unsigned labelSymId );
  530. cmRC_t cmRecdPlayInsertRecord(cmRecdPlay* p, unsigned labelSymId, const cmChar_t* wavFn );
  531. cmRC_t cmRecdPlayBeginPlay( cmRecdPlay* p, unsigned labelSymId );
  532. cmRC_t cmRecdPlayEndPlay( cmRecdPlay* p, unsigned labelSymId );
  533. // Begin fading out the specified fragment at a rate deteremined by 'dbPerSec'.
  534. cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec );
  535. cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt );
  536. //)
  537. #ifdef __cplusplus
  538. }
  539. #endif
  540. #endif