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.

cmProc4.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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. //=======================================================================================================================
  166. enum
  167. {
  168. kSaMinIdx,
  169. kSaSubIdx, // 'substitute' - may or may not match
  170. kSaDelIdx, // 'delete' - delete a MIDI note
  171. kSaInsIdx, // 'insert' - insert a space in the score
  172. kSaCnt
  173. };
  174. // Dynamic Programming (DP) matrix element
  175. typedef struct
  176. {
  177. unsigned v[kSaCnt]; //
  178. bool matchFl; // if this is a substitute; is it also a match?
  179. bool transFl; // if this is a substitute; is this the second element in a reversed pair?
  180. } cmScAlignVal_t;
  181. // List record used to track a path through the DP matrix p->m[,]
  182. typedef struct cmScAlignPath_str
  183. {
  184. unsigned code;
  185. unsigned ri;
  186. unsigned ci;
  187. bool matchFl;
  188. bool transFl;
  189. unsigned locIdx;
  190. struct cmScAlignPath_str* next;
  191. } cmScAlignPath_t;
  192. // Score note event record
  193. typedef struct
  194. {
  195. unsigned pitch;
  196. } cmScAlignScEvt_t;
  197. // Score location record.
  198. typedef struct
  199. {
  200. unsigned evtCnt; //
  201. cmScAlignScEvt_t* evtV; // evtV[evtCnt]
  202. unsigned scLocIdx; // scH score location index
  203. int barNumb; // bar number of this location
  204. } cmScAlignLoc_t;
  205. typedef struct
  206. {
  207. unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a positive-match)
  208. unsigned cbCnt; // count of times this event has been sent via the callback
  209. unsigned mni; // unique identifier for this event since previous call to cmScAlignReset().
  210. unsigned smpIdx; // time stamp of this event
  211. unsigned pitch; // MIDI note pitch
  212. unsigned vel; // " " velocity
  213. } cmScAlignMidiEvt_t;
  214. typedef struct
  215. {
  216. unsigned locIdx; // loc[] sync. location
  217. unsigned smpIdx; //
  218. unsigned mni; // MIDI event unique index
  219. unsigned pitch; // MIDI event pitch which may not match the score event pitch
  220. unsigned vel; // " " velocity
  221. bool matchFl;
  222. bool transFl;
  223. bool foundFl;
  224. } cmScAlignResult_t;
  225. //
  226. typedef void (*cmScAlignCb_t)( void* cbArg, unsigned scLocIdx, unsigned mni, unsigned pitch, unsigned vel );
  227. typedef struct
  228. {
  229. cmObj obj;
  230. cmScAlignCb_t cbFunc; //
  231. void* cbArg; //
  232. cmScH_t scH; //
  233. double srate; //
  234. unsigned locN; // length of loc[]
  235. cmScAlignLoc_t* loc; // loc[locN] score array
  236. unsigned rn; // length of midiBuf[] (mn+1)
  237. unsigned cn; // length of score window (scWndN+1)
  238. unsigned mn; // length of midiBuf[] (rn-1)
  239. cmScAlignMidiEvt_t* midiBuf; // midiBuf[ mn ]
  240. unsigned mbi; // index of first element in midiBuf[] - this is required because the MIDI buf fills from the end to the beginning
  241. unsigned mni; // index of event in midiBuf[p->mn] - increments on each note inserted into midiBuf[] - zeroed by cmScAlignReset().
  242. cmScAlignVal_t* m; // m[rn,cn]
  243. unsigned pn; // rn+cn
  244. cmScAlignPath_t* p_mem; // pmem[ 2*pn ];
  245. cmScAlignPath_t* p_avl; // available path record linked list
  246. cmScAlignPath_t* p_cur; // current path linked list
  247. cmScAlignPath_t* p_opt; // p_opt[pn] current best alignment
  248. double s_opt; // score of the current best alignment
  249. unsigned esi; // loc[] index of latest positive match
  250. unsigned missCnt; // count of consecutive trailing MIDI events without positive matches
  251. unsigned scanCnt;
  252. bool printFl;
  253. unsigned begScanLocIdx; // begin the search at this score locations scWnd[begScanLocIdx:begScanLocIdx+p->cn-1]
  254. unsigned begSyncLocIdx; // initial sync location
  255. unsigned resN; // count of records in res[] == 2*cmScoreEvtCount()
  256. cmScAlignResult_t* res; // res[resN]
  257. unsigned ri; //
  258. int stepCnt; // count of loc[] locations to step ahead/back during a cmScAlignStep() operation.
  259. int maxStepMissCnt; // max. consecutive trailing non-positive matches before a scan takes place.
  260. } cmScAlign;
  261. cmScAlign* cmScAlignAlloc( cmCtx* ctx, cmScAlign* p, cmScAlignCb_t cbFunc, void* cbArg, cmReal_t srate, cmScH_t scH, unsigned midiN, unsigned scWndN );
  262. cmRC_t cmScAlignFree( cmScAlign** pp );
  263. cmRC_t cmScAlignInit( cmScAlign* p, cmScAlignCb_t cbFunc, void* cbArg, cmReal_t srate, cmScH_t scH, unsigned midiN, unsigned scWndN );
  264. cmRC_t cmScAlignFinal( cmScAlign* p );
  265. void cmScAlignReset( cmScAlign* p, unsigned begScanLocIdx );
  266. cmRC_t cmScAlignExec( cmScAlign* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  267. bool cmScAlignInputMidi( cmScAlign* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
  268. // Scan from p->begScanLocIdx to the end of the score looking
  269. // for the best match to p->midiBuf[].
  270. // Returns the score location index which best matches the
  271. // first note p->midiBuf[]. The score associated
  272. // with this match is stored in s_opt.
  273. unsigned cmScAlignScan( cmScAlign* p, unsigned scanCnt );
  274. // Step forward/back by p->stepCnt from p->esi.
  275. // If more than p->maxStepMissCnt consecutive MIDI events are
  276. // missed then automatically run cmScAlignScan().
  277. // Return cmEofRC if the end of the score is encountered.
  278. // Return cmSubSysFailRC if an internal scan resync. failed.
  279. cmRC_t cmScAlignStep( cmScAlign* p );
  280. unsigned cmScAlignScanToTimeLineEvent( cmScAlign* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
  281. // Given a score, a time-line, and a marker on the time line scan the
  282. // entire score looking for the best match between the first 'midiN'
  283. // notes in each marker region and the score.
  284. void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
  285. //=======================================================================================================================
  286. typedef struct
  287. {
  288. unsigned mni;
  289. unsigned locIdx;
  290. unsigned pitch;
  291. unsigned vel;
  292. unsigned smpIdx;
  293. } cmScMeasMidi_t;
  294. typedef struct
  295. {
  296. cmScoreSet_t* set; // A pointer to defining score set
  297. unsigned bli; // Begin index into sap->loc[].
  298. unsigned eli; // End index into sap->loc[].
  299. unsigned bmi; // Begin index into midi[].
  300. unsigned emi; // End index into midi[].
  301. double* val; // val[sap->eleCnt]
  302. } cmScMeasSet_t;
  303. typedef struct
  304. {
  305. cmObj obj;
  306. cmScAlign* sap;
  307. unsigned mn;
  308. cmScMeasMidi_t* midi;
  309. } cmScMeas;
  310. cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, double srate, cmScH_t scH );
  311. cmRC_t cmScMeasFree( cmScMeas** pp );
  312. cmRC_t cmScMeasInit( cmScMeas* p, double srate, cmScH_t scH );
  313. cmRC_t cmScMeasFinal( cmScMeas* p );
  314. cmRC_t cmScMeasExec( cmScMeas* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1, unsigned scLocIdx );
  315. #ifdef __cplusplus
  316. }
  317. #endif
  318. #endif