libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmProc4.h 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. #ifndef cmProc4_h
  2. #define cmProc4_h
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. typedef struct
  7. {
  8. unsigned smpIdx; // time tag sample index for val
  9. cmMidiByte_t val; //
  10. bool validFl; //
  11. } cmScFolBufEle_t;
  12. typedef struct
  13. {
  14. unsigned pitch;
  15. unsigned scEvtIdx;
  16. } cmScFolEvt_t;
  17. typedef struct
  18. {
  19. unsigned evtCnt; //
  20. cmScFolEvt_t* evtV; // pitchV[pitchCnt]
  21. unsigned scIdx; // index of the score loc (into cmScoreEvt[]) at this location
  22. int barNumb; // bar number of this location
  23. } cmScFolLoc_t;
  24. typedef struct
  25. {
  26. cmObj obj;
  27. cmReal_t srate; //
  28. cmScH_t scH; // score handle
  29. unsigned bufN; // event buffer count
  30. cmScFolBufEle_t* bufV; // event buffer bufV[bufN] - bufV[bufN-1] newest event, bufV[boi] oldest event
  31. int locN; // count of score locations
  32. cmScFolLoc_t* loc; // score loc[locN]
  33. unsigned sbi; // oldest score window index
  34. unsigned sei; // newest score window index
  35. unsigned msln; // minimum score look ahead count
  36. unsigned mswn; // maximum score window length
  37. unsigned forwardCnt; // count of score loc's to look ahead for a match to the current pitch when the optimal edit-dist alignment does not produce a match for the current pitch
  38. unsigned maxDist; // max. dist allowed to still consider matching
  39. unsigned minVel; // notes < minVel are ignored
  40. bool printFl; // true if pitch tracker reporting should be included
  41. bool noBackFl; // prevent the tracker from going backwards in time
  42. unsigned* edWndMtx;
  43. unsigned missCnt; // current consecutive unmatched notes
  44. unsigned matchCnt; // current consecutive matched notes
  45. unsigned eventIdx; // events since reset
  46. unsigned skipCnt; // notes skipped due to velocity
  47. unsigned ret_idx; // last tracked location
  48. } cmScFol;
  49. cmScFol* cmScFolAlloc( cmCtx* ctx, cmScFol* p, cmReal_t srate, cmScH_t scH, unsigned bufN, unsigned minWndLookAhead, unsigned maxWndCnt, unsigned minVel );
  50. cmRC_t cmScFolFree( cmScFol** pp );
  51. cmRC_t cmScFolInit( cmScFol* p, cmReal_t srate, cmScH_t scH, unsigned bufN, unsigned minWndLookAhead, unsigned maxWndCnt, unsigned minVel );
  52. cmRC_t cmScFolFinal( cmScFol* p );
  53. // Jump to a score location and reset the internal state of the follower.
  54. cmRC_t cmScFolReset( cmScFol* p, unsigned scoreIndex );
  55. // Give the follower a MIDI performance event. Only MIDI note-on events are acted upon;
  56. // all others are ignored.
  57. unsigned cmScFolExec( cmScFol* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  58. //=======================================================================================================================
  59. typedef struct
  60. {
  61. unsigned pitch;
  62. unsigned scEvtIdx;
  63. bool matchFl;
  64. } cmScTrkEvt_t;
  65. typedef struct
  66. {
  67. unsigned evtCnt; //
  68. cmScTrkEvt_t* evtV; // evtV[evtCnt]
  69. unsigned scIdx; // index of the score event (into cmScoreEvt[]) at this location
  70. int barNumb; // bar number of this location
  71. } cmScTrkLoc_t;
  72. typedef struct
  73. {
  74. cmObj obj;
  75. cmScFol* sfp;
  76. double srate;
  77. cmScH_t scH;
  78. unsigned locN;
  79. cmScTrkLoc_t* loc;
  80. unsigned minVel;
  81. unsigned maxWndCnt;
  82. unsigned minWndLookAhead;
  83. bool printFl;
  84. int curLocIdx;
  85. unsigned evtIndex;
  86. } cmScTrk;
  87. cmScTrk* cmScTrkAlloc( cmCtx* ctx, cmScTrk* p, cmReal_t srate, cmScH_t scH, unsigned bufN, unsigned minWndLookAhead, unsigned maxWndCnt, unsigned minVel );
  88. cmRC_t cmScTrkFree( cmScTrk** pp );
  89. cmRC_t cmScTrkInit( cmScTrk* p, cmReal_t srate, cmScH_t scH, unsigned bufN, unsigned minWndLookAhead, unsigned maxWndCnt, unsigned minVel );
  90. cmRC_t cmScTrkFinal( cmScTrk* p );
  91. // Jump to a score location and reset the internal state of the follower.
  92. cmRC_t cmScTrkReset( cmScTrk* p, unsigned scoreIndex );
  93. // Give the follower a MIDI performance event. Only MIDI note-on events are acted upon;
  94. // all others are ignored.
  95. unsigned cmScTrkExec( cmScTrk* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  96. //=======================================================================================================================
  97. //
  98. // Simplified string alignment function based on Levenshtein edit distance.
  99. //
  100. enum { kEdMinIdx, kEdSubIdx, kEdDelIdx, kEdInsIdx, kEdCnt };
  101. typedef struct
  102. {
  103. unsigned v[kEdCnt];
  104. bool matchFl;
  105. bool transFl;
  106. } ed_val;
  107. typedef struct ed_path_str
  108. {
  109. unsigned code;
  110. unsigned ri;
  111. unsigned ci;
  112. bool matchFl;
  113. bool transFl;
  114. struct ed_path_str* next;
  115. } ed_path;
  116. /*
  117. Backtracking:
  118. m[rn,cn] is organized to indicate the mutation operations
  119. on s0[0:rn-1] or s1[0:cn-1] during backtracking.
  120. Backtracking begins at cell m[rn-1,cn-1] and proceeds
  121. up and left toward m[0,0]. The action to perform during
  122. backtracking is determined by examinging which values
  123. int m[].v[1:3] match m[].v[0].
  124. Match Next Cell
  125. Index Operation Location
  126. ----- ------------------------ ------------------------
  127. 1 Substitute char s0[ri-1] move diagonally; up-left
  128. 2 Delete char s0[ri-1] move up.
  129. 3 Delete char s1[ci-1] move left.
  130. (same as inserting blank
  131. into after s[ri-1]
  132. Note that more than one value in m[].v[1:3] may match
  133. m[].v[0]. In this case the candidate solution branches
  134. at this point in the candidate selection processes.
  135. */
  136. typedef struct
  137. {
  138. const char* s0; // forms rows of m[] - mutate to match s1 - rn=strlen(s0)
  139. const char* s1; // forms columns of m[] - target string - cn=strlen(s1)
  140. unsigned rn; // length of s0 + 1
  141. unsigned cn; // length of s1 + 1
  142. ed_val* m; // m[rn,cn]
  143. unsigned pn; // rn+cn
  144. ed_path* p_mem; // pmem[ 2*pn ];
  145. ed_path* p_avl; // available path record linked list
  146. ed_path* p_cur; // current path linked list
  147. ed_path* p_opt; // p_opt[pn] current best alignment
  148. double s_opt; // score of the current best alignment
  149. } ed_r;
  150. // print the DP matrix ed_r.m[rn,cn].
  151. void ed_print_mtx( ed_r* r );
  152. // Initialize ed_r.
  153. void ed_init( ed_r* r, const char* s0, const char* s1 );
  154. // Fill in the DP matrix.
  155. void ed_calc_mtx( ed_r* r );
  156. // Traverse the possible alignments in the DP matrix and determine the optimal alignment.
  157. void ed_align( ed_r* r );
  158. // Print the optimal alignment p_opt[]
  159. void ed_print_opt( ed_r* r );
  160. // Free resource allocated by ed_init().
  161. void ed_free(ed_r* r);
  162. // Main test function.
  163. void ed_main();
  164. //=======================================================================================================================
  165. enum
  166. {
  167. kSmMinIdx, //
  168. kSmSubIdx, // 'substitute' - may or may not match
  169. kSmDelIdx, // 'delete' - delete a MIDI note
  170. kSmInsIdx, // 'insert' - insert a space in the score
  171. kSmCnt
  172. };
  173. enum
  174. {
  175. kSmMatchFl = 0x01,
  176. kSmTransFl = 0x02,
  177. kSmTruePosFl = 0x04,
  178. kSmFalsePosFl = 0x08,
  179. kSmBarFl = 0x10,
  180. kSmNoteFl = 0x20
  181. };
  182. // Dynamic Programming (DP) matrix element
  183. typedef struct
  184. {
  185. unsigned v[kSmCnt]; // cost for each operation
  186. unsigned flags; // cmSmMatchFl | cmSmTransFl
  187. } cmScMatchVal_t;
  188. // List record used to track a path through the DP matrix p->m[,]
  189. typedef struct cmScMatchPath_str
  190. {
  191. unsigned code; // kSmXXXIdx
  192. unsigned ri; // matrix row index
  193. unsigned ci; // matrix col index
  194. unsigned flags; // cmSmMatchFl | cmSmTransFl
  195. unsigned locIdx; // p->loc index or cmInvalidIdx
  196. struct cmScMatchPath_str* next; //
  197. } cmScMatchPath_t;
  198. typedef struct cmScMatchEvt_str
  199. {
  200. unsigned pitch; //
  201. unsigned scEvtIdx; // scScore event index
  202. } cmScMatchEvt_t;
  203. // Score location record.
  204. typedef struct
  205. {
  206. unsigned evtCnt; //
  207. cmScMatchEvt_t* evtV; // evtV[evtCnt]
  208. unsigned scLocIdx; // scH score location index
  209. int barNumb; // bar number of this location
  210. } cmScMatchLoc_t;
  211. typedef struct
  212. {
  213. cmObj obj; //
  214. cmScH_t scH; // cmScore handle
  215. unsigned locN; //
  216. cmScMatchLoc_t* loc; // loc[locN]
  217. unsigned mrn; // max row count (midi)
  218. unsigned rn; // cur row count
  219. unsigned mcn; // max column count (score)
  220. unsigned cn; // cur column count
  221. unsigned mmn; // max length of midiBuf[] (mrn-1)
  222. unsigned msn; // max length of score window (mcn-1)
  223. cmScMatchVal_t* m; // m[mrn,mcn] DP matrix
  224. unsigned pn; // mrn+mcn
  225. cmScMatchPath_t* p_mem; // pmem[ 2*pn ];
  226. cmScMatchPath_t* p_avl; // available path record linked list
  227. cmScMatchPath_t* p_cur; // current path linked list
  228. cmScMatchPath_t* p_opt; // p_opt[pn] current best alignment
  229. double opt_cost; // p_opt cost set by cmScMatchExec()
  230. } cmScMatch;
  231. cmScMatch* cmScMatchAlloc( cmCtx* c, cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
  232. cmRC_t cmScMatchFree( cmScMatch** pp );
  233. cmRC_t cmScMatchInit( cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
  234. cmRC_t cmScMatchFinal( cmScMatch* p );
  235. // Returns cmEofRC if locIdx + locN > p->locN - note that this is not necessarily an error.
  236. // The optimal path p_opt[] will only be updated if the edit cost is less than min_cost.
  237. // Set min_cost to DBL_MAX to force p_opt[] to be updated.
  238. cmRC_t cmScMatchExec( cmScMatch* p, unsigned locIdx, unsigned locN, const unsigned* midiPitchV, unsigned midiPitchN, double min_cost );
  239. //=======================================================================================================================
  240. typedef struct
  241. {
  242. unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a positive-match)
  243. //unsigned cbCnt; // count of times this event has been sent via the callback
  244. unsigned mni; // unique identifier for this event since previous call to cmScAlignReset().
  245. unsigned smpIdx; // time stamp of this event
  246. unsigned pitch; // MIDI note pitch
  247. unsigned vel; // " " velocity
  248. } cmScMatcherMidi_t;
  249. typedef struct
  250. {
  251. unsigned locIdx;
  252. unsigned mni;
  253. unsigned smpIdx;
  254. unsigned pitch;
  255. unsigned vel;
  256. unsigned flags;
  257. } cmScMatcherResult_t;
  258. struct cmScMatcher_str;
  259. typedef void (*cmScMatcherCb_t)( struct cmScMatcher_str* p, void* arg, cmScMatcherResult_t* rp );
  260. typedef struct cmScMatcher_str
  261. {
  262. cmObj obj;
  263. cmScMatcherCb_t cbFunc;
  264. void* cbArg;
  265. cmScMatch* mp;
  266. unsigned mn;
  267. cmScMatcherMidi_t* midiBuf; // midiBuf[mn]
  268. cmScMatcherResult_t* res; // res[rn]
  269. unsigned rn; // length of res[]
  270. unsigned ri; // next avail res[] recd.
  271. double s_opt; //
  272. unsigned missCnt; // count of consecutive trailing non-matches
  273. unsigned esi; // index into loc[] of the last positive match.
  274. unsigned mni; // track the count of MIDI events since the last call to cmScMatcherReset()
  275. unsigned mbi; // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
  276. unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan
  277. unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
  278. unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan.
  279. unsigned scanCnt; // count of time scan was executed inside cmScMatcherStep()
  280. } cmScMatcher;
  281. cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
  282. cmRC_t cmScMatcherFree( cmScMatcher** pp );
  283. cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
  284. cmRC_t cmScMatcherFinal( cmScMatcher* p );
  285. void cmScMatcherReset( cmScMatcher* p );
  286. bool cmScMatcherInputMidi( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  287. // Slide a score window scanCnt times, beginning at 'bsi',
  288. // looking for the best match to p->midiBuf[]. The score window
  289. // contain scWndN (p->mp->mcn-1) score locations.
  290. // Returns the index into p->mp->loc[] of the start of the best
  291. // match score window. The score associated
  292. // with this match is stored in s_opt.
  293. unsigned cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt );
  294. // Step forward/back by p->stepCnt from p->esi.
  295. // p->esi must therefore be valid prior to calling this function.
  296. // If more than p->maxMissCnt consecutive MIDI events are
  297. // missed then automatically run cmScAlignScan().
  298. // Return cmEofRC if the end of the score is encountered.
  299. // Return cmSubSysFailRC if an internal scan resync. failed.
  300. cmRC_t cmScMatcherStep( cmScMatcher* p );
  301. cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  302. //=======================================================================================================================
  303. typedef struct
  304. {
  305. unsigned mni;
  306. unsigned scEvtIdx;
  307. unsigned locIdx;
  308. unsigned smpIdx;
  309. unsigned pitch;
  310. unsigned vel;
  311. } cmScMeasMidi_t;
  312. typedef struct
  313. {
  314. unsigned bsei; // begin score event index
  315. unsigned esei; // end score event index
  316. unsigned bsli; //
  317. unsigned esli; // end score loc index
  318. unsigned bli; //
  319. unsigned eli; //
  320. } cmScMeasSet_t;
  321. typedef struct
  322. {
  323. cmObj obj;
  324. cmScMatch* mp;
  325. unsigned mi; // next avail recd in midiBuf[]
  326. unsigned mn; // length of of midiBuf[]
  327. cmScMeasMidi_t* midiBuf; // midiBuf[mn]
  328. unsigned sn; // length of set[]
  329. cmScMeasSet_t* set; // set[sn]
  330. unsigned nsi; // next set index
  331. unsigned nsli; // next score location index
  332. } cmScMeas;
  333. cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, cmScH_t scH );
  334. cmRC_t cmScMeasFree( cmScMeas** pp );
  335. cmRC_t cmScMeasInit( cmScMeas* p, cmScH_t scH );
  336. cmRC_t cmScMeasFinal( cmScMeas* p );
  337. cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel );
  338. //=======================================================================================================================
  339. unsigned cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
  340. // Given a score, a time-line, and a marker on the time line scan the
  341. // entire score looking for the best match between the first 'midiN'
  342. // notes in each marker region and the score.
  343. void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
  344. #ifdef __cplusplus
  345. }
  346. #endif
  347. #endif