libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmScore.c 44KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873
  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 "cmMidi.h"
  10. #include "cmLex.h"
  11. #include "cmCsv.h"
  12. #include "cmMidiFile.h"
  13. #include "cmAudioFile.h"
  14. #include "cmTimeLine.h"
  15. #include "cmScore.h"
  16. #include "cmVectOpsTemplateMain.h"
  17. cmScH_t cmScNullHandle = cmSTATIC_NULL_HANDLE;
  18. enum
  19. {
  20. kLabelCharCnt = 7,
  21. kInvalidDynScId = 0,
  22. };
  23. enum
  24. {
  25. kMidiFileIdColScIdx= 0,
  26. kTypeLabelColScIdx = 3,
  27. kDSecsColScIdx = 4,
  28. kSecsColScIdx = 5,
  29. kPitchColScIdx = 11,
  30. kBarColScIdx = 13,
  31. kSkipColScIdx = 14,
  32. kEvenColScIdx = 15,
  33. kTempoColScIdx = 16,
  34. kDynColScIdx = 17,
  35. kSectionColScIdx = 18,
  36. kRemarkColScIdx = 19
  37. };
  38. typedef struct
  39. {
  40. unsigned id;
  41. unsigned flag;
  42. cmChar_t label[ kLabelCharCnt + 1 ];
  43. } cmScEvtRef_t;
  44. typedef struct cmScSect_str
  45. {
  46. const cmChar_t* label;
  47. unsigned startIdx;
  48. struct cmScSect_str* link;
  49. } cmScSect_t;
  50. typedef struct cmScSetEle_str
  51. {
  52. cmChar_t* label;
  53. unsigned eleIdx;
  54. struct cmScSetEle_str* link;
  55. } cmScSetEle_t;
  56. typedef struct cmScSet_str
  57. {
  58. unsigned typeFl; // type of this set
  59. cmScSetEle_t* eles; // indexes of set elements
  60. cmScSetEle_t* sects; // application section labels
  61. bool inFl; // true if currently accepting elements
  62. struct cmScSet_str* link; //
  63. } cmScSet_t;
  64. typedef struct
  65. {
  66. cmErr_t err;
  67. cmCsvH_t cH;
  68. cmScCb_t cbFunc;
  69. void* cbArg;
  70. cmChar_t* fn;
  71. cmScoreEvt_t* array;
  72. unsigned cnt;
  73. cmScoreLoc_t* loc;
  74. unsigned locCnt;
  75. cmScoreSection_t* sect;
  76. unsigned sectCnt;
  77. unsigned sciPitchLexTId; // sci pitch and section id lexer token id's
  78. unsigned sectionLexTId;
  79. cmScSect_t* sectList; // lists used during parsing
  80. cmScSet_t* setList;
  81. cmScoreSet_t* sets;
  82. unsigned setCnt;
  83. unsigned* dynRefArray;
  84. unsigned dynRefCnt;
  85. unsigned nxtLocIdx;
  86. unsigned minSetLocIdx;
  87. unsigned maxSetLocIdx;
  88. } cmSc_t;
  89. cmScEvtRef_t _cmScEvtRefArray[] =
  90. {
  91. { kTimeSigEvtScId, 0, "tsg" },
  92. { kKeySigEvtScId, 0, "ksg" },
  93. { kTempoEvtScId, 0, "tmp" },
  94. { kTrackEvtScId, 0, "trk" },
  95. { kTextEvtScId, 0, "txt" },
  96. { kEOTrackEvtScId, 0, "eot" },
  97. { kCopyEvtScId, 0, "cpy" },
  98. { kBlankEvtScId, 0, "blk" },
  99. { kBarEvtScId, 0, "bar" },
  100. { kPgmEvtScId, 0, "pgm" },
  101. { kCtlEvtScId, 0, "ctl" },
  102. { kNonEvtScId, 0, "non" },
  103. { kInvalidEvtScId, 0, "***" }
  104. };
  105. cmScEvtRef_t _cmScDynRefArray[] =
  106. {
  107. { 1, 0, "pppp" },
  108. { 2, 0, "ppp" },
  109. { 3, 0, "pp" },
  110. { 4, 0, "p" },
  111. { 5, 0, "mp" },
  112. { 6, 0, "m" },
  113. { 7, 0, "mf" },
  114. { 8, 0, "f" },
  115. { 9, 0, "ff" },
  116. { 10,0, "fff" },
  117. { 11,0, "ffff"},
  118. { kInvalidDynScId,0, "***" },
  119. };
  120. cmScEvtRef_t _cmScVarRefArray[] =
  121. {
  122. { kEvenVarScId, kEvenScFl, "e"},
  123. { kDynVarScId, kDynScFl, "d"},
  124. { kTempoVarScId,kTempoScFl,"t"},
  125. { cmInvalidId, 0, "@"}
  126. };
  127. cmSc_t* _cmScHandleToPtr( cmScH_t h )
  128. {
  129. cmSc_t* p = (cmSc_t*)h.h;
  130. assert( p != NULL );
  131. return p;
  132. }
  133. unsigned _cmScEvtTypeLabelToId( const cmChar_t* label )
  134. {
  135. cmScEvtRef_t* r = _cmScEvtRefArray;
  136. for(; r->id != kInvalidEvtScId; ++r )
  137. if( strcmp(label,r->label) == 0 )
  138. return r->id;
  139. return kInvalidEvtScId;
  140. }
  141. const cmChar_t* cmScEvtTypeIdToLabel( unsigned id )
  142. {
  143. cmScEvtRef_t* r = _cmScEvtRefArray;
  144. for(; r->id != kInvalidEvtScId; ++r )
  145. if( r->id == id )
  146. return r->label;
  147. return NULL;
  148. }
  149. unsigned _cmScDynLabelToId( const cmChar_t* label )
  150. {
  151. cmScEvtRef_t* r = _cmScDynRefArray;
  152. for(; r->id != kInvalidEvtScId; ++r )
  153. if( strncmp(label,r->label,strlen(r->label)) == 0 )
  154. return r->id;
  155. return kInvalidDynScId;
  156. }
  157. // return the count of dynamic label/id pairs
  158. unsigned _cmScDynLabelCount( )
  159. {
  160. unsigned n = 0;
  161. cmScEvtRef_t* r = _cmScDynRefArray;
  162. for(; r->id != kInvalidEvtScId; ++r )
  163. ++n;
  164. return n;
  165. }
  166. const cmChar_t* cmScDynIdToLabel( unsigned id )
  167. {
  168. cmScEvtRef_t* r = _cmScDynRefArray;
  169. for(; r->id != kInvalidDynScId; ++r )
  170. if( r->id == id )
  171. return r->label;
  172. return NULL;
  173. }
  174. char _cmScVarFlagToChar( unsigned flags )
  175. {
  176. unsigned i;
  177. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  178. if( _cmScVarRefArray[i].flag == flags )
  179. return _cmScVarRefArray[i].label[0];
  180. assert(0);
  181. return ' ';
  182. }
  183. char _cmScVarIdToChar( unsigned id )
  184. {
  185. unsigned i;
  186. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  187. if( _cmScVarRefArray[i].id == id )
  188. return _cmScVarRefArray[i].label[0];
  189. assert(0);
  190. return ' ';
  191. }
  192. unsigned _cmScVarFlagToId( unsigned flags )
  193. {
  194. unsigned i;
  195. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  196. if( _cmScVarRefArray[i].flag == flags )
  197. return _cmScVarRefArray[i].id;
  198. assert(0);
  199. return cmInvalidId;
  200. }
  201. const char* _cmScFlagsToStr( unsigned flags, char* buf, int bufCharCnt )
  202. {
  203. unsigned i=0;
  204. if( cmIsFlag(flags,kEvenScFl) )
  205. {
  206. assert(i<bufCharCnt);
  207. buf[i] = 'e';
  208. ++i;
  209. }
  210. if( cmIsFlag(flags,kDynScFl) )
  211. {
  212. assert(i<bufCharCnt);
  213. buf[i] = 'd';
  214. ++i;
  215. }
  216. if( cmIsFlag(flags,kTempoScFl ))
  217. {
  218. assert(i<bufCharCnt);
  219. buf[i] = 't';
  220. ++i;
  221. }
  222. assert(i<bufCharCnt);
  223. buf[i] = 0;
  224. return buf;
  225. }
  226. unsigned _cmScLexSciPitchMatcher( const cmChar_t* cp, unsigned cn )
  227. {
  228. if( cp==NULL || cn < 2 )
  229. return 0;
  230. // first char must be "A-G"
  231. if( strspn(cp,"ABCDEFG") != 1 )
  232. return 0;
  233. unsigned i = 1;
  234. // next char could be accidental
  235. if( cp[i] == '#' || cp[i] == 'b' )
  236. ++i; // i==2
  237. // the 2nd or 3rd char must be a digit
  238. if( i>=cn || isdigit(cp[i]) == false )
  239. return 0;
  240. ++i; // i==2 or i==3
  241. // the 3rd or 4th char must be a digit or EOS
  242. if( i>=cn || isdigit(cp[i]) == false )
  243. return i;
  244. ++i;
  245. return i;
  246. }
  247. unsigned _cmScLexSectionIdMatcher( const cmChar_t* cp, unsigned cn )
  248. {
  249. if( cp==NULL || cn < 2 )
  250. return 0;
  251. // first char must be a number
  252. if( !isdigit(cp[0]) )
  253. return 0;
  254. // if 2nd char is a char then terminate
  255. if( 'a'<=cp[1] && cp[1]<='z' )
  256. return 2;
  257. // if 2nd char is digit and 3rd char is char then terminate
  258. if( isdigit(cp[1]) && cn>2 && 'a'<=cp[2] && cp[2]<='z' )
  259. return 3;
  260. return 0;
  261. }
  262. void _cmScFreeSetList( cmScSet_t* setList )
  263. {
  264. cmScSet_t* tp = setList;
  265. cmScSet_t* ntp = NULL;
  266. while(tp!=NULL)
  267. {
  268. ntp = tp->link;
  269. cmScSetEle_t* ep = tp->eles;
  270. while( ep != NULL )
  271. {
  272. cmScSetEle_t* nep = ep->link;
  273. cmMemFree(ep);
  274. ep = nep;
  275. }
  276. ep = tp->sects;
  277. while( ep != NULL )
  278. {
  279. cmScSetEle_t* nep = ep->link;
  280. cmMemFree(ep->label);
  281. cmMemFree(ep);
  282. ep = nep;
  283. }
  284. cmMemFree(tp);
  285. tp = ntp;
  286. }
  287. }
  288. cmScRC_t _cmScFinalize( cmSc_t* p )
  289. {
  290. cmScRC_t rc = kOkScRC;
  291. unsigned i;
  292. if( cmCsvFinalize(&p->cH) != kOkCsvRC )
  293. return rc;
  294. if( p->sets != NULL )
  295. {
  296. for(i=0; i<p->setCnt; ++i)
  297. {
  298. cmMemFree(p->sets[i].eleArray);
  299. //cmMemFree(p->sets[i].sectArray);
  300. }
  301. cmMemFree(p->sets);
  302. }
  303. _cmScFreeSetList(p->setList);
  304. if( p->loc != NULL )
  305. {
  306. for(i=0; i<p->locCnt; ++i)
  307. {
  308. cmMemFree(p->loc[i].evtArray);
  309. if( p->loc[i].begSectPtr != NULL )
  310. cmMemFree(p->loc[i].begSectPtr->setArray);
  311. }
  312. cmMemFree(p->loc);
  313. }
  314. cmMemFree(p->sect);
  315. cmMemFree(p->fn);
  316. cmMemFree(p->array);
  317. cmMemFree(p);
  318. return rc;
  319. }
  320. cmScRC_t _cmScParseBar( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, int* barNumb )
  321. {
  322. if((*barNumb = cmCsvCellInt(p->cH,rowIdx,kBarColScIdx)) == INT_MAX )
  323. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to parse the bar number.");
  324. s->type = kBarEvtScId;
  325. s->secs = 0;
  326. s->barNumb = *barNumb;
  327. s->csvRowNumb = rowIdx + 1;
  328. return kOkScRC;
  329. }
  330. cmScSet_t* _cmScNewSet( cmSc_t* p, unsigned typeFl )
  331. {
  332. // create a new set record
  333. cmScSet_t* nsp = cmMemAllocZ(cmScSet_t,1);
  334. nsp->inFl = true;
  335. nsp->typeFl = typeFl;
  336. if( p->setList == NULL )
  337. p->setList = nsp;
  338. else
  339. {
  340. // go to the end of the the set list
  341. cmScSet_t* sp = p->setList;
  342. assert(sp!=NULL);
  343. while( sp->link != NULL )
  344. sp = sp->link;
  345. sp->link = nsp;
  346. }
  347. return nsp;
  348. }
  349. cmScSet_t* _cmScFindSet( cmSc_t* p, unsigned typeFl )
  350. {
  351. // locate the set currently accepting ele's for this type
  352. cmScSet_t* sp = p->setList;
  353. for(; sp != NULL; sp=sp->link )
  354. if( sp->typeFl == typeFl && sp->inFl )
  355. break;
  356. return sp;
  357. }
  358. void _cmScSetDone(cmSc_t* p, unsigned typeFl)
  359. {
  360. cmScSet_t* sp = _cmScFindSet(p,typeFl);
  361. assert( sp != NULL );
  362. sp->inFl = false;
  363. }
  364. // This function is called during parsing to
  365. // insert a set element or set section into a cmScSet_t
  366. // element or section linked list. Either the scoreIdx
  367. // or the label is valid but not both.
  368. cmScSet_t* _cmScInsertSetEle(cmSc_t* p, unsigned scoreIdx, unsigned typeFl, const cmChar_t* label, unsigned labelCharCnt)
  369. {
  370. assert( scoreIdx!=cmInvalidId || (scoreIdx==cmInvalidIdx && label!=NULL && labelCharCnt>0));
  371. cmScSet_t* sp = _cmScFindSet(p,typeFl);
  372. if( sp == NULL )
  373. sp = _cmScNewSet(p,typeFl);
  374. // allocate a new set element record
  375. cmScSetEle_t* nep = cmMemAllocZ(cmScSetEle_t,1);
  376. cmScSetEle_t** list = NULL;
  377. nep->eleIdx = scoreIdx;
  378. if( label == NULL )
  379. {
  380. // all elements must be of the same type
  381. assert( sp->typeFl == typeFl );
  382. sp->typeFl = typeFl;
  383. list = &sp->eles;
  384. }
  385. else
  386. {
  387. nep->label = cmMemAllocStrN(label,labelCharCnt);
  388. list = &sp->sects;
  389. }
  390. // *list refers to sp->sects or sp->ele's depending on the type of ele
  391. if( *list == NULL )
  392. *list = nep;
  393. else
  394. {
  395. // got to the last element in the set
  396. cmScSetEle_t* ep = *list;
  397. while( ep->link != NULL )
  398. ep = ep->link;
  399. // append the new element to the end of the list
  400. ep->link = nep;
  401. }
  402. return sp;
  403. }
  404. // Extract the next attribute section identifier.
  405. const cmChar_t* _cmScParseOneSetSection( cmSc_t* p, unsigned typeFl, const cmChar_t* c0p )
  406. {
  407. // advance white space
  408. while( *c0p && (isspace(*c0p) || *c0p==',') )
  409. ++c0p;
  410. if( *c0p==0 )
  411. return c0p;
  412. // c0p now points to a section id or an asterisk
  413. const cmChar_t* c1p = c0p;
  414. // advance past section id
  415. while( *c1p && (!isspace(*c1p) && (isdigit(*c1p) || isalpha(*c1p))))
  416. ++c1p;
  417. // if c0p pointed to an asterisk then c1p is still equal to c0p
  418. if( c1p > c0p )
  419. _cmScInsertSetEle(p,cmInvalidIdx,typeFl,c0p,c1p-c0p);
  420. return c1p;
  421. }
  422. // Parse an attribute string to extract the section
  423. // identifiers which may follow the attribute token (e,t,mf,ff,...)
  424. cmScRC_t _cmScParseAttr(cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned typeFl)
  425. {
  426. const cmChar_t* cp = text;
  427. // insert a set element - all attribute's produce one element record
  428. _cmScInsertSetEle(p,scoreIdx,typeFl,NULL,0);
  429. // advance past the attribute type marking (e,t,(p,mf,f,fff,etc)) in search
  430. // of section identifiers
  431. while( *cp && !isspace(*cp) )
  432. ++cp;
  433. if( *cp )
  434. {
  435. // search for the first section identifier
  436. if((cp =_cmScParseOneSetSection(p,typeFl,cp)) != NULL )
  437. {
  438. bool asteriskFl = false;
  439. // search for the second section identifier
  440. if((cp = _cmScParseOneSetSection(p,typeFl,cp)) != NULL && *cp!=0 )
  441. asteriskFl = *cp == '*';
  442. _cmScSetDone(p,typeFl);
  443. // if the attr just parsed ended with an asterisk then it is both
  444. // the last element of the previous set and the first ele of the
  445. // next set
  446. if( asteriskFl )
  447. {
  448. // if the attr just parsed had a section id then it was the last
  449. // element in the set - create a new set record to hold the next set
  450. _cmScNewSet(p,typeFl);
  451. _cmScInsertSetEle(p,scoreIdx,typeFl,NULL,0);
  452. }
  453. }
  454. }
  455. return kOkScRC;
  456. }
  457. void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
  458. {
  459. printf("%s\n",label);
  460. const cmScSet_t* sp = setList;
  461. for(; sp != NULL; sp=sp->link )
  462. {
  463. const cmScSetEle_t* ep = sp->eles;
  464. for(; ep!=NULL; ep=ep->link)
  465. printf("%i ",ep->eleIdx);
  466. printf(" : ");
  467. for(ep=sp->sects; ep!=NULL; ep=ep->link)
  468. printf("%s ",cmStringNullGuard(ep->label));
  469. printf("\n");
  470. }
  471. }
  472. cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned scoreIdx, int barNumb, unsigned barNoteIdx )
  473. {
  474. cmScRC_t rc = kOkScRC;
  475. unsigned flags = 0;
  476. unsigned dynVal = kInvalidDynScId;
  477. const cmChar_t* sciPitch;
  478. cmMidiByte_t midiPitch;
  479. const cmChar_t* attr;
  480. double secs;
  481. double durSecs;
  482. const cmCsvCell_t* cell;
  483. s += scoreIdx;
  484. // verify the scientific pitch cell was formatted correcly
  485. if((cell = cmCsvCellPtr(p->cH,rowIdx,kPitchColScIdx)) == NULL || cell->lexTId != p->sciPitchLexTId )
  486. return cmErrMsg(&p->err,kSyntaxErrScRC,"Pitch column format error.");
  487. if((sciPitch = cmCsvCellText(p->cH,rowIdx,kPitchColScIdx)) == NULL )
  488. return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
  489. if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch)
  490. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. ");
  491. // it is possible that note delta-secs field is empty - so default to 0
  492. if((secs = cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
  493. flags += kInvalidScFl;
  494. // skip attribute
  495. if((attr = cmCsvCellText(p->cH,rowIdx,kSkipColScIdx)) != NULL && *attr == 's' )
  496. flags += kSkipScFl;
  497. // evenness attribute
  498. if((attr = cmCsvCellText(p->cH,rowIdx,kEvenColScIdx)) != NULL && *attr == 'e' )
  499. {
  500. flags += kEvenScFl;
  501. _cmScParseAttr(p,scoreIdx,attr,kEvenScFl);
  502. }
  503. // tempo attribute
  504. if((attr = cmCsvCellText(p->cH,rowIdx,kTempoColScIdx)) != NULL && *attr == 't' )
  505. {
  506. flags += kTempoScFl;
  507. _cmScParseAttr(p,scoreIdx,attr,kTempoScFl);
  508. }
  509. // dynamics attribute
  510. if((attr = cmCsvCellText(p->cH,rowIdx,kDynColScIdx)) != NULL )
  511. {
  512. if((dynVal = _cmScDynLabelToId(attr)) == kInvalidDynScId )
  513. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unknown dynamic label '%s'.",cmStringNullGuard(attr));
  514. flags += kDynScFl;
  515. _cmScParseAttr(p,scoreIdx,attr,kDynScFl);
  516. }
  517. // Returns DBL_MAX on error.
  518. if((durSecs = cmCsvCellDouble(p->cH, rowIdx, kDSecsColScIdx )) == DBL_MAX)
  519. durSecs = 0.25;
  520. s->type = kNonEvtScId;
  521. s->secs = secs;
  522. s->pitch = midiPitch;
  523. s->flags = flags;
  524. s->dynVal = dynVal;
  525. s->barNumb = barNumb;
  526. s->barNoteIdx = barNoteIdx;
  527. s->durSecs = durSecs;
  528. s->csvRowNumb = rowIdx+1;
  529. return rc;
  530. }
  531. cmScRC_t _cmScParseSectionColumn( cmSc_t* p, unsigned rowIdx, unsigned evtIdx, cmScSect_t* sectList )
  532. {
  533. const cmCsvCell_t* cell;
  534. cmScSect_t* sect;
  535. const cmChar_t* label;
  536. // most rows don't have section labels
  537. if( (cell = cmCsvCellPtr( p->cH,rowIdx,kSectionColScIdx)) == NULL
  538. || (label = cmCsvCellText(p->cH,rowIdx,kSectionColScIdx)) == NULL)
  539. return kOkScRC;
  540. // verify the section id type
  541. if( cell->lexTId != p->sectionLexTId && cell->lexTId != kIntLexTId )
  542. return cmErrMsg(&p->err,kSyntaxErrScRC,"'section' column format error.");
  543. sect = cmMemAllocZ(cmScSect_t,1);
  544. sect->label = label;
  545. sect->startIdx = evtIdx;
  546. //printf("section:%s\n",label);
  547. cmScSect_t* sp = sectList;
  548. assert( sp != NULL );
  549. while( sp->link != NULL )
  550. sp = sp->link;
  551. sp->link = sect;
  552. return kOkScRC;
  553. }
  554. cmScoreSection_t* _cmScLabelToSection( cmSc_t* p, const cmChar_t* label )
  555. {
  556. int i;
  557. for(i=0; i<p->sectCnt; ++i)
  558. if( strcmp(p->sect[i].label,label) == 0 )
  559. return p->sect + i;
  560. return NULL;
  561. }
  562. // Calculate the total number of all types of sets and
  563. // then convert each of the cmScSet_t linked list's to
  564. // a single linear cmScoreSet_t list (p->sets[]).
  565. cmScRC_t _cmScProcSets( cmSc_t* p )
  566. {
  567. cmScRC_t rc = kOkScRC;
  568. // calculate the count of all sets
  569. unsigned i;
  570. unsigned n = 0;
  571. cmScSet_t* sp = p->setList;
  572. for(n=0; sp!=NULL; sp=sp->link)
  573. if( sp->eles != NULL )
  574. ++n;
  575. // allocate the linear set array
  576. p->sets = cmMemAllocZ(cmScoreSet_t,n);
  577. p->setCnt = n;
  578. // fill in the linear set array
  579. sp = p->setList;
  580. for(i=0; sp!=NULL; sp=sp->link)
  581. if( sp->eles != NULL )
  582. {
  583. unsigned j;
  584. unsigned en;
  585. unsigned rowNumb = 0;
  586. assert( i<n );
  587. // get the count of elements assoc'd with this set
  588. cmScSetEle_t* ep = sp->eles;
  589. for(en=0; ep!=NULL; ep=ep->link)
  590. ++en;
  591. assert( en > 0 );
  592. // allocate the element array
  593. p->sets[i].eleCnt = en;
  594. p->sets[i].eleArray = cmMemAllocZ(cmScoreEvt_t*,en);
  595. // fill in the element array
  596. ep = sp->eles;
  597. for(j=0; ep!=NULL; ep=ep->link,++j)
  598. {
  599. assert(ep->eleIdx != cmInvalidIdx && ep->eleIdx<p->cnt);
  600. p->sets[i].eleArray[j] = p->array + ep->eleIdx;
  601. assert( cmIsFlag( p->sets[i].eleArray[j]->flags, sp->typeFl) );
  602. rowNumb = p->array[ep->eleIdx].csvRowNumb;
  603. }
  604. // get the count of sections assoc'd with this set
  605. ep = sp->sects;
  606. for(en=0; ep!=NULL; ep=ep->link)
  607. ++en;
  608. // allocate the section array
  609. p->sets[i].varId = _cmScVarFlagToId(sp->typeFl);
  610. //p->sets[i].sectCnt = en;
  611. //p->sets[i].sectArray = cmMemAllocZ(cmScoreSection_t*,en);
  612. // fill in the section array with sections which this set will be applied to
  613. ep = sp->sects;
  614. for(j=0; ep!=NULL; ep=ep->link,++j)
  615. {
  616. cmScoreSection_t* sp;
  617. assert(ep->label != NULL);
  618. if((sp = _cmScLabelToSection(p, ep->label )) == NULL )
  619. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The section labelled '%s' could not be found for the set which includes row number %i.",ep->label,rowNumb);
  620. else
  621. {
  622. //= p->sets[i].sectArray[j];
  623. sp->setArray = cmMemResizeP(cmScoreSet_t*,sp->setArray,++sp->setCnt);
  624. sp->setArray[sp->setCnt-1] = p->sets + i;
  625. }
  626. }
  627. ++i;
  628. }
  629. assert(i==n);
  630. // assign each set to the location which contains it's last element.
  631. // (this is earliest point in the score location where all the
  632. // performance information contained in the set may be valid)
  633. for(i=0; i<p->setCnt; ++i)
  634. {
  635. assert( p->sets[i].eleCnt >= 1 );
  636. // get a ptr to the last element for the ith set
  637. const cmScoreEvt_t* ep = p->sets[i].eleArray[ p->sets[i].eleCnt-1 ];
  638. unsigned j,k;
  639. // find the location which contains the last element
  640. for(j=0; j<p->locCnt; ++j)
  641. {
  642. for(k=0; k<p->loc[j].evtCnt; ++k)
  643. if( p->loc[j].evtArray[k] == ep )
  644. break;
  645. if(k<p->loc[j].evtCnt)
  646. break;
  647. }
  648. assert( j<p->locCnt );
  649. // assign the ith set to the location which contains it's last element
  650. p->sets[i].llink = p->loc[j].setList;
  651. p->loc[j].setList = p->sets + i;
  652. }
  653. return rc;
  654. }
  655. cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
  656. {
  657. cmScRC_t rc = kOkScRC;
  658. unsigned i;
  659. // count the sections
  660. cmScSect_t* sp = sectList;
  661. p->sectCnt = 0;
  662. for(; sp!=NULL; sp=sp->link)
  663. if( sp->label != NULL )
  664. ++p->sectCnt;
  665. // alloc a section array
  666. p->sect = cmMemAllocZ(cmScoreSection_t,p->sectCnt);
  667. // fill the section array
  668. sp = sectList;
  669. for(i=0; sp!=NULL; sp=sp->link)
  670. if( sp->label != NULL )
  671. {
  672. p->sect[i].label = sp->label;
  673. p->sect[i].index = i;
  674. p->sect[i].begEvtIndex = sp->startIdx;
  675. ++i;
  676. }
  677. // assign the begSectPtr to each section
  678. for(i=0; i<p->sectCnt; ++i)
  679. {
  680. assert( p->sect[i].begEvtIndex < p->cnt );
  681. unsigned j,k;
  682. const cmScoreEvt_t* ep = p->array + p->sect[i].begEvtIndex;
  683. for(j=0; j<p->locCnt; ++j)
  684. {
  685. for(k=0; k<p->loc[j].evtCnt; ++k)
  686. if( p->loc[j].evtArray[k] == ep )
  687. {
  688. p->loc[j].begSectPtr = p->sect + i;
  689. p->sect[i].locPtr = p->loc + j;
  690. break;
  691. }
  692. if( k<p->loc[j].evtCnt)
  693. break;
  694. }
  695. }
  696. // release the section linked list
  697. sp = sectList;
  698. cmScSect_t* np = NULL;
  699. while(sp!=NULL)
  700. {
  701. np = sp->link;
  702. cmMemFree(sp);
  703. sp = np;
  704. }
  705. //_cmScPrintSets("Sets",p->setList );
  706. _cmScProcSets(p);
  707. return rc;
  708. }
  709. cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
  710. {
  711. cmScRC_t rc = kOkScRC;
  712. unsigned barNoteIdx = 0;
  713. int barEvtIdx = cmInvalidIdx;
  714. int barNumb = 0;
  715. double secs;
  716. double cur_secs = 0;
  717. p->sectList = cmMemAllocZ(cmScSect_t,1); // section zero
  718. //_cmScNewSet(p); // preallocate the first set
  719. // initialize the CSV file parser
  720. if( cmCsvInitialize(&p->cH, ctx ) != kOkCsvRC )
  721. {
  722. rc = cmErrMsg(&p->err,kCsvFailScRC,"Score file initialization failed.");
  723. goto errLabel;
  724. }
  725. // register custom lex token matchers for sci-pitch and section id's
  726. if( cmCsvLexRegisterMatcher(p->cH, p->sciPitchLexTId = cmCsvLexNextAvailId(p->cH)+0, _cmScLexSciPitchMatcher ) != kOkCsvRC
  727. ||cmCsvLexRegisterMatcher(p->cH, p->sectionLexTId = cmCsvLexNextAvailId(p->cH)+1, _cmScLexSectionIdMatcher) != kOkCsvRC )
  728. {
  729. rc = cmErrMsg(&p->err,kCsvFailScRC,"CSV token matcher registration failed.");
  730. goto errLabel;
  731. }
  732. // parse the CSV file
  733. if( cmCsvParseFile(p->cH, fn, 0 ) != kOkCsvRC )
  734. {
  735. rc = cmErrMsg(&p->err,kCsvFailScRC,"CSV file parsing failed on the file '%s'.",cmStringNullGuard(fn));
  736. goto errLabel;
  737. }
  738. // allocate the score event array
  739. p->cnt = cmCsvRowCount(p->cH);
  740. p->array = cmMemAllocZ(cmScoreEvt_t,p->cnt);
  741. unsigned i,j;
  742. // skip labels line - start on line 1
  743. for(i=1,j=0; i<p->cnt && rc==kOkScRC; ++i)
  744. {
  745. // get the row 'type' label
  746. const char* typeLabel;
  747. if((typeLabel = cmCsvCellText(p->cH,i,kTypeLabelColScIdx)) == NULL )
  748. {
  749. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"No type label.");
  750. break;
  751. }
  752. // convert the row 'type' label to an id
  753. unsigned tid;
  754. if((tid = _cmScEvtTypeLabelToId(typeLabel)) == kInvalidEvtScId)
  755. {
  756. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"Unknown type '%s'.",cmStringNullGuard(typeLabel));
  757. break;
  758. }
  759. secs = DBL_MAX;
  760. switch(tid)
  761. {
  762. case kBarEvtScId: // parse bar lines
  763. if((rc = _cmScParseBar(p,i,p->array+j,&barNumb)) == kOkScRC )
  764. {
  765. barNoteIdx = 0;
  766. barEvtIdx = j;
  767. p->array[j].index = j;
  768. ++j;
  769. }
  770. break;
  771. case kNonEvtScId: // parse note-on events
  772. if((rc = _cmScParseNoteOn(p, i, p->array, j, barNumb, barNoteIdx )) == kOkScRC )
  773. {
  774. secs = p->array[j].secs;
  775. if( p->array[j].secs == DBL_MAX )
  776. p->array[j].secs = cur_secs;
  777. if( cmIsFlag(p->array[j].flags,kSkipScFl) == false )
  778. {
  779. p->array[j].index = j;
  780. ++j;
  781. }
  782. ++barNoteIdx;
  783. }
  784. break;
  785. default:
  786. // Returns DBL_MAX on error.
  787. secs = cmCsvCellDouble(p->cH, i, kSecsColScIdx );
  788. break;
  789. }
  790. if( secs != DBL_MAX )
  791. cur_secs = secs;
  792. // form the section list
  793. if( j > 0 )
  794. if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
  795. break;
  796. // the bar lines don't have times so set the time of the bar line to the
  797. // time of the first event in the bar.
  798. if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
  799. {
  800. assert( p->array[ barEvtIdx ].type == kBarEvtScId );
  801. p->array[ barEvtIdx ].secs = secs;
  802. // handle the case where the previous bar had no events
  803. // BUG BUG BUG this is a hack which will fail if the first bar does not have events.
  804. if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId )
  805. p->array[ barEvtIdx-1].secs = secs;
  806. barEvtIdx = cmInvalidIdx;
  807. }
  808. }
  809. if( rc == kSyntaxErrScRC )
  810. {
  811. cmErrMsg(&p->err,rc,"Syntax error on line %i in '%s'.",i+1,cmStringNullGuard(fn));
  812. goto errLabel;
  813. }
  814. p->cnt = j;
  815. errLabel:
  816. return rc;
  817. }
  818. cmScRC_t _cmScInitLocArray( cmSc_t* p )
  819. {
  820. cmScRC_t rc = kOkScRC;
  821. double maxDSecs = 0; // max time between events that are considered simultaneous
  822. unsigned barNumb = 0;
  823. int i,j,k;
  824. if( p->cnt==0)
  825. return rc;
  826. p->locCnt = 1;
  827. // count the number of unique time locations in the score
  828. p->locCnt = 1;
  829. for(i=1; i<p->cnt; ++i )
  830. {
  831. if( p->array[i].secs < p->array[i-1].secs )
  832. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The time associated with the score entry on line %i is less than the previous line.",p->array[i].csvRowNumb);
  833. if( (p->array[i].secs - p->array[i-1].secs) > maxDSecs )
  834. ++p->locCnt;
  835. }
  836. if( rc != kOkScRC )
  837. return rc;
  838. // allocate the loc. array
  839. p->loc = cmMemAllocZ(cmScoreLoc_t,p->locCnt);
  840. // fill in the location array
  841. for(i=0,k=0; i<p->cnt; ++k)
  842. {
  843. j = i+1;
  844. // get the count of events at this location
  845. while( j<p->cnt && p->array[j].secs - p->array[j-1].secs <= maxDSecs )
  846. ++j;
  847. assert(k<p->locCnt);
  848. p->loc[k].index = k;
  849. p->loc[k].evtCnt = j-i;
  850. p->loc[k].evtArray = cmMemAllocZ(cmScoreEvt_t*,p->loc[k].evtCnt);
  851. // fill in the location record event pointers
  852. for(j=0; j<p->loc[k].evtCnt; ++j)
  853. {
  854. p->loc[k].evtArray[j] = p->array + (i + j);
  855. p->loc[k].evtArray[j]->locIdx = k;
  856. if( p->array[i+j].type == kBarEvtScId )
  857. barNumb = p->array[i+j].barNumb;
  858. }
  859. // fill in the location record
  860. p->loc[k].secs = p->array[i].secs;
  861. p->loc[k].barNumb = barNumb;
  862. i += p->loc[k].evtCnt;
  863. }
  864. assert( p->locCnt == k );
  865. return rc;
  866. }
  867. cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, const unsigned* dynRefArray, unsigned dynRefCnt, cmScCb_t cbFunc, void* cbArg )
  868. {
  869. cmScRC_t rc = kOkScRC;
  870. if((rc = cmScoreFinalize(hp)) != kOkScRC )
  871. return rc;
  872. cmSc_t* p = cmMemAllocZ(cmSc_t,1);
  873. cmErrSetup(&p->err,&ctx->rpt,"Score");
  874. if((rc = _cmScParseFile(p,ctx,fn)) != kOkScRC )
  875. goto errLabel;
  876. if((rc = _cmScInitLocArray(p)) != kOkScRC )
  877. goto errLabel;
  878. if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
  879. goto errLabel;
  880. // load the dynamic reference array
  881. if( dynRefArray != NULL && dynRefCnt > 0)
  882. {
  883. unsigned n = _cmScDynLabelCount();
  884. if( dynRefCnt != n )
  885. {
  886. rc = cmErrMsg(&p->err,kInvalidDynRefCntScRC,"The count of dynamics labels must be %i not %i.",n,dynRefCnt);
  887. goto errLabel;
  888. }
  889. p->dynRefArray = cmMemAllocZ(unsigned,dynRefCnt);
  890. memcpy(p->dynRefArray,dynRefArray,sizeof(unsigned)*dynRefCnt);
  891. p->dynRefCnt = dynRefCnt;
  892. }
  893. p->cbFunc = cbFunc;
  894. p->cbArg = cbArg;
  895. p->fn = cmMemAllocStr(fn);
  896. p->nxtLocIdx = 0;
  897. p->minSetLocIdx = cmInvalidIdx;
  898. p->maxSetLocIdx = cmInvalidIdx;
  899. hp->h = p;
  900. cmScoreClearPerfInfo(*hp);
  901. //cmScorePrintLoc(*hp);
  902. errLabel:
  903. if( rc != kOkScRC )
  904. _cmScFinalize(p);
  905. return rc;
  906. }
  907. cmScRC_t cmScoreFinalize( cmScH_t* hp )
  908. {
  909. cmScRC_t rc = kOkScRC;
  910. if( hp == NULL || cmScoreIsValid(*hp) == false )
  911. return kOkScRC;
  912. cmSc_t* p = _cmScHandleToPtr(*hp);
  913. if((rc = _cmScFinalize(p)) != kOkScRC )
  914. return rc;
  915. hp->h = NULL;
  916. return rc;
  917. }
  918. const cmChar_t* cmScoreFileName( cmScH_t h )
  919. {
  920. cmSc_t* p = _cmScHandleToPtr(h);
  921. return p->fn;
  922. }
  923. bool cmScoreIsValid( cmScH_t h )
  924. { return h.h != NULL; }
  925. unsigned cmScoreEvtCount( cmScH_t h )
  926. {
  927. cmSc_t* p = _cmScHandleToPtr(h);
  928. return p->cnt;
  929. }
  930. cmScoreEvt_t* cmScoreEvt( cmScH_t h, unsigned idx )
  931. {
  932. cmSc_t* p = _cmScHandleToPtr(h);
  933. if( idx >= p->cnt )
  934. {
  935. cmErrMsg(&p->err,kInvalidIdxScRC,"%i is an invalid index for %i records.",idx,p->cnt);
  936. return NULL;
  937. }
  938. return p->array + idx;
  939. }
  940. unsigned cmScoreSectionCount( cmScH_t h )
  941. {
  942. cmSc_t* p = _cmScHandleToPtr(h);
  943. return p->sectCnt;
  944. }
  945. cmScoreSection_t* cmScoreSection( cmScH_t h, unsigned idx )
  946. {
  947. cmSc_t* p = _cmScHandleToPtr(h);
  948. assert( idx < p->sectCnt);
  949. return p->sect + idx;
  950. }
  951. unsigned cmScoreLocCount( cmScH_t h )
  952. {
  953. cmSc_t* p = _cmScHandleToPtr(h);
  954. return p->locCnt;
  955. }
  956. cmScoreLoc_t* cmScoreLoc( cmScH_t h, unsigned idx )
  957. {
  958. cmSc_t* p = _cmScHandleToPtr(h);
  959. if( idx >= p->locCnt )
  960. {
  961. cmErrMsg(&p->err,kInvalidIdxScRC,"%i is an invalid index for %i location records.",idx,p->locCnt);
  962. return NULL;
  963. }
  964. return p->loc + idx;
  965. }
  966. void cmScorePrintLoc( cmScH_t h )
  967. {
  968. unsigned i = 0;
  969. cmSc_t* p = _cmScHandleToPtr(h);
  970. unsigned colCnt = 10;
  971. int bufCharCnt = 4;
  972. char buf[ bufCharCnt ];
  973. const char* emptyStr = " ";
  974. // for each set of 'colCnt' columns
  975. for(i=0; i<p->locCnt; i+=colCnt )
  976. {
  977. // print the location 'index' line
  978. unsigned c,j,k;
  979. printf("index: ");
  980. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  981. printf("%7i ",j);
  982. printf("\n");
  983. // print the 'sectn' label line
  984. printf("sectn: ");
  985. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  986. if( p->loc[j].begSectPtr==NULL )
  987. printf("%s",emptyStr);
  988. else
  989. printf("%7s ",p->loc[j].begSectPtr->label);
  990. printf("\n");
  991. // calculate the max number of simultan. events at any one location
  992. // for this set of 'colCnt' columns.
  993. unsigned n=0;
  994. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  995. if( p->loc[j].evtCnt > n )
  996. n = p->loc[j].evtCnt;
  997. // for each 'sco' line
  998. for(k=0; k<n; ++k)
  999. {
  1000. printf("sco%2i: ",k);
  1001. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1002. if( k >= p->loc[j].evtCnt )
  1003. printf("%s",emptyStr);
  1004. else
  1005. {
  1006. switch(p->loc[j].evtArray[k]->type)
  1007. {
  1008. case kBarEvtScId:
  1009. printf(" |%3i ",p->loc[j].evtArray[k]->barNumb);
  1010. break;
  1011. case kNonEvtScId:
  1012. {
  1013. int bn=16;
  1014. char b[bn];
  1015. strcpy(b,cmMidiToSciPitch(p->loc[j].evtArray[k]->pitch,NULL,0));
  1016. strcat(b,_cmScFlagsToStr( p->loc[j].evtArray[k]->flags,buf,bufCharCnt));
  1017. assert(strlen(b)<bn);
  1018. printf("%7s ",b);
  1019. break;
  1020. }
  1021. }
  1022. }
  1023. printf("\n");
  1024. }
  1025. // calc the max number of set triggers which will occur on
  1026. // any one location for this set of 'colCnt' columns.
  1027. n=0;
  1028. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1029. if(p->loc[j].begSectPtr != NULL && p->loc[j].begSectPtr->setCnt > n )
  1030. n = p->loc[j].begSectPtr->setCnt;
  1031. for(k=0; k<n; ++k)
  1032. {
  1033. printf("trig%1i: ",k);
  1034. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1035. {
  1036. if( p->loc[j].begSectPtr != NULL && k<p->loc[j].begSectPtr->setCnt )
  1037. {
  1038. const cmScoreSet_t* sp = p->loc[j].begSectPtr->setArray[k];
  1039. printf(" %3s-%c ",p->loc[j].begSectPtr->label,_cmScVarIdToChar(sp->varId) );
  1040. }
  1041. else
  1042. {
  1043. printf("%s",emptyStr);
  1044. }
  1045. }
  1046. printf("\n");
  1047. }
  1048. printf("\n");
  1049. }
  1050. }
  1051. cmScRC_t cmScoreSeqNotify( cmScH_t h )
  1052. {
  1053. cmScRC_t rc = kOkScRC;
  1054. cmSc_t* p = _cmScHandleToPtr(h);
  1055. cmScMsg_t m;
  1056. unsigned i;
  1057. if( p->cbFunc != NULL )
  1058. {
  1059. memset(&m.u.evt,0,sizeof(m.u.evt));
  1060. m.typeId = kBeginMsgScId;
  1061. p->cbFunc(p->cbArg,&m,sizeof(m));
  1062. m.typeId = kEventMsgScId;
  1063. for(i=0; i<p->cnt; ++i)
  1064. {
  1065. m.u.evt = p->array[i];
  1066. p->cbFunc(p->cbArg,&m,sizeof(m));
  1067. }
  1068. m.typeId = kSectionMsgScId;
  1069. for(i=0; i<p->sectCnt; ++i)
  1070. {
  1071. m.u.sect = p->sect[i];
  1072. p->cbFunc(p->cbArg,&m,sizeof(m));
  1073. }
  1074. memset(&m.u.evt,0,sizeof(m.u.evt));
  1075. m.typeId = kEndMsgScId;
  1076. p->cbFunc(p->cbArg,&m,sizeof(m));
  1077. }
  1078. return rc;
  1079. }
  1080. void cmScoreClearPerfInfo( cmScH_t h )
  1081. {
  1082. cmSc_t* p = _cmScHandleToPtr(h);
  1083. unsigned i;
  1084. for(i=0; i<p->cnt; ++i)
  1085. {
  1086. p->array[i].perfSmpIdx = cmInvalidIdx;
  1087. p->array[i].perfVel = 0;
  1088. p->array[i].perfDynLvl = 0;
  1089. }
  1090. for(i=0; i<p->locCnt; ++i)
  1091. {
  1092. cmScoreSet_t* sp = p->loc[i].setList;
  1093. for(; sp!=NULL; sp=sp->llink)
  1094. sp->doneFl = false;
  1095. }
  1096. for(i=0; i<p->sectCnt; ++i)
  1097. {
  1098. unsigned j;
  1099. for(j=0; j<kScVarCnt; ++j)
  1100. p->sect[i].vars[j] = DBL_MAX;
  1101. }
  1102. p->nxtLocIdx = 0;
  1103. p->minSetLocIdx = cmInvalidIdx;
  1104. p->maxSetLocIdx = cmInvalidIdx;
  1105. }
  1106. bool _cmScIsSetPerfDone( cmScoreSet_t* sp )
  1107. {
  1108. unsigned i = 0;
  1109. for(i=0; i<sp->eleCnt; ++i)
  1110. if( sp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1111. return false;
  1112. return true;
  1113. }
  1114. void _cmScPerfSortTimes( unsigned *v, unsigned n )
  1115. {
  1116. unsigned i;
  1117. bool fl = true;
  1118. while(fl && n)
  1119. {
  1120. fl = false;
  1121. for(i=1; i<n; ++i)
  1122. {
  1123. if( v[i-1] > v[i] )
  1124. {
  1125. unsigned t = v[i-1];
  1126. v[i-1] = v[i];
  1127. v[i] = t;
  1128. fl = true;
  1129. }
  1130. }
  1131. --n;
  1132. }
  1133. }
  1134. bool _cmScPerfEven(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1135. {
  1136. unsigned i = 0;
  1137. double u = 0;
  1138. double x = 0;
  1139. bool sortFl = false;
  1140. bool printFl = true;
  1141. unsigned v[ stp->eleCnt ];
  1142. unsigned d[ stp->eleCnt - 1];
  1143. assert( stp->eleCnt > 1 );
  1144. // calculate the sum of the time between events
  1145. for(i=0; i<stp->eleCnt; ++i)
  1146. {
  1147. // if this event was not received - then the set is not valid
  1148. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1149. {
  1150. if( printFl && printMissFl)
  1151. printf("EVENESS: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1152. return false;
  1153. }
  1154. // load v[i]
  1155. v[i] = stp->eleArray[i]->perfSmpIdx;
  1156. // check for out of order elements
  1157. if( i> 0 )
  1158. if( v[i] < v[i-1] )
  1159. sortFl = true;
  1160. }
  1161. // sort the times in ascending order
  1162. if( sortFl )
  1163. _cmScPerfSortTimes(v,stp->eleCnt);
  1164. // calc the sum of time differences
  1165. for(i=1; i<stp->eleCnt; ++i)
  1166. u += d[i-1] = v[i] - v[i-1];
  1167. // calculate the average time between events
  1168. u /= stp->eleCnt-1;
  1169. // calculate the std-dev of the time between events
  1170. for(i=0; i<stp->eleCnt-1; ++i)
  1171. x += (d[i]-u)*(d[i]-u);
  1172. double sd = sqrt(x/(stp->eleCnt-1));
  1173. // compute the average z-score
  1174. double c = 0;
  1175. for(i=0; i<stp->eleCnt-1; ++i)
  1176. c += fabs(d[i]-u)/sd;
  1177. stp->value = c/(stp->eleCnt-1);
  1178. stp->doneFl = true;
  1179. if(printFl)
  1180. {
  1181. /*
  1182. for(i=0; i<stp->eleCnt; ++i)
  1183. {
  1184. printf("%i %i ",i,v[i]);
  1185. if( i > 0 )
  1186. printf("%i ", d[i-1]);
  1187. printf("\n");
  1188. }
  1189. */
  1190. printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
  1191. }
  1192. return true;
  1193. }
  1194. bool _cmScPerfDyn( cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1195. {
  1196. double a = 0;
  1197. unsigned i = 0;
  1198. bool printFl = true;
  1199. for(i=0; i<stp->eleCnt; ++i)
  1200. {
  1201. unsigned j;
  1202. // if this event was not received - then the set is not valid
  1203. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1204. {
  1205. if( printFl && printMissFl )
  1206. printf("DYNAMICS: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1207. return false;
  1208. }
  1209. unsigned m = 0; // lower bound for the first dyn. category
  1210. // determine the dynamic category for the performed velocity of each event
  1211. for(j=0; j<p->dynRefCnt; ++j)
  1212. {
  1213. // if the vel fall's into the jth dyn. category
  1214. if( m <= stp->eleArray[i]->perfVel && stp->eleArray[i]->perfVel < p->dynRefArray[j] )
  1215. break;
  1216. // store the min vel for the next dyn category
  1217. m = p->dynRefArray[j];
  1218. }
  1219. assert( j < p->dynRefCnt );
  1220. stp->eleArray[i]->perfDynLvl = j+1;
  1221. a += abs((j+1) - stp->eleArray[i]->dynVal);
  1222. if( p->cbFunc != NULL )
  1223. {
  1224. cmScMsg_t m;
  1225. m.typeId = kDynMsgScId;
  1226. m.u.dyn.evtIdx = stp->eleArray[i]->index;
  1227. m.u.dyn.dynLvl = stp->eleArray[i]->perfDynLvl;
  1228. p->cbFunc(p->cbArg,&m,sizeof(m));
  1229. }
  1230. }
  1231. stp->value = a / stp->eleCnt;
  1232. stp->doneFl = true;
  1233. if( printFl )
  1234. printf("DYNAMICS:%f\n",stp->value);
  1235. return true;
  1236. }
  1237. bool _cmScPerfTempo(cmSc_t* p, cmScoreSet_t* stp, bool printFl)
  1238. {
  1239. return false;
  1240. }
  1241. void _cmScPerfExec( cmSc_t* p, cmScoreSet_t* sp, bool printMissFl )
  1242. {
  1243. if( sp->doneFl == false )
  1244. {
  1245. switch( sp->varId )
  1246. {
  1247. case kEvenVarScId:
  1248. _cmScPerfEven(p,sp,printMissFl);
  1249. break;
  1250. case kDynVarScId:
  1251. _cmScPerfDyn(p,sp,printMissFl);
  1252. break;
  1253. case kTempoVarScId:
  1254. _cmScPerfTempo(p,sp,printMissFl);
  1255. break;
  1256. default:
  1257. { assert(0); }
  1258. }
  1259. }
  1260. }
  1261. void _cmScPerfExecRange( cmSc_t* p )
  1262. {
  1263. if( p->minSetLocIdx == cmInvalidIdx || p->maxSetLocIdx==cmInvalidIdx )
  1264. return;
  1265. unsigned i = p->minSetLocIdx;
  1266. for(; i<=p->maxSetLocIdx; ++i)
  1267. {
  1268. cmScoreSet_t* sp = p->loc[i].setList;
  1269. for(; sp!=NULL; sp=sp->llink)
  1270. _cmScPerfExec(p,sp,false);
  1271. }
  1272. }
  1273. bool _cmScSetPerfEvent( cmSc_t* p, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1274. {
  1275. assert(locIdx < p->locCnt );
  1276. cmScoreLoc_t* lp = p->loc + locIdx;
  1277. bool foundFl = false;
  1278. bool doneFl = true;
  1279. unsigned i;
  1280. // locate the event at the loc[locIdx]
  1281. for(i=0; i<lp->evtCnt; ++i)
  1282. {
  1283. cmScoreEvt_t* ep = lp->evtArray[i];
  1284. if( ep->type == kNonEvtScId )
  1285. {
  1286. if( ep->pitch == pitch )
  1287. {
  1288. assert( ep->perfSmpIdx == cmInvalidIdx );
  1289. ep->perfSmpIdx = smpIdx;
  1290. ep->perfVel = vel;
  1291. foundFl = true;
  1292. }
  1293. // check if all notes have arrived for this location
  1294. if( ep->perfSmpIdx == cmInvalidIdx )
  1295. doneFl = false;
  1296. }
  1297. }
  1298. // the event must always be found
  1299. assert( foundFl );
  1300. return doneFl;
  1301. }
  1302. bool cmScoreSetPerfEvent( cmScH_t h, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1303. {
  1304. cmSc_t* p = _cmScHandleToPtr(h);
  1305. return _cmScSetPerfEvent(p,locIdx,smpIdx,pitch,vel);
  1306. }
  1307. void cmScoreExecPerfEvent( cmScH_t h, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1308. {
  1309. unsigned i;
  1310. cmSc_t* p = _cmScHandleToPtr(h);
  1311. bool doneFl = _cmScSetPerfEvent(p,locIdx,smpIdx,pitch,vel);
  1312. unsigned printLvl = 1;
  1313. cmScoreLoc_t* lp = p->loc + locIdx;
  1314. // all events for a location must be complete to trigger attached events
  1315. if( doneFl == false )
  1316. return;
  1317. if( p->loc[locIdx].setList != NULL )
  1318. {
  1319. // set idx of most recent loc w/ a set end event
  1320. p->maxSetLocIdx = locIdx;
  1321. if( p->minSetLocIdx == cmInvalidIdx )
  1322. p->minSetLocIdx = locIdx;
  1323. }
  1324. // attempt to calculate all sets between loc[p->minSetLocIdx] and loc[p->maxSetLocIdx]
  1325. _cmScPerfExecRange(p);
  1326. // prevent event retriggering or going backwards
  1327. if( printLvl && locIdx < p->nxtLocIdx )
  1328. {
  1329. printf("----- BACK ----- \n");
  1330. return;
  1331. }
  1332. if( printLvl && locIdx > p->nxtLocIdx )
  1333. {
  1334. printf("----- SKIP ----- \n");
  1335. }
  1336. // for each location between the current and previous location
  1337. for(; p->nxtLocIdx<=locIdx; ++p->nxtLocIdx)
  1338. {
  1339. lp = p->loc + p->nxtLocIdx;
  1340. // if this location is the start of a new section - then apply
  1341. // sets that are assigned to this section
  1342. if( lp->begSectPtr != NULL && lp->begSectPtr->setCnt > 0 )
  1343. {
  1344. // notice the location of the oldest section start - once we cross this point
  1345. // it is too late to notice set completions - so incr p->inSetLocIdx
  1346. if( lp->begSectPtr->setCnt )
  1347. p->minSetLocIdx = p->nxtLocIdx+1;
  1348. for(i=0; i<lp->begSectPtr->setCnt; ++i)
  1349. {
  1350. cmScoreSet_t* stp = lp->begSectPtr->setArray[i];
  1351. if( stp->doneFl == false )
  1352. _cmScPerfExec(p, stp, printLvl>0 );
  1353. if( stp->doneFl )
  1354. {
  1355. assert( stp->varId < kScVarCnt );
  1356. lp->begSectPtr->vars[ stp->varId ] = stp->value;
  1357. if( p->cbFunc != NULL )
  1358. {
  1359. cmScMsg_t m;
  1360. m.typeId = kVarMsgScId;
  1361. m.u.meas.varId = stp->varId;
  1362. m.u.meas.value = stp->value;
  1363. p->cbFunc(p->cbArg,&m,sizeof(m));
  1364. }
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }
  1370. void cmScoreSetPerfValue( cmScH_t h, unsigned locIdx, unsigned varId, double value )
  1371. {
  1372. cmSc_t* p = _cmScHandleToPtr(h);
  1373. int li = locIdx;
  1374. for(; li>=0; --li)
  1375. if( p->loc[li].begSectPtr != NULL )
  1376. {
  1377. assert( varId < kScVarCnt );
  1378. p->loc[li].begSectPtr->vars[varId] = value;
  1379. break;
  1380. }
  1381. assert( li>=0);
  1382. }
  1383. void cmScoreSetPerfDynLevel( cmScH_t h, unsigned evtIdx, unsigned dynLvl )
  1384. {
  1385. cmSc_t* p = _cmScHandleToPtr(h);
  1386. assert(evtIdx < p->cnt );
  1387. p->array[ evtIdx ].perfDynLvl = dynLvl;
  1388. }
  1389. cmScRC_t cmScoreDecode( const void* msg, unsigned msgByteCnt, cmScMsg_t* m)
  1390. {
  1391. cmScMsg_t* mp = (cmScMsg_t*)msg;
  1392. *m = *mp;
  1393. return kOkScRC;
  1394. }
  1395. void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
  1396. {
  1397. cmSc_t* p = _cmScHandleToPtr(h);
  1398. unsigned i;
  1399. for(i=0; i<20 /*p->cnt*/; ++i)
  1400. {
  1401. cmScoreEvt_t* r = p->array + i;
  1402. switch(r->type)
  1403. {
  1404. case kNonEvtScId:
  1405. cmRptPrintf(rpt,"%5i %3i %3i %s 0x%2x %c%c%c %s\n",
  1406. i,
  1407. r->barNumb,
  1408. r->barNoteIdx,
  1409. cmScEvtTypeIdToLabel(r->type),
  1410. r->pitch,
  1411. cmIsFlag(r->flags,kEvenScFl) ? 'e' : ' ',
  1412. cmIsFlag(r->flags,kTempoScFl) ? 't' : ' ',
  1413. cmIsFlag(r->flags,kDynScFl) ? 'd' : ' ',
  1414. cmIsFlag(r->flags,kDynScFl) ? cmScDynIdToLabel(r->dynVal) : "");
  1415. break;
  1416. default:
  1417. break;
  1418. }
  1419. }
  1420. }
  1421. void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
  1422. {
  1423. cmScH_t h = cmScNullHandle;
  1424. if( cmScoreInitialize(ctx,&h,fn,NULL,0,NULL,NULL) != kOkScRC )
  1425. return;
  1426. cmScorePrint(h,&ctx->rpt);
  1427. cmScoreFinalize(&h);
  1428. }
  1429. // 1. Fix absolute message time which was incorrect on original score file.
  1430. // 2.
  1431. void cmScoreFix( cmCtx_t* ctx )
  1432. {
  1433. const cmChar_t* mfn = "/home/kevin/src/cmgv/src/gv/data/ImaginaryThemes.mid";
  1434. const cmChar_t* crfn = "/home/kevin/src/cmgv/src/gv/data/mod0a.txt";
  1435. const cmChar_t* cwfn = "/home/kevin/src/cmgv/src/gv/data/mod1.csv";
  1436. cmMidiFileH_t mfH = cmMidiFileNullHandle;
  1437. cmCsvH_t csvH = cmCsvNullHandle;
  1438. const cmMidiTrackMsg_t** msg = NULL;
  1439. double secs = 0.0;
  1440. int ci,mi,crn,mn;
  1441. bool errFl = true;
  1442. unsigned handCnt = 0;
  1443. unsigned midiMissCnt = 0;
  1444. if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
  1445. goto errLabel;
  1446. if( cmCsvLexRegisterMatcher(csvH, cmCsvLexNextAvailId(csvH), _cmScLexSciPitchMatcher ) != kOkCsvRC )
  1447. goto errLabel;
  1448. if( cmCsvParseFile(csvH, crfn, 0 ) != kOkCsvRC )
  1449. goto errLabel;
  1450. if( cmMidiFileOpen(mfn,&mfH,ctx) != kOkMfRC )
  1451. goto errLabel;
  1452. cmMidiFileTickToMicros(mfH);
  1453. cmMidiFileCalcNoteDurations(mfH);
  1454. mn = cmMidiFileMsgCount(mfH);
  1455. msg = cmMidiFileMsgArray(mfH);
  1456. crn = cmCsvRowCount(csvH);
  1457. // for each row in the score file
  1458. for(ci=1,mi=0; ci<crn && cmCsvLastRC(csvH)==kOkCsvRC; ++ci)
  1459. {
  1460. unsigned id;
  1461. // zero the duration column
  1462. if( cmCsvCellPtr(csvH, ci, kDSecsColScIdx ) != NULL )
  1463. cmCsvSetCellUInt( csvH, ci, kDSecsColScIdx, 0 );
  1464. // get the MIDI file event id for this row
  1465. if((id = cmCsvCellUInt(csvH,ci,kMidiFileIdColScIdx)) == UINT_MAX)
  1466. {
  1467. // this is a hand-entered event - so it has no event id
  1468. ++handCnt;
  1469. }
  1470. else
  1471. {
  1472. for(; mi<mn; ++mi)
  1473. {
  1474. const cmMidiTrackMsg_t* m = msg[mi];
  1475. assert( mi+1 <= id );
  1476. secs += m->dtick/1000000.0;
  1477. if( mi+1 != id )
  1478. {
  1479. if( m->status == kNoteOnMdId && m->u.chMsgPtr->d1>0 )
  1480. {
  1481. // this MIDI note-on does not have a corresponding score event
  1482. ++midiMissCnt;
  1483. }
  1484. }
  1485. else
  1486. {
  1487. cmCsvSetCellDouble( csvH, ci, kSecsColScIdx, secs );
  1488. ++mi;
  1489. if( m->status == kNoteOnMdId )
  1490. cmCsvSetCellDouble( csvH, ci, kDSecsColScIdx, m->u.chMsgPtr->durTicks/1000000.0 );
  1491. break;
  1492. }
  1493. }
  1494. if( mi==mn)
  1495. printf("done on row:%i\n",ci);
  1496. }
  1497. }
  1498. if( cmCsvLastRC(csvH) != kOkCsvRC )
  1499. goto errLabel;
  1500. if( cmCsvWrite(csvH,cwfn) != kOkCsvRC )
  1501. goto errLabel;
  1502. errFl = false;
  1503. errLabel:
  1504. if( errFl )
  1505. printf("Score fix failed.\n");
  1506. else
  1507. printf("Score fix done! hand:%i miss:%i\n",handCnt,midiMissCnt);
  1508. cmMidiFileClose(&mfH);
  1509. cmCsvFinalize(&csvH);
  1510. }