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.

cmScore.c 74KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891
  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 "cmLinkedHeap.h"
  10. #include "cmTime.h"
  11. #include "cmMidi.h"
  12. #include "cmLex.h"
  13. #include "cmCsv.h"
  14. #include "cmSymTbl.h"
  15. #include "cmMidiFile.h"
  16. #include "cmAudioFile.h"
  17. #include "cmTimeLine.h"
  18. #include "cmText.h"
  19. #include "cmFile.h"
  20. #include "cmScore.h"
  21. #include "cmVectOpsTemplateMain.h"
  22. cmScH_t cmScNullHandle = cmSTATIC_NULL_HANDLE;
  23. enum
  24. {
  25. kLabelCharCnt = 7,
  26. kInvalidDynScId = 0,
  27. };
  28. enum
  29. {
  30. kMidiFileIdColScIdx= 0,
  31. kEventIdColScIdx = 2,
  32. kTypeLabelColScIdx = 3,
  33. kDSecsColScIdx = 4,
  34. kSecsColScIdx = 5,
  35. kD0ColScIdx = 9,
  36. kD1ColScIdx = 10,
  37. kPitchColScIdx = 11,
  38. kBarColScIdx = 13,
  39. kSkipColScIdx = 14,
  40. kEvenColScIdx = 15,
  41. kGraceColScIdx = 16,
  42. kTempoColScIdx = 17,
  43. kFracColScIdx = 18,
  44. kDynColScIdx = 19,
  45. kSectionColScIdx = 20,
  46. kRecdPlayColScIdx = 21,
  47. kRemarkColScIdx = 22
  48. };
  49. typedef struct
  50. {
  51. unsigned id;
  52. unsigned flag;
  53. cmChar_t label[ kLabelCharCnt + 1 ];
  54. } cmScEvtRef_t;
  55. typedef struct cmScSect_str
  56. {
  57. const cmChar_t* label;
  58. unsigned startIdx;
  59. struct cmScSect_str* link;
  60. } cmScSect_t;
  61. typedef struct cmScSetEle_str
  62. {
  63. cmChar_t* label;
  64. unsigned eleIdx;
  65. struct cmScSetEle_str* link;
  66. } cmScSetEle_t;
  67. typedef struct cmScSet_str
  68. {
  69. unsigned typeFl; // type of this set
  70. cmScSetEle_t* eles; // indexes of set elements
  71. cmScSetEle_t* sects; // application section labels
  72. bool inFl; // true if currently accepting elements
  73. struct cmScSet_str* link; //
  74. } cmScSet_t;
  75. typedef struct cmScMark_str
  76. {
  77. cmMarkScMId_t cmdId;
  78. unsigned labelSymId;
  79. unsigned scoreIdx;
  80. unsigned csvRowIdx;
  81. struct cmScMark_str* link;
  82. } cmScMark_t;
  83. typedef struct
  84. {
  85. cmErr_t err;
  86. cmCsvH_t cH;
  87. cmSymTblH_t stH;
  88. cmScCb_t cbFunc;
  89. void* cbArg;
  90. cmChar_t* fn;
  91. double srate;
  92. cmScoreEvt_t* array;
  93. unsigned cnt;
  94. cmScoreLoc_t* loc;
  95. unsigned locCnt;
  96. cmScoreSection_t* sect;
  97. unsigned sectCnt;
  98. unsigned* markLabelArray; // one symId per unique cmScoreMarker_t.labelSymId;
  99. unsigned markLabelCnt;
  100. unsigned sciPitchLexTId; // sci pitch and section id lexer token id's
  101. unsigned sectionLexTId;
  102. cmScSect_t* sectList; // lists used during parsing
  103. cmScSet_t* setList;
  104. cmScMark_t* markList;
  105. cmScoreSet_t* sets;
  106. unsigned setCnt;
  107. unsigned* dynRefArray;
  108. unsigned dynRefCnt;
  109. unsigned nxtLocIdx;
  110. unsigned minSetLocIdx;
  111. unsigned maxSetLocIdx;
  112. } cmSc_t;
  113. cmScEvtRef_t _cmScEvtRefArray[] =
  114. {
  115. { kTimeSigEvtScId, kTimeSigMdId, "tsg" },
  116. { kKeySigEvtScId, kKeySigMdId, "ksg" },
  117. { kTempoEvtScId, kTempoMdId, "tmp" },
  118. { kTrackEvtScId, kTrkNameMdId, "trk" },
  119. { kTextEvtScId, kTextMdId, "txt" },
  120. { kNameEvtScId, kInstrNameMdId,"nam" },
  121. { kEOTrackEvtScId, kEndOfTrkMdId, "eot" },
  122. { kCopyEvtScId, kCopyMdId, "cpy" },
  123. { kBlankEvtScId, 0, "blk" },
  124. { kBarEvtScId, 0, "bar" },
  125. { kPgmEvtScId, kPgmMdId, "pgm" },
  126. { kCtlEvtScId, kCtlMdId, "ctl" },
  127. { kNonEvtScId, kNoteOnMdId, "non" },
  128. { kInvalidEvtScId, 0, "***" }
  129. };
  130. cmScEvtRef_t _cmScDynRefArray[] =
  131. {
  132. { 1, 0, "pppp"},
  133. { 2, 0, "ppp" },
  134. { 3, 0, "pp" },
  135. { 4, 0, "p" },
  136. { 5, 0, "mp" },
  137. { 6, 0, "mf" },
  138. { 7, 0, "f" },
  139. { 8, 0, "ff" },
  140. { 9, 0, "fff" },
  141. { kInvalidDynScId,0, "***" },
  142. };
  143. cmScEvtRef_t _cmScVarRefArray[] =
  144. {
  145. { kEvenVarScId, kEvenScFl, "e"},
  146. { kDynVarScId, kDynScFl, "d"},
  147. { kTempoVarScId,kTempoScFl,"t"},
  148. { cmInvalidId, 0, "@"}
  149. };
  150. cmSc_t* _cmScHandleToPtr( cmScH_t h )
  151. {
  152. cmSc_t* p = (cmSc_t*)h.h;
  153. assert( p != NULL );
  154. return p;
  155. }
  156. unsigned _cmScEvtTypeLabelToId( const cmChar_t* label )
  157. {
  158. cmScEvtRef_t* r = _cmScEvtRefArray;
  159. for(; r->id != kInvalidEvtScId; ++r )
  160. if( strcmp(label,r->label) == 0 )
  161. return r->id;
  162. return kInvalidEvtScId;
  163. }
  164. const cmChar_t* cmScEvtTypeIdToLabel( unsigned id )
  165. {
  166. cmScEvtRef_t* r = _cmScEvtRefArray;
  167. for(; r->id != kInvalidEvtScId; ++r )
  168. if( r->id == id )
  169. return r->label;
  170. return NULL;
  171. }
  172. const cmChar_t* cmScStatusToOpString( unsigned id )
  173. {
  174. if( id == 0 )
  175. return "<unknown>";
  176. cmScEvtRef_t* r = _cmScEvtRefArray;
  177. for(; r->id != kInvalidEvtScId; ++r )
  178. if( r->flag == id )
  179. return r->label;
  180. return NULL;
  181. }
  182. unsigned _cmScDynLabelToId( const cmChar_t* label )
  183. {
  184. cmScEvtRef_t* r = _cmScDynRefArray;
  185. for(; r->id != kInvalidEvtScId; ++r )
  186. if( strncmp(label,r->label,strlen(r->label)) == 0 )
  187. return r->id;
  188. return kInvalidDynScId;
  189. }
  190. // return the count of dynamic label/id pairs
  191. unsigned _cmScDynLabelCount( )
  192. {
  193. unsigned n = 0;
  194. cmScEvtRef_t* r = _cmScDynRefArray;
  195. for(; r->id != kInvalidEvtScId; ++r )
  196. ++n;
  197. return n;
  198. }
  199. const cmChar_t* cmScDynIdToLabel( unsigned id )
  200. {
  201. cmScEvtRef_t* r = _cmScDynRefArray;
  202. for(; r->id != kInvalidDynScId; ++r )
  203. if( r->id == id )
  204. return r->label;
  205. return NULL;
  206. }
  207. char _cmScVarFlagToChar( unsigned flags )
  208. {
  209. unsigned i;
  210. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  211. if( _cmScVarRefArray[i].flag == flags )
  212. return _cmScVarRefArray[i].label[0];
  213. assert(0);
  214. return ' ';
  215. }
  216. char _cmScVarIdToChar( unsigned id )
  217. {
  218. unsigned i;
  219. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  220. if( _cmScVarRefArray[i].id == id )
  221. return _cmScVarRefArray[i].label[0];
  222. assert(0);
  223. return ' ';
  224. }
  225. unsigned _cmScVarFlagToId( unsigned flags )
  226. {
  227. unsigned i;
  228. for(i=0; _cmScVarRefArray[i].id!=cmInvalidId; ++i)
  229. if( _cmScVarRefArray[i].flag == flags )
  230. return _cmScVarRefArray[i].id;
  231. assert(0);
  232. return cmInvalidId;
  233. }
  234. const char* _cmScFlagsToStr( unsigned flags, char* buf, int bufCharCnt )
  235. {
  236. unsigned i=0;
  237. if( cmIsFlag(flags,kEvenScFl) )
  238. {
  239. assert(i<bufCharCnt);
  240. buf[i] = 'e';
  241. ++i;
  242. }
  243. if( cmIsFlag(flags,kDynScFl) )
  244. {
  245. assert(i<bufCharCnt);
  246. buf[i] = 'd';
  247. ++i;
  248. }
  249. if( cmIsFlag(flags,kTempoScFl ))
  250. {
  251. assert(i<bufCharCnt);
  252. buf[i] = 't';
  253. ++i;
  254. }
  255. assert(i<bufCharCnt);
  256. buf[i] = 0;
  257. return buf;
  258. }
  259. unsigned _cmScLexSciPitchMatcher( const cmChar_t* cp, unsigned cn )
  260. {
  261. if( cp==NULL || cn < 2 )
  262. return 0;
  263. // first char must be "A-G"
  264. if( strspn(cp,"ABCDEFG") != 1 )
  265. return 0;
  266. unsigned i = 1;
  267. // next char could be accidental
  268. if( cp[i] == '#' || cp[i] == 'b' )
  269. ++i; // i==2
  270. // the 2nd or 3rd char must be a digit
  271. if( i>=cn || isdigit(cp[i]) == false )
  272. return 0;
  273. ++i; // i==2 or i==3
  274. // the 3rd or 4th char must be a digit or EOS
  275. if( i>=cn || isdigit(cp[i]) == false )
  276. return i;
  277. ++i;
  278. return i;
  279. }
  280. unsigned _cmScLexSectionIdMatcher( const cmChar_t* cp, unsigned cn )
  281. {
  282. if( cp==NULL || cn < 2 )
  283. return 0;
  284. // first char must be a number
  285. if( !isdigit(cp[0]) )
  286. return 0;
  287. // if 2nd char is a char then terminate
  288. if( 'a'<=cp[1] && cp[1]<='z' )
  289. return 2;
  290. // if 2nd char is digit and 3rd char is char then terminate
  291. if( isdigit(cp[1]) && cn>2 && 'a'<=cp[2] && cp[2]<='z' )
  292. return 3;
  293. return 0;
  294. }
  295. void _cmScFreeMarkList( cmScMark_t* markList )
  296. {
  297. cmScMark_t* mp = markList;
  298. while( mp!=NULL )
  299. {
  300. cmScMark_t* np = mp->link;
  301. cmMemFree(mp);
  302. mp = np;
  303. }
  304. }
  305. void _cmScFreeSetList( cmScSet_t* setList )
  306. {
  307. cmScSet_t* tp = setList;
  308. cmScSet_t* ntp = NULL;
  309. while(tp!=NULL)
  310. {
  311. ntp = tp->link;
  312. cmScSetEle_t* ep = tp->eles;
  313. while( ep != NULL )
  314. {
  315. cmScSetEle_t* nep = ep->link;
  316. cmMemFree(ep);
  317. ep = nep;
  318. }
  319. ep = tp->sects;
  320. while( ep != NULL )
  321. {
  322. cmScSetEle_t* nep = ep->link;
  323. cmMemFree(ep->label);
  324. cmMemFree(ep);
  325. ep = nep;
  326. }
  327. cmMemFree(tp);
  328. tp = ntp;
  329. }
  330. }
  331. cmScRC_t _cmScFinalize( cmSc_t* p )
  332. {
  333. cmScRC_t rc = kOkScRC;
  334. unsigned i;
  335. if( cmCsvFinalize(&p->cH) != kOkCsvRC )
  336. return rc;
  337. if( p->sets != NULL )
  338. {
  339. for(i=0; i<p->setCnt; ++i)
  340. {
  341. cmMemFree(p->sets[i].eleArray);
  342. cmMemFree(p->sets[i].sectArray);
  343. cmMemFree(p->sets[i].symArray);
  344. cmMemFree(p->sets[i].costSymArray);
  345. }
  346. cmMemFree(p->sets);
  347. }
  348. _cmScFreeSetList(p->setList);
  349. _cmScFreeMarkList(p->markList);
  350. if( p->loc != NULL )
  351. {
  352. for(i=0; i<p->locCnt; ++i)
  353. {
  354. cmMemFree(p->loc[i].evtArray);
  355. if( p->loc[i].begSectPtr != NULL )
  356. cmMemFree(p->loc[i].begSectPtr->setArray);
  357. // free the marker list assoc'd with this location
  358. cmScoreMarker_t* smp = p->loc[i].markList;
  359. while( smp!=NULL )
  360. {
  361. cmScoreMarker_t* np = smp->link;
  362. cmMemFree(smp);
  363. smp = np;
  364. }
  365. }
  366. cmMemFree(p->loc);
  367. }
  368. cmMemPtrFree(&p->dynRefArray);
  369. cmMemFree(p->markLabelArray);
  370. cmMemFree(p->sect);
  371. cmMemFree(p->fn);
  372. cmMemFree(p->array);
  373. cmMemFree(p);
  374. return rc;
  375. }
  376. cmScRC_t _cmScParseBar( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, int* barNumb )
  377. {
  378. if((*barNumb = cmCsvCellInt(p->cH,rowIdx,kBarColScIdx)) == INT_MAX )
  379. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to parse the bar number.");
  380. s->type = kBarEvtScId;
  381. s->secs = 0;
  382. s->barNumb = *barNumb;
  383. s->csvRowNumb = rowIdx + 1;
  384. return kOkScRC;
  385. }
  386. cmScSet_t* _cmScNewSet( cmSc_t* p, unsigned typeFl )
  387. {
  388. // create a new set record
  389. cmScSet_t* nsp = cmMemAllocZ(cmScSet_t,1);
  390. nsp->inFl = true;
  391. nsp->typeFl = typeFl;
  392. if( p->setList == NULL )
  393. p->setList = nsp;
  394. else
  395. {
  396. // go to the end of the the set list
  397. cmScSet_t* sp = p->setList;
  398. assert(sp!=NULL);
  399. while( sp->link != NULL )
  400. sp = sp->link;
  401. sp->link = nsp;
  402. }
  403. return nsp;
  404. }
  405. cmScSet_t* _cmScFindSet( cmSc_t* p, unsigned typeFl )
  406. {
  407. // locate the set currently accepting ele's for this type
  408. cmScSet_t* sp = p->setList;
  409. for(; sp != NULL; sp=sp->link )
  410. if( sp->typeFl == typeFl && sp->inFl )
  411. break;
  412. return sp;
  413. }
  414. void _cmScSetDone(cmSc_t* p, unsigned typeFl)
  415. {
  416. cmScSet_t* sp = _cmScFindSet(p,typeFl);
  417. assert( sp != NULL );
  418. sp->inFl = false;
  419. }
  420. // This function is called during parsing to
  421. // insert a set element or set section into a cmScSet_t
  422. // element or section linked list. Either the scoreIdx
  423. // or the label is valid but not both.
  424. cmScSet_t* _cmScInsertSetEle(cmSc_t* p, unsigned scoreIdx, unsigned typeFl, const cmChar_t* label, unsigned labelCharCnt)
  425. {
  426. assert( scoreIdx!=cmInvalidId || (scoreIdx==cmInvalidIdx && label!=NULL && labelCharCnt>0));
  427. cmScSet_t* sp = _cmScFindSet(p,typeFl);
  428. if( sp == NULL )
  429. sp = _cmScNewSet(p,typeFl);
  430. // allocate a new set element record
  431. cmScSetEle_t* nep = cmMemAllocZ(cmScSetEle_t,1);
  432. cmScSetEle_t** list = NULL;
  433. nep->eleIdx = scoreIdx;
  434. if( label == NULL )
  435. {
  436. // all elements must be of the same type
  437. assert( sp->typeFl == typeFl );
  438. sp->typeFl = typeFl;
  439. list = &sp->eles;
  440. }
  441. else
  442. {
  443. nep->label = cmMemAllocStrN(label,labelCharCnt);
  444. list = &sp->sects;
  445. }
  446. // *list refers to sp->sects or sp->ele's depending on the type of ele
  447. if( *list == NULL )
  448. *list = nep;
  449. else
  450. {
  451. // got to the last element in the set
  452. cmScSetEle_t* ep = *list;
  453. while( ep->link != NULL )
  454. ep = ep->link;
  455. // append the new element to the end of the list
  456. ep->link = nep;
  457. }
  458. return sp;
  459. }
  460. // Extract the next attribute section identifier.
  461. const cmChar_t* _cmScParseOneSetSection( cmSc_t* p, unsigned typeFl, const cmChar_t* c0p )
  462. {
  463. // advance white space
  464. while( *c0p && (isspace(*c0p) || *c0p==',') )
  465. ++c0p;
  466. if( *c0p==0 )
  467. return c0p;
  468. // c0p now points to a section id or an asterisk
  469. const cmChar_t* c1p = c0p;
  470. // advance past section id
  471. while( *c1p && (!isspace(*c1p) && (isdigit(*c1p) || isalpha(*c1p))))
  472. ++c1p;
  473. // if c0p pointed to an asterisk then c1p is still equal to c0p
  474. if( c1p > c0p )
  475. _cmScInsertSetEle(p,cmInvalidIdx,typeFl,c0p,c1p-c0p);
  476. return c1p;
  477. }
  478. // Parse an attribute string to extract the section
  479. // identifiers which may follow the attribute token (e,t,mf,ff,...)
  480. cmScRC_t _cmScParseAttr(cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned typeFl)
  481. {
  482. const cmChar_t* cp = text;
  483. // insert a set element - all attribute's produce one element record
  484. _cmScInsertSetEle(p,scoreIdx,typeFl,NULL,0);
  485. // advance past the attribute type marking (e,t,(p,mf,f,fff,etc)) in search
  486. // of section identifiers
  487. while( *cp && !isspace(*cp) )
  488. ++cp;
  489. if( *cp )
  490. {
  491. // search for the first section identifier
  492. if((cp =_cmScParseOneSetSection(p,typeFl,cp)) != NULL )
  493. {
  494. bool asteriskFl = false;
  495. // search for the second section identifier
  496. if((cp = _cmScParseOneSetSection(p,typeFl,cp)) != NULL && *cp!=0 )
  497. asteriskFl = *cp == '*';
  498. _cmScSetDone(p,typeFl);
  499. // if the attr just parsed ended with an asterisk then it is both
  500. // the last element of the previous set and the first ele of the
  501. // next set
  502. if( asteriskFl )
  503. {
  504. // if the attr just parsed had a section id then it was the last
  505. // element in the set - create a new set record to hold the next set
  506. _cmScNewSet(p,typeFl);
  507. _cmScInsertSetEle(p,scoreIdx,typeFl,NULL,0);
  508. }
  509. }
  510. }
  511. return kOkScRC;
  512. }
  513. // Parse a record/playback string
  514. cmScRC_t _cmScParseMarkers( cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned rowIdx )
  515. {
  516. const cmChar_t* cp = text;
  517. const cmChar_t* ip;
  518. const cmChar_t* ep;
  519. // if no symbol table has been registered then don't bother storing markers.
  520. // (NOTE - THIS IS A HACK BECAUSE THE SCORE OBJECT USED IN THE cmdIf DOES NOT HAVE
  521. // A SYMBOL TABLE - WE COULD EASILY ADD ONE IF IT EVENTUALLY NEEDS ACCESS TO THE MARKERS
  522. // - OR A SYMBOL TABLE COULD BE ADDED TO THE SCORE ITSELF.)
  523. if( cmSymTblIsValid(p->stH) == false )
  524. return kOkScRC;
  525. for(;(cp = cmTextNextNonWhiteC(cp)) != NULL; cp=ep )
  526. {
  527. // go to command/id space
  528. if((ip = cmTextNextWhiteOrEosC(cp)) == NULL )
  529. goto errLabel;
  530. // goto label
  531. if((ip = cmTextNextNonWhiteC(ip)) == NULL )
  532. goto errLabel;
  533. // goto end of label
  534. if((ep = cmTextNextWhiteOrEosC(ip)) == NULL )
  535. goto errLabel;
  536. else
  537. {
  538. unsigned n = (ep-ip)+1;
  539. cmChar_t markTextStr[n+1];
  540. strncpy(markTextStr,ip,n);
  541. markTextStr[n] = 0;
  542. // remove any trailing white space
  543. cmTextTrimEnd(markTextStr);
  544. cmMarkScMId_t cmdId = kInvalidScMId;
  545. switch( *cp )
  546. {
  547. case 'c': cmdId = kRecdBegScMId; break;
  548. case 'e': cmdId = kRecdEndScMId; break;
  549. case 'p': cmdId = kPlayBegScMId; break;
  550. case 'd': cmdId = kPlayEndScMId; break;
  551. case 'f': cmdId = kFadeScMId; break;
  552. default:
  553. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unrecognized marker command character '%c' at row index %i.",*cp,rowIdx);
  554. }
  555. cmScMark_t* mp = cmMemAllocZ(cmScMark_t,1);
  556. mp->cmdId = cmdId;
  557. mp->labelSymId = cmSymTblRegisterSymbol(p->stH,markTextStr);
  558. mp->scoreIdx = scoreIdx;
  559. mp->csvRowIdx = rowIdx;
  560. //printf("%i %c '%s'\n",rowIdx,*cp,markTextStr);
  561. // insert the new mark at the end of the list
  562. if( p->markList == NULL )
  563. p->markList = mp;
  564. else
  565. {
  566. cmScMark_t* ep = p->markList;
  567. while( ep->link != NULL )
  568. ep = ep->link;
  569. ep->link = mp;
  570. }
  571. }
  572. }
  573. return kOkScRC;
  574. errLabel:
  575. return cmErrMsg(&p->err,kSyntaxErrScRC,"Invalid record/playback field ('%s') on row index:%i.",cmStringNullGuard(text),rowIdx);
  576. }
  577. void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
  578. {
  579. printf("%s\n",label);
  580. const cmScSet_t* sp = setList;
  581. for(; sp != NULL; sp=sp->link )
  582. {
  583. const cmScSetEle_t* ep = sp->eles;
  584. for(; ep!=NULL; ep=ep->link)
  585. printf("%i ",ep->eleIdx);
  586. printf(" : ");
  587. for(ep=sp->sects; ep!=NULL; ep=ep->link)
  588. printf("%s ",cmStringNullGuard(ep->label));
  589. printf("\n");
  590. }
  591. }
  592. cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned scoreIdx, int barNumb, unsigned barNoteIdx )
  593. {
  594. cmScRC_t rc = kOkScRC;
  595. unsigned flags = 0;
  596. unsigned dynVal = kInvalidDynScId;
  597. const cmChar_t* sciPitch;
  598. cmMidiByte_t midiPitch;
  599. const cmChar_t* attr;
  600. double secs;
  601. double durSecs;
  602. unsigned eventId;
  603. const cmCsvCell_t* cell;
  604. s += scoreIdx;
  605. eventId = cmCsvCellUInt(p->cH,rowIdx,kEventIdColScIdx);
  606. // verify the scientific pitch cell was formatted correcly
  607. if((cell = cmCsvCellPtr(p->cH,rowIdx,kPitchColScIdx)) == NULL || cell->lexTId != p->sciPitchLexTId )
  608. return cmErrMsg(&p->err,kSyntaxErrScRC,"Pitch column format error.");
  609. if((sciPitch = cmCsvCellText(p->cH,rowIdx,kPitchColScIdx)) == NULL )
  610. return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
  611. if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch)
  612. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. ");
  613. // get the sec's field - or DBL_MAX if it is not set
  614. if((secs = cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
  615. flags += kInvalidScFl;
  616. // skip attribute
  617. if((attr = cmCsvCellText(p->cH,rowIdx,kSkipColScIdx)) != NULL && *attr == 's' )
  618. flags += kSkipScFl;
  619. // evenness attribute
  620. if((attr = cmCsvCellText(p->cH,rowIdx,kEvenColScIdx)) != NULL && *attr == 'e' )
  621. {
  622. flags += kEvenScFl;
  623. _cmScParseAttr(p,scoreIdx,attr,kEvenScFl);
  624. }
  625. // grace attribute
  626. if((attr = cmCsvCellText(p->cH,rowIdx,kGraceColScIdx)) != NULL && *attr == 'g' )
  627. {
  628. flags += kGraceScFl;
  629. if( cmIsNotFlag(flags,kEvenScFl) )
  630. return cmErrMsg(&p->err,kSyntaxErrScRC,"All 'grace' notes should also be 'even' notes.");
  631. }
  632. // tempo attribute
  633. if((attr = cmCsvCellText(p->cH,rowIdx,kTempoColScIdx)) != NULL && *attr == 't' )
  634. {
  635. flags += kTempoScFl;
  636. _cmScParseAttr(p,scoreIdx,attr,kTempoScFl);
  637. }
  638. // dynamics attribute
  639. if((attr = cmCsvCellText(p->cH,rowIdx,kDynColScIdx)) != NULL )
  640. {
  641. if((dynVal = _cmScDynLabelToId(attr)) == kInvalidDynScId )
  642. return cmErrMsg(&p->err,kSyntaxErrScRC,"Unknown dynamic label '%s'.",cmStringNullGuard(attr));
  643. flags += kDynScFl;
  644. _cmScParseAttr(p,scoreIdx,attr,kDynScFl);
  645. }
  646. // tempo/non-grace rythmic value
  647. if( cmIsFlag(flags,kTempoScFl) || (cmIsFlag(flags,kEvenScFl) && cmIsNotFlag(flags,kGraceScFl)) )
  648. {
  649. double frac = cmCsvCellDouble(p->cH,rowIdx,kFracColScIdx);
  650. // no 'frac' value is given for the last note of the set we must accept error
  651. // values here and validate the actual values later
  652. if( frac>0 && frac!=DBL_MAX )
  653. s->frac = frac;
  654. }
  655. // Returns DBL_MAX on error.
  656. if((durSecs = cmCsvCellDouble(p->cH, rowIdx, kDSecsColScIdx )) == DBL_MAX)
  657. durSecs = 0.25;
  658. // parse the recd/play markers
  659. if((attr = cmCsvCellText(p->cH,rowIdx,kRecdPlayColScIdx)) != NULL )
  660. {
  661. if((rc = _cmScParseMarkers(p,scoreIdx,attr,rowIdx)) != kOkScRC )
  662. return rc;
  663. }
  664. s->type = kNonEvtScId;
  665. s->secs = secs;
  666. s->pitch = midiPitch;
  667. s->flags = flags;
  668. s->dynVal = dynVal;
  669. s->barNumb = barNumb;
  670. s->barNoteIdx = barNoteIdx;
  671. s->durSecs = durSecs;
  672. s->csvRowNumb = rowIdx+1;
  673. s->csvEventId = eventId;
  674. return rc;
  675. }
  676. cmScRC_t _cmScParseMidiCtlMsg( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned scoreIdx, int barNumb, unsigned barNoteIdx, cmScoreEvt_t** pedalV, unsigned pedalN )
  677. {
  678. cmScRC_t rc = kOkScRC;
  679. unsigned flags = 0;
  680. const cmChar_t* attr;
  681. double secs = DBL_MAX;
  682. double durSecs = 0;
  683. const unsigned pedalBaseMidiId = 64;
  684. s += scoreIdx;
  685. // get the sec's field - or DBL_MAX if it is not set
  686. if((secs = cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
  687. flags += kInvalidScFl;
  688. // skip attribute
  689. if((attr = cmCsvCellText(p->cH,rowIdx,kSkipColScIdx)) != NULL && *attr == 's' )
  690. flags += kSkipScFl;
  691. // get MIDI ctl msg data byte 1
  692. unsigned d0 = cmCsvCellUInt( p->cH,rowIdx,kD0ColScIdx);
  693. // get MIDI ctl msg data byte 2
  694. unsigned d1 = cmCsvCellUInt( p->cH,rowIdx,kD1ColScIdx);
  695. // if this is a pedal event
  696. if( pedalBaseMidiId <= d0 && d0 < pedalBaseMidiId + pedalN )
  697. {
  698. bool pedalDnFl = d1 >= 64;
  699. unsigned pedalIdx = d0 - pedalBaseMidiId;
  700. // if this is a pedal-down message ...
  701. if( pedalDnFl )
  702. {
  703. flags += kPedalDnScFl;
  704. if( pedalV[pedalIdx] != NULL )
  705. cmErrWarnMsg(&p->err,kPedalInvalidScRC,"The score contains multiple pedal down messages withouth an intervening pedal up message in or near bar %i.",barNumb );
  706. else
  707. {
  708. // Don't store a pointer to a skipped pedal down msg because it will not
  709. // not exist in p->array[] when the associated 'pedal-up' message is
  710. // encountered. Note the the 'postProcFl' controlled section of
  711. // _cmScParseFile() effectively eliminates cmScoreEvt_t records from
  712. // p->array[] that are marked with kSkipScFl.
  713. if( cmIsFlag(flags,kSkipScFl) )
  714. cmErrWarnMsg(&p->err,kPedalInvalidScRC,"A 'pedal-down' msg is marked to skip in or near bar %i this will probably produce a 'missing pedal-down' warning.",barNumb );
  715. else
  716. pedalV[pedalIdx] = s; // ... store a pointer to the scEvt recd in pedalV[]
  717. }
  718. }
  719. else // ... else this is a pedal-up msg ...
  720. {
  721. flags += kPedalUpScFl;
  722. if( pedalV[pedalIdx] == NULL )
  723. cmErrWarnMsg(&p->err,kPedalInvalidScRC,"The score contains multiple pedal up messages withouth an intervening pedal down message in or near bar %i.",barNumb );
  724. else // ... update the pedal down duration in the pedal-down message assoc'd w/ this pedal-up msg.
  725. {
  726. if( secs == DBL_MAX )
  727. cmErrWarnMsg(&p->err,kPedalInvalidScRC,"A pedal-up message was encountered with an invalid time-stamp in or near bar %i the pedal down duration could therefore not be calculated.",barNumb);
  728. else
  729. {
  730. // update the pedal down event record with the pedal down duration
  731. pedalV[pedalIdx]->durSecs = secs - pedalV[pedalIdx]->secs;
  732. }
  733. pedalV[pedalIdx] = NULL;
  734. }
  735. }
  736. }
  737. s->type = kPedalEvtScId;
  738. s->secs = secs;
  739. s->pitch = d0; // store the pedal type identifer in the pitch field
  740. s->flags = flags;
  741. s->dynVal = 0;
  742. s->barNumb = barNumb;
  743. s->barNoteIdx = barNoteIdx;
  744. s->durSecs = durSecs;
  745. s->csvRowNumb = rowIdx+1;
  746. return rc;
  747. }
  748. cmScRC_t _cmScParseSectionColumn( cmSc_t* p, unsigned rowIdx, unsigned evtIdx, cmScSect_t* sectList )
  749. {
  750. const cmCsvCell_t* cell;
  751. cmScSect_t* sect;
  752. const cmChar_t* label;
  753. // most rows don't have section labels
  754. if( (cell = cmCsvCellPtr( p->cH,rowIdx,kSectionColScIdx)) == NULL
  755. || (label = cmCsvCellText(p->cH,rowIdx,kSectionColScIdx)) == NULL)
  756. return kOkScRC;
  757. // verify the section id type
  758. if( cell->lexTId != p->sectionLexTId && cell->lexTId != kIntLexTId )
  759. return cmErrMsg(&p->err,kSyntaxErrScRC,"'section' column format error.");
  760. sect = cmMemAllocZ(cmScSect_t,1);
  761. sect->label = label;
  762. sect->startIdx = evtIdx;
  763. //printf("section:%s\n",label);
  764. cmScSect_t* sp = sectList;
  765. assert( sp != NULL );
  766. while( sp->link != NULL )
  767. sp = sp->link;
  768. sp->link = sect;
  769. return kOkScRC;
  770. }
  771. cmScoreSection_t* _cmScLabelToSection( cmSc_t* p, const cmChar_t* label )
  772. {
  773. int i;
  774. for(i=0; i<p->sectCnt; ++i)
  775. if( strcmp(p->sect[i].label,label) == 0 )
  776. return p->sect + i;
  777. return NULL;
  778. }
  779. // Calculate the total number of all types of sets and
  780. // then convert each of the cmScSet_t linked list's to
  781. // a single linear cmScoreSet_t list (p->sets[]).
  782. cmScRC_t _cmScProcSets( cmSc_t* p )
  783. {
  784. cmScRC_t rc = kOkScRC;
  785. // calculate the count of all sets
  786. unsigned i;
  787. unsigned n = 0;
  788. cmScSet_t* sp = p->setList;
  789. for(n=0; sp!=NULL; sp=sp->link)
  790. if( sp->eles != NULL )
  791. ++n;
  792. // allocate the linear set array
  793. p->sets = cmMemAllocZ(cmScoreSet_t,n);
  794. p->setCnt = n;
  795. // fill in the linear set array
  796. sp = p->setList;
  797. for(i=0; sp!=NULL; sp=sp->link)
  798. if( sp->eles != NULL )
  799. {
  800. unsigned j;
  801. unsigned en;
  802. unsigned rowNumb = 0;
  803. assert( i<n );
  804. // get the count of elements assoc'd with this set
  805. cmScSetEle_t* ep = sp->eles;
  806. for(en=0; ep!=NULL; ep=ep->link)
  807. ++en;
  808. assert( en > 0 );
  809. // allocate the element array
  810. p->sets[i].eleCnt = en;
  811. p->sets[i].eleArray = cmMemAllocZ(cmScoreEvt_t*,en);
  812. // fill in the element array
  813. ep = sp->eles;
  814. unsigned graceCnt = 0;
  815. for(j=0; ep!=NULL; ep=ep->link,++j)
  816. {
  817. assert(ep->eleIdx != cmInvalidIdx && ep->eleIdx<p->cnt);
  818. p->sets[i].eleArray[j] = p->array + ep->eleIdx;
  819. assert( cmIsFlag( p->sets[i].eleArray[j]->flags, sp->typeFl) );
  820. rowNumb = p->array[ep->eleIdx].csvRowNumb;
  821. unsigned flags = p->array[ep->eleIdx].flags;
  822. // count grace notes
  823. if( cmIsFlag(flags,kGraceScFl) )
  824. ++graceCnt;
  825. // validate the 'frac' field - all but the last note in
  826. // tempo and non-grace evenness sets must have a non-zero 'frac' value.
  827. if( en>0 && j<en-1 && (sp->typeFl==kTempoScFl || (sp->typeFl==kEvenScFl && graceCnt==0)) && p->array[ep->eleIdx].frac==0)
  828. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The note on row number %i must have a non-zero 'frac' value.",p->array[ep->eleIdx].csvRowNumb);
  829. }
  830. // get the count of sections assoc'd with this set
  831. ep = sp->sects;
  832. for(en=0; ep!=NULL; ep=ep->link)
  833. ++en;
  834. // allocate the section array
  835. p->sets[i].varId = _cmScVarFlagToId(sp->typeFl);
  836. p->sets[i].sectCnt = en;
  837. p->sets[i].sectArray = cmMemAllocZ(cmScoreSection_t*,en);
  838. p->sets[i].symArray = cmMemAllocZ(unsigned,en);
  839. p->sets[i].costSymArray = cmMemAllocZ(unsigned,en);
  840. // fill in the section array with sections which this set will be applied to
  841. ep = sp->sects;
  842. for(j=0; ep!=NULL; ep=ep->link,++j)
  843. {
  844. cmScoreSection_t* sp;
  845. assert(ep->label != NULL);
  846. if((sp = _cmScLabelToSection(p, ep->label )) == NULL )
  847. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The section labelled '%s' could not be found for the set which includes row number %i.",ep->label,rowNumb);
  848. else
  849. {
  850. if( cmSymTblIsValid(p->stH) )
  851. {
  852. // THIS PRINTF PREVENTS CRASH ON OSX ???????
  853. //printf("PROCSET:%i %c %s\n",p->sets[i].varId,_cmScVarIdToChar(p->sets[i].varId),ep->label);
  854. char cc = _cmScVarIdToChar(p->sets[i].varId);
  855. int nn = snprintf(NULL,0,"%c-%s",cc,ep->label);
  856. char b[nn+2];
  857. snprintf(b,nn,"%c-%s",cc,ep->label);
  858. p->sets[i].symArray[j] = cmSymTblRegisterSymbol(p->stH,b);
  859. snprintf(b,nn+1,"c%c-%s",cc,ep->label);
  860. p->sets[i].costSymArray[j] = cmSymTblRegisterSymbol(p->stH,b);
  861. //p->sets[i].symArray[j] = cmSymTblRegisterFmt(p->stH,"%c-%s", cc,ep->label);
  862. //p->sets[i].costSymArray[j] = cmSymTblRegisterFmt(p->stH,"c%c-%s",cc,ep->label);
  863. }
  864. else
  865. {
  866. p->sets[i].symArray[j] = cmInvalidId;
  867. p->sets[i].costSymArray[j] = cmInvalidId;
  868. }
  869. p->sets[i].sectArray[j] = sp;
  870. sp->setArray = cmMemResizeP(cmScoreSet_t*,sp->setArray,++sp->setCnt);
  871. sp->setArray[sp->setCnt-1] = p->sets + i;
  872. }
  873. }
  874. ++i;
  875. }
  876. assert(i==n);
  877. // assign each set to the location which contains it's last element.
  878. // (this is earliest point in the score location where all the
  879. // performance information contained in the set may be valid)
  880. for(i=0; i<p->setCnt; ++i)
  881. {
  882. assert( p->sets[i].eleCnt >= 1 );
  883. // get a ptr to the last element for the ith set
  884. const cmScoreEvt_t* ep = p->sets[i].eleArray[ p->sets[i].eleCnt-1 ];
  885. unsigned j,k;
  886. // find the location which contains the last element
  887. for(j=0; j<p->locCnt; ++j)
  888. {
  889. for(k=0; k<p->loc[j].evtCnt; ++k)
  890. if( p->loc[j].evtArray[k] == ep )
  891. break;
  892. if(k<p->loc[j].evtCnt)
  893. break;
  894. }
  895. assert( j<p->locCnt );
  896. // assign the ith set to the location which contains it's last element
  897. p->sets[i].llink = p->loc[j].setList;
  898. p->loc[j].setList = p->sets + i;
  899. }
  900. return rc;
  901. }
  902. cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
  903. {
  904. cmScRC_t rc = kOkScRC;
  905. unsigned i;
  906. // count the sections
  907. cmScSect_t* sp = sectList;
  908. p->sectCnt = 0;
  909. for(; sp!=NULL; sp=sp->link)
  910. if( sp->label != NULL )
  911. ++p->sectCnt;
  912. // alloc a section array
  913. p->sect = cmMemAllocZ(cmScoreSection_t,p->sectCnt);
  914. // fill the section array
  915. sp = sectList;
  916. for(i=0; sp!=NULL; sp=sp->link)
  917. if( sp->label != NULL )
  918. {
  919. p->sect[i].label = sp->label;
  920. p->sect[i].index = i;
  921. p->sect[i].begEvtIndex = sp->startIdx;
  922. ++i;
  923. }
  924. // assign the begSectPtr to each section
  925. for(i=0; i<p->sectCnt; ++i)
  926. {
  927. assert( p->sect[i].begEvtIndex < p->cnt );
  928. unsigned j,k;
  929. const cmScoreEvt_t* ep = p->array + p->sect[i].begEvtIndex;
  930. for(j=0; j<p->locCnt; ++j)
  931. {
  932. for(k=0; k<p->loc[j].evtCnt; ++k)
  933. if( p->loc[j].evtArray[k] == ep )
  934. {
  935. p->loc[j].begSectPtr = p->sect + i;
  936. p->sect[i].locPtr = p->loc + j;
  937. break;
  938. }
  939. if( k<p->loc[j].evtCnt)
  940. break;
  941. }
  942. }
  943. // release the section linked list
  944. sp = sectList;
  945. cmScSect_t* np = NULL;
  946. while(sp!=NULL)
  947. {
  948. np = sp->link;
  949. cmMemFree(sp);
  950. sp = np;
  951. }
  952. //_cmScPrintSets("Sets",p->setList );
  953. _cmScProcSets(p);
  954. return rc;
  955. }
  956. const cmScoreLoc_t* _cmScFindMarkLoc( cmSc_t* p, cmMarkScMId_t cmdId, unsigned labelSymId, const cmScoreMarker_t** markRef )
  957. {
  958. unsigned i;
  959. for(i=0; i<p->locCnt; ++i)
  960. {
  961. cmScoreMarker_t* smp = p->loc[i].markList;
  962. for(; smp!=NULL; smp=smp->link)
  963. {
  964. if( smp->markTypeId==cmdId && smp->labelSymId==labelSymId )
  965. return p->loc + i;
  966. if( markRef != NULL )
  967. *markRef = smp;
  968. }
  969. }
  970. return NULL;
  971. }
  972. unsigned _cmScMarkerLabelIndex( cmSc_t* p, unsigned labelSymId )
  973. {
  974. unsigned i;
  975. for(i=0; i<p->markLabelCnt; ++i)
  976. if( p->markLabelArray[i] == labelSymId )
  977. return i;
  978. return cmInvalidIdx;
  979. }
  980. // Verify that the record/play begin/end and fade markers fall in the correct time order.
  981. // (e.g. 'begin' must be before 'end' and 'fade' must be between and 'begin' and 'end').
  982. cmScRC_t _cmScValidateMarkers( cmSc_t* p )
  983. {
  984. cmScRC_t rc = kOkScRC;
  985. unsigned i;
  986. for(i=0; i<p->locCnt; ++i)
  987. {
  988. cmScoreMarker_t* sm0p = p->loc[i].markList;
  989. for(; sm0p!=NULL; sm0p=sm0p->link)
  990. {
  991. const cmScoreLoc_t* sl0p;
  992. const cmScoreLoc_t* sl1p;
  993. switch( sm0p->markTypeId )
  994. {
  995. case kRecdBegScMId:
  996. if((sl0p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
  997. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
  998. else
  999. if( sl0p->index <= p->loc[i].index )
  1000. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker comes before associated with the 'record begin' marker at CSV row index %i.",sm0p->csvRowIdx);
  1001. break;
  1002. case kRecdEndScMId:
  1003. if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
  1004. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
  1005. else
  1006. if( sl0p->index > p->loc[i].index )
  1007. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker comes after the associated with the 'record end' marker at CSV row index %i.",sm0p->csvRowIdx);
  1008. break;
  1009. case kFadeScMId:
  1010. if((sl0p = _cmScFindMarkLoc(p,kPlayBegScMId, sm0p->labelSymId, NULL )) == NULL )
  1011. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'play begin' marker.",sm0p->csvRowIdx);
  1012. else
  1013. if((sl1p = _cmScFindMarkLoc(p,kPlayEndScMId, sm0p->labelSymId, NULL )) == NULL )
  1014. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'play end' marker.",sm0p->csvRowIdx);
  1015. else
  1016. if( sl0p->index > p->loc[i].index || sl1p->index < p->loc[i].index )
  1017. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i is not between it's associated 'play begin' and 'play end' markers.",sm0p->csvRowIdx);
  1018. break;
  1019. case kPlayBegScMId:
  1020. if((sl0p = _cmScFindMarkLoc(p,kPlayEndScMId, sm0p->labelSymId, NULL )) == NULL )
  1021. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker at CSV row index %i does not have an associated 'play end' marker.",sm0p->csvRowIdx);
  1022. else
  1023. if( sl0p->index <= p->loc[i].index )
  1024. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker comes before associated with the 'play begin' marker at CSV row index %i.",sm0p->csvRowIdx);
  1025. break;
  1026. case kPlayEndScMId:
  1027. if((sl0p = _cmScFindMarkLoc(p,kPlayBegScMId, sm0p->labelSymId, NULL )) == NULL )
  1028. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker at CSV row index %i does not have an associated 'play begin' marker.",sm0p->csvRowIdx);
  1029. else
  1030. if( sl0p->index > p->loc[i].index )
  1031. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker comes after the associated with the 'play end' marker at CSV row index %i.",sm0p->csvRowIdx);
  1032. break;
  1033. default:
  1034. break;
  1035. }
  1036. }
  1037. }
  1038. return rc;
  1039. }
  1040. cmScRC_t _cmScProcMarkers( cmSc_t* p )
  1041. {
  1042. // for each marker in the p->markList
  1043. // (p->markList is created by _cmScParseMarkers() during CSV file parsing.)
  1044. cmScMark_t* mp = p->markList;
  1045. for(; mp!=NULL; mp=mp->link)
  1046. {
  1047. assert( mp->scoreIdx < p->cnt );
  1048. // get the score location assoc'd with this marker
  1049. unsigned locIdx = p->array[ mp->scoreIdx ].locIdx;
  1050. assert( locIdx < p->locCnt );
  1051. cmScoreLoc_t* slp = p->loc + locIdx;
  1052. // create a cmScoreMarker record.
  1053. cmScoreMarker_t* smp = cmMemAllocZ(cmScoreMarker_t,1);
  1054. smp->markTypeId = mp->cmdId;
  1055. smp->labelSymId = mp->labelSymId;
  1056. smp->csvRowIdx = mp->csvRowIdx;
  1057. smp->scoreLocPtr = slp;
  1058. // attach the new scoreMarker record to the assoc'd score loc. recd
  1059. if( slp->markList == NULL )
  1060. slp->markList = smp;
  1061. else
  1062. {
  1063. cmScoreMarker_t* sm0p = slp->markList;
  1064. while( sm0p->link != NULL )
  1065. sm0p = sm0p->link;
  1066. sm0p->link = smp;
  1067. }
  1068. // if the id represented by this marker
  1069. if( _cmScMarkerLabelIndex(p,smp->labelSymId) == cmInvalidIdx )
  1070. {
  1071. p->markLabelArray = cmMemResizeP(unsigned,p->markLabelArray,p->markLabelCnt+1);
  1072. p->markLabelArray[p->markLabelCnt] = smp->labelSymId;
  1073. p->markLabelCnt += 1;
  1074. }
  1075. }
  1076. // validate the markers
  1077. return _cmScValidateMarkers(p);
  1078. }
  1079. cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
  1080. {
  1081. cmScRC_t rc = kOkScRC;
  1082. unsigned barNoteIdx = 0;
  1083. int barEvtIdx = cmInvalidIdx;
  1084. int barNumb = 0;
  1085. double secs;
  1086. double cur_secs = 0;
  1087. const unsigned pedalN = 3;
  1088. cmScoreEvt_t* pedalV[] = { NULL,NULL,NULL };
  1089. p->sectList = cmMemAllocZ(cmScSect_t,1); // section zero
  1090. //_cmScNewSet(p); // preallocate the first set
  1091. // initialize the CSV file parser
  1092. if( cmCsvInitialize(&p->cH, ctx ) != kOkCsvRC )
  1093. {
  1094. rc = cmErrMsg(&p->err,kCsvFailScRC,"Score file initialization failed.");
  1095. goto errLabel;
  1096. }
  1097. // register custom lex token matchers for sci-pitch and section id's
  1098. if( cmCsvLexRegisterMatcher(p->cH, p->sciPitchLexTId = cmCsvLexNextAvailId(p->cH)+0, _cmScLexSciPitchMatcher ) != kOkCsvRC
  1099. ||cmCsvLexRegisterMatcher(p->cH, p->sectionLexTId = cmCsvLexNextAvailId(p->cH)+1, _cmScLexSectionIdMatcher) != kOkCsvRC )
  1100. {
  1101. rc = cmErrMsg(&p->err,kCsvFailScRC,"CSV token matcher registration failed.");
  1102. goto errLabel;
  1103. }
  1104. // parse the CSV file
  1105. if( cmCsvParseFile(p->cH, fn, 0 ) != kOkCsvRC )
  1106. {
  1107. rc = cmErrMsg(&p->err,kCsvFailScRC,"CSV file parsing failed on the file '%s'.",cmStringNullGuard(fn));
  1108. goto errLabel;
  1109. }
  1110. // allocate the score event array
  1111. p->cnt = cmCsvRowCount(p->cH);
  1112. p->array = cmMemAllocZ(cmScoreEvt_t,p->cnt);
  1113. unsigned i,j;
  1114. // skip labels line - start on line 1
  1115. for(i=1,j=0; i<p->cnt && rc==kOkScRC; ++i)
  1116. {
  1117. bool postProcFl = false;
  1118. // get the row 'type' label
  1119. const char* typeLabel;
  1120. if((typeLabel = cmCsvCellText(p->cH,i,kTypeLabelColScIdx)) == NULL )
  1121. {
  1122. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"No type label.");
  1123. break;
  1124. }
  1125. // convert the row 'type' label to an id
  1126. unsigned tid;
  1127. if((tid = _cmScEvtTypeLabelToId(typeLabel)) == kInvalidEvtScId)
  1128. {
  1129. rc = cmErrMsg(&p->err,kSyntaxErrScRC,"Unknown type '%s'.",cmStringNullGuard(typeLabel));
  1130. break;
  1131. }
  1132. // set the score file line number
  1133. p->array[j].line = i + 1;
  1134. secs = DBL_MAX;
  1135. switch(tid)
  1136. {
  1137. case kBarEvtScId: // parse bar lines
  1138. if((rc = _cmScParseBar(p,i,p->array+j,&barNumb)) == kOkScRC )
  1139. {
  1140. barNoteIdx = 0;
  1141. barEvtIdx = j;
  1142. p->array[j].index = j;
  1143. ++j;
  1144. }
  1145. break;
  1146. case kNonEvtScId: // parse note-on events
  1147. if((rc = _cmScParseNoteOn(p, i, p->array, j, barNumb, barNoteIdx )) == kOkScRC )
  1148. {
  1149. postProcFl = true;
  1150. ++barNoteIdx;
  1151. }
  1152. break;
  1153. case kCtlEvtScId:
  1154. if((rc = _cmScParseMidiCtlMsg(p, i, p->array, j, barNumb, barNoteIdx, pedalV, pedalN )) == kOkScRC )
  1155. {
  1156. postProcFl = true;
  1157. }
  1158. break;
  1159. default:
  1160. // Returns DBL_MAX on error.
  1161. secs = cmCsvCellDouble(p->cH, i, kSecsColScIdx );
  1162. break;
  1163. }
  1164. if( postProcFl )
  1165. {
  1166. // update the 'secs' according to the parsed time
  1167. secs = p->array[j].secs;
  1168. // it is possible that the parsed time field was blank ...
  1169. if( p->array[j].secs == DBL_MAX )
  1170. {
  1171. // ... so set the msg time to the last valid time
  1172. p->array[j].secs = cur_secs;
  1173. // note that 'secs' is now set to DBL_MAX so cur_secs will
  1174. // not be updated on this row iteration
  1175. }
  1176. // if this msg was marked to skip then don't advance j (and thereby
  1177. // write over this scEvt with the next note). ...
  1178. if( cmIsFlag(p->array[j].flags,kSkipScFl) == false )
  1179. {
  1180. p->array[j].index = j; // ... otherwise advance j
  1181. ++j;
  1182. }
  1183. }
  1184. if( rc == kOkScRC )
  1185. {
  1186. // if sec's is valid then update cur_secs
  1187. if( secs != DBL_MAX )
  1188. cur_secs = secs;
  1189. // form the section list
  1190. if( j > 0 )
  1191. if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
  1192. break;
  1193. // the bar lines don't have times so set the time of the bar line to the
  1194. // time of the first event in the bar.
  1195. if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
  1196. {
  1197. assert( p->array[ barEvtIdx ].type == kBarEvtScId );
  1198. p->array[ barEvtIdx ].secs = secs;
  1199. // handle the case where the previous bar had no events
  1200. // BUG BUG BUG this is a hack which will fail if the first bar does not have events.
  1201. if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId )
  1202. p->array[ barEvtIdx-1].secs = secs;
  1203. barEvtIdx = cmInvalidIdx;
  1204. }
  1205. }
  1206. }
  1207. if( rc == kSyntaxErrScRC )
  1208. {
  1209. cmErrMsg(&p->err,rc,"Syntax error on line %i in '%s'.",i+1,cmStringNullGuard(fn));
  1210. goto errLabel;
  1211. }
  1212. p->cnt = j;
  1213. errLabel:
  1214. return rc;
  1215. }
  1216. cmScRC_t _cmScInitLocArray( cmSc_t* p )
  1217. {
  1218. cmScRC_t rc = kOkScRC;
  1219. double maxDSecs = 0; // max time between events that are considered simultaneous
  1220. unsigned barNumb = 0;
  1221. int i,j,k;
  1222. if( p->cnt==0)
  1223. return rc;
  1224. p->locCnt = 1;
  1225. // count the number of unique time locations in the score
  1226. p->locCnt = 1;
  1227. for(i=1; i<p->cnt; ++i )
  1228. {
  1229. if( p->array[i].secs < p->array[i-1].secs )
  1230. 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);
  1231. if( (p->array[i].secs - p->array[i-1].secs) > maxDSecs )
  1232. ++p->locCnt;
  1233. }
  1234. if( rc != kOkScRC )
  1235. return rc;
  1236. // allocate the loc. array
  1237. p->loc = cmMemAllocZ(cmScoreLoc_t,p->locCnt);
  1238. // fill in the location array
  1239. for(i=0,k=0; i<p->cnt; ++k)
  1240. {
  1241. j = i+1;
  1242. // get the count of events at this location
  1243. while( j<p->cnt && p->array[j].secs - p->array[j-1].secs <= maxDSecs )
  1244. ++j;
  1245. assert(k<p->locCnt);
  1246. p->loc[k].index = k;
  1247. p->loc[k].evtCnt = j-i;
  1248. p->loc[k].evtArray = cmMemAllocZ(cmScoreEvt_t*,p->loc[k].evtCnt);
  1249. // fill in the location record event pointers
  1250. for(j=0; j<p->loc[k].evtCnt; ++j)
  1251. {
  1252. p->loc[k].evtArray[j] = p->array + (i + j);
  1253. p->loc[k].evtArray[j]->locIdx = k;
  1254. if( p->array[i+j].type == kBarEvtScId )
  1255. barNumb = p->array[i+j].barNumb;
  1256. }
  1257. // fill in the location record
  1258. p->loc[k].secs = p->array[i].secs;
  1259. p->loc[k].barNumb = barNumb;
  1260. i += p->loc[k].evtCnt;
  1261. }
  1262. assert( p->locCnt == k );
  1263. return rc;
  1264. }
  1265. cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, double srate, const unsigned* dynRefArray, unsigned dynRefCnt, cmScCb_t cbFunc, void* cbArg, cmSymTblH_t stH )
  1266. {
  1267. cmScRC_t rc = kOkScRC;
  1268. if((rc = cmScoreFinalize(hp)) != kOkScRC )
  1269. return rc;
  1270. cmSc_t* p = cmMemAllocZ(cmSc_t,1);
  1271. cmErrSetup(&p->err,&ctx->rpt,"Score");
  1272. p->stH = stH;
  1273. if((rc = _cmScParseFile(p,ctx,fn)) != kOkScRC )
  1274. goto errLabel;
  1275. if((rc = _cmScInitLocArray(p)) != kOkScRC )
  1276. goto errLabel;
  1277. if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
  1278. goto errLabel;
  1279. if((rc = _cmScProcMarkers(p)) != kOkScRC )
  1280. goto errLabel;
  1281. // load the dynamic reference array
  1282. if( dynRefArray != NULL && dynRefCnt > 0)
  1283. {
  1284. unsigned n = _cmScDynLabelCount();
  1285. if( dynRefCnt != n )
  1286. {
  1287. rc = cmErrMsg(&p->err,kInvalidDynRefCntScRC,"The count of dynamics labels must be %i not %i.",n,dynRefCnt);
  1288. goto errLabel;
  1289. }
  1290. p->dynRefArray = cmMemAllocZ(unsigned,dynRefCnt);
  1291. memcpy(p->dynRefArray,dynRefArray,sizeof(unsigned)*dynRefCnt);
  1292. p->dynRefCnt = dynRefCnt;
  1293. }
  1294. p->srate = srate;
  1295. p->cbFunc = cbFunc;
  1296. p->cbArg = cbArg;
  1297. p->fn = cmMemAllocStr(fn);
  1298. p->nxtLocIdx = 0;
  1299. p->minSetLocIdx = cmInvalidIdx;
  1300. p->maxSetLocIdx = cmInvalidIdx;
  1301. hp->h = p;
  1302. cmScoreClearPerfInfo(*hp);
  1303. //cmScorePrintLoc(*hp);
  1304. errLabel:
  1305. if( rc != kOkScRC )
  1306. _cmScFinalize(p);
  1307. return rc;
  1308. }
  1309. cmScRC_t cmScoreFinalize( cmScH_t* hp )
  1310. {
  1311. cmScRC_t rc = kOkScRC;
  1312. if( hp == NULL || cmScoreIsValid(*hp) == false )
  1313. return kOkScRC;
  1314. cmSc_t* p = _cmScHandleToPtr(*hp);
  1315. if((rc = _cmScFinalize(p)) != kOkScRC )
  1316. return rc;
  1317. hp->h = NULL;
  1318. return rc;
  1319. }
  1320. const cmChar_t* cmScoreFileName( cmScH_t h )
  1321. {
  1322. cmSc_t* p = _cmScHandleToPtr(h);
  1323. return p->fn;
  1324. }
  1325. double cmScoreSampleRate( cmScH_t h )
  1326. {
  1327. cmSc_t* p = _cmScHandleToPtr(h);
  1328. return p->srate;
  1329. }
  1330. bool cmScoreIsValid( cmScH_t h )
  1331. { return h.h != NULL; }
  1332. unsigned cmScoreEvtCount( cmScH_t h )
  1333. {
  1334. cmSc_t* p = _cmScHandleToPtr(h);
  1335. return p->cnt;
  1336. }
  1337. cmScoreEvt_t* cmScoreEvt( cmScH_t h, unsigned idx )
  1338. {
  1339. cmSc_t* p = _cmScHandleToPtr(h);
  1340. if( idx >= p->cnt )
  1341. {
  1342. cmErrMsg(&p->err,kInvalidIdxScRC,"%i is an invalid index for %i records.",idx,p->cnt);
  1343. return NULL;
  1344. }
  1345. return p->array + idx;
  1346. }
  1347. cmScoreEvt_t* cmScoreBarEvt( cmScH_t h, unsigned barNumb )
  1348. {
  1349. cmSc_t* p = _cmScHandleToPtr(h);
  1350. unsigned i = 0;
  1351. for(; i<p->cnt; ++i)
  1352. if( p->array[i].type==kBarEvtScId && p->array[i].barNumb==barNumb )
  1353. return p->array + i;
  1354. return NULL;
  1355. }
  1356. unsigned cmScoreSectionCount( cmScH_t h )
  1357. {
  1358. cmSc_t* p = _cmScHandleToPtr(h);
  1359. return p->sectCnt;
  1360. }
  1361. cmScoreSection_t* cmScoreSection( cmScH_t h, unsigned idx )
  1362. {
  1363. cmSc_t* p = _cmScHandleToPtr(h);
  1364. assert( idx < p->sectCnt);
  1365. return p->sect + idx;
  1366. }
  1367. unsigned cmScoreLocCount( cmScH_t h )
  1368. {
  1369. cmSc_t* p = _cmScHandleToPtr(h);
  1370. return p->locCnt;
  1371. }
  1372. cmScoreLoc_t* cmScoreLoc( cmScH_t h, unsigned idx )
  1373. {
  1374. cmSc_t* p = _cmScHandleToPtr(h);
  1375. if( idx >= p->locCnt )
  1376. {
  1377. cmErrMsg(&p->err,kInvalidIdxScRC,"%i is an invalid index for %i location records.",idx,p->locCnt);
  1378. return NULL;
  1379. }
  1380. return p->loc + idx;
  1381. }
  1382. cmScoreLoc_t* cmScoreEvtLoc( cmScH_t h, const cmScoreEvt_t* evt )
  1383. {
  1384. cmSc_t* p = _cmScHandleToPtr(h);
  1385. unsigned i;
  1386. if( evt != NULL )
  1387. for(i=0; i<p->locCnt; ++i)
  1388. {
  1389. unsigned j;
  1390. for(j=0; j<p->loc[i].evtCnt; ++j)
  1391. if( p->loc[i].evtArray[j] == evt )
  1392. return p->loc + i;
  1393. }
  1394. return NULL;
  1395. }
  1396. void cmScorePrintLoc( cmScH_t h )
  1397. {
  1398. unsigned i = 0;
  1399. cmSc_t* p = _cmScHandleToPtr(h);
  1400. unsigned colCnt = 10;
  1401. int bufCharCnt = 4;
  1402. char buf[ bufCharCnt ];
  1403. const char* emptyStr = " ";
  1404. // for each set of 'colCnt' columns
  1405. for(i=0; i<p->locCnt; i+=colCnt )
  1406. {
  1407. // print the location 'index' line
  1408. unsigned c,j,k;
  1409. printf("index: ");
  1410. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1411. printf("%7i ",j);
  1412. printf("\n");
  1413. // print the 'sectn' label line
  1414. printf("sectn: ");
  1415. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1416. if( p->loc[j].begSectPtr==NULL )
  1417. printf("%s",emptyStr);
  1418. else
  1419. printf("%7s ",p->loc[j].begSectPtr->label);
  1420. printf("\n");
  1421. // calculate the max number of simultan. events at any one location
  1422. // for this set of 'colCnt' columns.
  1423. unsigned n=0;
  1424. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1425. if( p->loc[j].evtCnt > n )
  1426. n = p->loc[j].evtCnt;
  1427. // for each 'sco' line
  1428. for(k=0; k<n; ++k)
  1429. {
  1430. printf("sco%2i: ",k);
  1431. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1432. if( k >= p->loc[j].evtCnt )
  1433. printf("%s",emptyStr);
  1434. else
  1435. {
  1436. switch(p->loc[j].evtArray[k]->type)
  1437. {
  1438. case kBarEvtScId:
  1439. printf(" |%3i ",p->loc[j].evtArray[k]->barNumb);
  1440. break;
  1441. case kNonEvtScId:
  1442. {
  1443. int bn=16;
  1444. char b[bn];
  1445. strcpy(b,cmMidiToSciPitch(p->loc[j].evtArray[k]->pitch,NULL,0));
  1446. strcat(b,_cmScFlagsToStr( p->loc[j].evtArray[k]->flags,buf,bufCharCnt));
  1447. assert(strlen(b)<bn);
  1448. printf("%7s ",b);
  1449. break;
  1450. }
  1451. }
  1452. }
  1453. printf("\n");
  1454. }
  1455. // calc the max number of set triggers which will occur on
  1456. // any one location for this set of 'colCnt' columns.
  1457. n=0;
  1458. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1459. if(p->loc[j].begSectPtr != NULL && p->loc[j].begSectPtr->setCnt > n )
  1460. n = p->loc[j].begSectPtr->setCnt;
  1461. for(k=0; k<n; ++k)
  1462. {
  1463. printf("trig%1i: ",k);
  1464. for(c=0,j=i; j<p->locCnt && c<colCnt; ++c,++j)
  1465. {
  1466. if( p->loc[j].begSectPtr != NULL && k<p->loc[j].begSectPtr->setCnt )
  1467. {
  1468. const cmScoreSet_t* sp = p->loc[j].begSectPtr->setArray[k];
  1469. printf(" %3s-%c ",p->loc[j].begSectPtr->label,_cmScVarIdToChar(sp->varId) );
  1470. }
  1471. else
  1472. {
  1473. printf("%s",emptyStr);
  1474. }
  1475. }
  1476. printf("\n");
  1477. }
  1478. printf("\n");
  1479. }
  1480. }
  1481. unsigned cmScoreSetCount( cmScH_t h )
  1482. {
  1483. cmSc_t* p = _cmScHandleToPtr(h);
  1484. return p->setCnt;
  1485. }
  1486. unsigned cmScoreMarkerLabelCount( cmScH_t h )
  1487. {
  1488. cmSc_t* p = _cmScHandleToPtr(h);
  1489. return p->markLabelCnt;
  1490. }
  1491. unsigned cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx )
  1492. {
  1493. cmSc_t* p = _cmScHandleToPtr(h);
  1494. assert( idx < p->markLabelCnt );
  1495. return p->markLabelArray[idx];
  1496. }
  1497. const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId )
  1498. {
  1499. cmSc_t* p = _cmScHandleToPtr(h);
  1500. const cmScoreMarker_t* smp = NULL;
  1501. if( _cmScFindMarkLoc(p, markMId, labelSymId, &smp ) == NULL )
  1502. return NULL;
  1503. return smp;
  1504. }
  1505. cmScRC_t cmScoreSeqNotify( cmScH_t h )
  1506. {
  1507. cmScRC_t rc = kOkScRC;
  1508. cmSc_t* p = _cmScHandleToPtr(h);
  1509. cmScMsg_t m;
  1510. unsigned i;
  1511. if( p->cbFunc != NULL )
  1512. {
  1513. memset(&m.u.evt,0,sizeof(m.u.evt));
  1514. m.typeId = kBeginMsgScId;
  1515. p->cbFunc(p->cbArg,&m,sizeof(m));
  1516. m.typeId = kEventMsgScId;
  1517. for(i=0; i<p->cnt; ++i)
  1518. {
  1519. m.u.evt = p->array[i];
  1520. p->cbFunc(p->cbArg,&m,sizeof(m));
  1521. }
  1522. m.typeId = kSectionMsgScId;
  1523. for(i=0; i<p->sectCnt; ++i)
  1524. {
  1525. m.u.sect = p->sect[i];
  1526. p->cbFunc(p->cbArg,&m,sizeof(m));
  1527. }
  1528. memset(&m.u.evt,0,sizeof(m.u.evt));
  1529. m.typeId = kEndMsgScId;
  1530. p->cbFunc(p->cbArg,&m,sizeof(m));
  1531. }
  1532. return rc;
  1533. }
  1534. cmScRC_t cmScoreSeqNotifyCb( cmScH_t h, cmScCb_t cbFunc, void* cbArg )
  1535. {
  1536. cmSc_t* p = _cmScHandleToPtr(h);
  1537. cmScRC_t rc = kOkScRC;
  1538. cmScCb_t cbf = p->cbFunc;
  1539. void* cba = p->cbArg;
  1540. p->cbFunc = cbFunc;
  1541. p->cbArg = cbArg;
  1542. rc = cmScoreSeqNotify(h);
  1543. p->cbFunc = cbf;
  1544. p->cbArg = cba;
  1545. return rc;
  1546. }
  1547. void cmScoreClearPerfInfo( cmScH_t h )
  1548. {
  1549. cmSc_t* p = _cmScHandleToPtr(h);
  1550. unsigned i;
  1551. for(i=0; i<p->cnt; ++i)
  1552. {
  1553. p->array[i].perfSmpIdx = cmInvalidIdx;
  1554. p->array[i].perfVel = 0;
  1555. p->array[i].perfDynLvl = 0;
  1556. }
  1557. for(i=0; i<p->locCnt; ++i)
  1558. {
  1559. cmScoreSet_t* sp = p->loc[i].setList;
  1560. for(; sp!=NULL; sp=sp->llink)
  1561. sp->doneFl = false;
  1562. }
  1563. for(i=0; i<p->sectCnt; ++i)
  1564. {
  1565. unsigned j;
  1566. for(j=0; j<kScVarCnt; ++j)
  1567. p->sect[i].vars[j] = DBL_MAX;
  1568. }
  1569. p->nxtLocIdx = 0;
  1570. p->minSetLocIdx = cmInvalidIdx;
  1571. p->maxSetLocIdx = cmInvalidIdx;
  1572. }
  1573. bool _cmScIsSetPerfDone( cmScoreSet_t* sp )
  1574. {
  1575. unsigned i = 0;
  1576. for(i=0; i<sp->eleCnt; ++i)
  1577. if( sp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1578. return false;
  1579. return true;
  1580. }
  1581. void _cmScPerfSortTimes( unsigned *v, unsigned n )
  1582. {
  1583. unsigned i;
  1584. bool fl = true;
  1585. while(fl && n)
  1586. {
  1587. fl = false;
  1588. for(i=1; i<n; ++i)
  1589. {
  1590. if( v[i-1] > v[i] )
  1591. {
  1592. unsigned t = v[i-1];
  1593. v[i-1] = v[i];
  1594. v[i] = t;
  1595. fl = true;
  1596. }
  1597. }
  1598. --n;
  1599. }
  1600. }
  1601. bool _cmScPerfEven(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1602. {
  1603. unsigned i = 0;
  1604. double u = 0;
  1605. double x = 0;
  1606. bool sortFl = false;
  1607. bool printFl = true;
  1608. unsigned v[ stp->eleCnt ];
  1609. unsigned d[ stp->eleCnt - 1];
  1610. assert( stp->eleCnt > 1 );
  1611. // calculate the sum of the time between events
  1612. for(i=0; i<stp->eleCnt; ++i)
  1613. {
  1614. // if this event was not received - then the set is not valid
  1615. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1616. {
  1617. if( printFl && printMissFl)
  1618. printf("EVENESS: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1619. return false;
  1620. }
  1621. // load v[i]
  1622. v[i] = stp->eleArray[i]->perfSmpIdx;
  1623. // check for out of order elements
  1624. if( i> 0 )
  1625. if( v[i] < v[i-1] )
  1626. sortFl = true;
  1627. }
  1628. // sort the times in ascending order
  1629. if( sortFl )
  1630. _cmScPerfSortTimes(v,stp->eleCnt);
  1631. // calc the sum of time differences
  1632. for(i=1; i<stp->eleCnt; ++i)
  1633. u += d[i-1] = v[i] - v[i-1];
  1634. // calculate the average time between events
  1635. u /= stp->eleCnt-1;
  1636. // calculate the std-dev of the time between events
  1637. for(i=0; i<stp->eleCnt-1; ++i)
  1638. x += (d[i]-u)*(d[i]-u);
  1639. double sd = sqrt(x/(stp->eleCnt-1));
  1640. // compute the average z-score
  1641. double c = 0;
  1642. for(i=0; i<stp->eleCnt-1; ++i)
  1643. c += fabs(d[i]-u)/sd;
  1644. stp->value = c/(stp->eleCnt-1);
  1645. stp->doneFl = true;
  1646. if(printFl)
  1647. {
  1648. /*
  1649. for(i=0; i<stp->eleCnt; ++i)
  1650. {
  1651. printf("%i %i ",i,v[i]);
  1652. if( i > 0 )
  1653. printf("%i ", d[i-1]);
  1654. printf("\n");
  1655. }
  1656. */
  1657. printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
  1658. }
  1659. return true;
  1660. }
  1661. bool _cmScPerfDyn( cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1662. {
  1663. double a = 0;
  1664. unsigned i = 0;
  1665. bool printFl = true;
  1666. for(i=0; i<stp->eleCnt; ++i)
  1667. {
  1668. unsigned j;
  1669. // if this event was not received - then the set is not valid
  1670. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1671. {
  1672. if( printFl && printMissFl )
  1673. printf("DYNAMICS: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1674. return false;
  1675. }
  1676. unsigned m = 0; // lower bound for the first dyn. category
  1677. // determine the dynamic category for the performed velocity of each event
  1678. for(j=0; j<p->dynRefCnt; ++j)
  1679. {
  1680. // if the vel fall's into the jth dyn. category
  1681. if( m <= stp->eleArray[i]->perfVel && stp->eleArray[i]->perfVel < p->dynRefArray[j] )
  1682. break;
  1683. // store the min vel for the next dyn category
  1684. m = p->dynRefArray[j];
  1685. }
  1686. assert( j < p->dynRefCnt );
  1687. stp->eleArray[i]->perfDynLvl = j+1;
  1688. a += abs((j+1) - stp->eleArray[i]->dynVal);
  1689. if( p->cbFunc != NULL )
  1690. {
  1691. cmScMsg_t m;
  1692. m.typeId = kDynMsgScId;
  1693. m.u.dyn.evtIdx = stp->eleArray[i]->index;
  1694. m.u.dyn.dynLvl = stp->eleArray[i]->perfDynLvl;
  1695. p->cbFunc(p->cbArg,&m,sizeof(m));
  1696. }
  1697. }
  1698. stp->value = a / stp->eleCnt;
  1699. stp->doneFl = true;
  1700. if( printFl )
  1701. printf("DYNAMICS:%f\n",stp->value);
  1702. return true;
  1703. }
  1704. bool _cmScPerfTempo1(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1705. {
  1706. bool printFl = true;
  1707. unsigned durSmpCnt = 0;
  1708. double durBeats = 0;
  1709. int i;
  1710. for(i=0; i<stp->eleCnt; ++i)
  1711. {
  1712. // if this event was not received - then the set is not valid
  1713. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1714. {
  1715. if( printFl && printMissFl )
  1716. printf("TEMPO: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1717. return false;
  1718. }
  1719. if( i > 0 )
  1720. durSmpCnt += stp->eleArray[i]->perfSmpIdx - stp->eleArray[i-1]->perfSmpIdx;
  1721. durBeats += stp->eleArray[i]->frac;
  1722. }
  1723. stp->value = durBeats / (durSmpCnt / p->srate*60.0 );
  1724. stp->doneFl = true;
  1725. if( printFl )
  1726. printf("TEMPO:%f\n",stp->value);
  1727. return true;
  1728. }
  1729. bool _cmScPerfTempo(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
  1730. {
  1731. bool printFl = true;
  1732. unsigned durSmpCnt = 0;
  1733. double durBeats = 0;
  1734. int i;
  1735. unsigned bi = cmInvalidIdx;
  1736. unsigned ei = cmInvalidIdx;
  1737. unsigned missCnt = 0;
  1738. for(i=0; i<stp->eleCnt; ++i)
  1739. {
  1740. // if this event was not received - then the set is not valid
  1741. if( stp->eleArray[i]->perfSmpIdx == cmInvalidIdx )
  1742. {
  1743. ++missCnt;
  1744. if( printFl && printMissFl )
  1745. printf("TEMPO: missing loc:%i %s\n",stp->eleArray[i]->locIdx,cmMidiToSciPitch(stp->eleArray[i]->pitch,NULL,0));
  1746. }
  1747. else
  1748. {
  1749. if( bi == cmInvalidIdx )
  1750. bi = i;
  1751. ei = i;
  1752. }
  1753. }
  1754. if( ei > bi )
  1755. {
  1756. for(i=bi; i<=ei; ++i)
  1757. durBeats += stp->eleArray[i]->frac;
  1758. durSmpCnt = stp->eleArray[ei]->perfSmpIdx - stp->eleArray[bi]->perfSmpIdx;
  1759. stp->value = durBeats / (durSmpCnt / (p->srate*60.0) );
  1760. stp->doneFl = true;
  1761. }
  1762. if( printFl )
  1763. printf("TEMPO:%f bi:%i ei:%i secs:%f bts:%f\n",stp->value,bi,ei,durSmpCnt/p->srate,durBeats);
  1764. return true;
  1765. }
  1766. void _cmScPerfExec( cmSc_t* p, cmScoreSet_t* sp, bool printMissFl )
  1767. {
  1768. if( sp->doneFl == false )
  1769. {
  1770. switch( sp->varId )
  1771. {
  1772. case kEvenVarScId:
  1773. _cmScPerfEven(p,sp,printMissFl);
  1774. break;
  1775. case kDynVarScId:
  1776. _cmScPerfDyn(p,sp,printMissFl);
  1777. break;
  1778. case kTempoVarScId:
  1779. _cmScPerfTempo(p,sp,printMissFl);
  1780. break;
  1781. default:
  1782. { assert(0); }
  1783. }
  1784. }
  1785. }
  1786. void _cmScPerfExecRange( cmSc_t* p )
  1787. {
  1788. if( p->minSetLocIdx == cmInvalidIdx || p->maxSetLocIdx==cmInvalidIdx )
  1789. return;
  1790. unsigned i = p->minSetLocIdx;
  1791. for(; i<=p->maxSetLocIdx; ++i)
  1792. {
  1793. cmScoreSet_t* sp = p->loc[i].setList;
  1794. for(; sp!=NULL; sp=sp->llink)
  1795. _cmScPerfExec(p,sp,true);
  1796. }
  1797. }
  1798. bool _cmScSetPerfEvent( cmSc_t* p, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1799. {
  1800. assert(locIdx < p->locCnt );
  1801. cmScoreLoc_t* lp = p->loc + locIdx;
  1802. bool doneFl = true;
  1803. unsigned i;
  1804. #ifndef NDEBUG
  1805. bool foundFl = false;
  1806. #endif
  1807. // locate the event at the loc[locIdx]
  1808. for(i=0; i<lp->evtCnt; ++i)
  1809. {
  1810. cmScoreEvt_t* ep = lp->evtArray[i];
  1811. if( ep->type == kNonEvtScId )
  1812. {
  1813. if( ep->pitch == pitch )
  1814. {
  1815. assert( ep->perfSmpIdx == cmInvalidIdx );
  1816. ep->perfSmpIdx = smpIdx;
  1817. ep->perfVel = vel;
  1818. #ifndef NDEBUG
  1819. foundFl = true;
  1820. #endif
  1821. }
  1822. // check if all notes have arrived for this location
  1823. if( ep->perfSmpIdx == cmInvalidIdx )
  1824. doneFl = false;
  1825. }
  1826. }
  1827. // the event must always be found
  1828. assert( foundFl );
  1829. return doneFl;
  1830. }
  1831. bool cmScoreSetPerfEvent( cmScH_t h, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1832. {
  1833. cmSc_t* p = _cmScHandleToPtr(h);
  1834. return _cmScSetPerfEvent(p,locIdx,smpIdx,pitch,vel);
  1835. }
  1836. void cmScoreExecPerfEvent( cmScH_t h, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel )
  1837. {
  1838. unsigned i;
  1839. cmSc_t* p = _cmScHandleToPtr(h);
  1840. bool doneFl = _cmScSetPerfEvent(p,locIdx,smpIdx,pitch,vel);
  1841. unsigned printLvl = 1;
  1842. cmScoreLoc_t* lp = p->loc + locIdx;
  1843. // all events for a location must be complete to trigger attached events
  1844. if( doneFl == false )
  1845. return;
  1846. if( p->loc[locIdx].setList != NULL )
  1847. {
  1848. // set idx of most recent loc w/ a set end event
  1849. p->maxSetLocIdx = locIdx;
  1850. if( p->minSetLocIdx == cmInvalidIdx )
  1851. p->minSetLocIdx = locIdx;
  1852. }
  1853. // attempt to calculate all sets between loc[p->minSetLocIdx] and loc[p->maxSetLocIdx]
  1854. _cmScPerfExecRange(p);
  1855. // prevent event retriggering or going backwards
  1856. if( printLvl && locIdx < p->nxtLocIdx )
  1857. {
  1858. printf("----- BACK ----- \n");
  1859. return;
  1860. }
  1861. if( printLvl && locIdx > p->nxtLocIdx )
  1862. {
  1863. printf("----- SKIP ----- \n");
  1864. }
  1865. // for each location between the current and previous location
  1866. for(; p->nxtLocIdx<=locIdx; ++p->nxtLocIdx)
  1867. {
  1868. lp = p->loc + p->nxtLocIdx;
  1869. // if this location is the start of a new section - then apply
  1870. // sets that are assigned to this section
  1871. if( lp->begSectPtr != NULL && lp->begSectPtr->setCnt > 0 )
  1872. {
  1873. // notice the location of the oldest section start - once we cross this point
  1874. // it is too late to notice set completions - so incr p->inSetLocIdx
  1875. if( lp->begSectPtr->setCnt )
  1876. p->minSetLocIdx = p->nxtLocIdx+1;
  1877. for(i=0; i<lp->begSectPtr->setCnt; ++i)
  1878. {
  1879. cmScoreSet_t* stp = lp->begSectPtr->setArray[i];
  1880. // temporarily commented out for testing purposes
  1881. // if( stp->doneFl == false )
  1882. // _cmScPerfExec(p, stp, printLvl>0 );
  1883. if( stp->doneFl )
  1884. {
  1885. assert( stp->varId < kScVarCnt );
  1886. lp->begSectPtr->vars[ stp->varId ] = stp->value;
  1887. if( p->cbFunc != NULL )
  1888. {
  1889. cmScMsg_t m;
  1890. m.typeId = kVarMsgScId;
  1891. m.u.meas.varId = stp->varId;
  1892. m.u.meas.value = stp->value;
  1893. p->cbFunc(p->cbArg,&m,sizeof(m));
  1894. }
  1895. }
  1896. }
  1897. }
  1898. }
  1899. }
  1900. void cmScoreSetPerfValue( cmScH_t h, unsigned locIdx, unsigned varId, double value )
  1901. {
  1902. cmSc_t* p = _cmScHandleToPtr(h);
  1903. int li = locIdx;
  1904. for(; li>=0; --li)
  1905. if( p->loc[li].begSectPtr != NULL )
  1906. {
  1907. assert( varId < kScVarCnt );
  1908. p->loc[li].begSectPtr->vars[varId] = value;
  1909. break;
  1910. }
  1911. assert( li>=0);
  1912. }
  1913. void cmScoreSetPerfDynLevel( cmScH_t h, unsigned evtIdx, unsigned dynLvl )
  1914. {
  1915. cmSc_t* p = _cmScHandleToPtr(h);
  1916. assert(evtIdx < p->cnt );
  1917. p->array[ evtIdx ].perfDynLvl = dynLvl;
  1918. }
  1919. cmScRC_t cmScoreDecode( const void* msg, unsigned msgByteCnt, cmScMsg_t* m)
  1920. {
  1921. cmScMsg_t* mp = (cmScMsg_t*)msg;
  1922. *m = *mp;
  1923. return kOkScRC;
  1924. }
  1925. void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
  1926. {
  1927. cmSc_t* p = _cmScHandleToPtr(h);
  1928. unsigned i;
  1929. cmRptPrintf(rpt,"evnt CSV bar\n");
  1930. cmRptPrintf(rpt,"index line loctn bar idx type pitch ETD Dynamic\n");
  1931. cmRptPrintf(rpt,"----- ----- ----- --- --- ----- ----- --- -------\n");
  1932. for(i=0; i<p->cnt; ++i)
  1933. {
  1934. cmScoreEvt_t* r = p->array + i;
  1935. switch(r->type)
  1936. {
  1937. case kBarEvtScId:
  1938. cmRptPrintf(rpt,"%5i %5i %3i bar\n",
  1939. i,
  1940. r->line,
  1941. r->barNumb );
  1942. break;
  1943. case kNonEvtScId:
  1944. cmRptPrintf(rpt,"%5i %5i %5i %3i %3i %s %5s %c%c%c %s\n",
  1945. i,
  1946. r->line,
  1947. r->locIdx,
  1948. r->barNumb,
  1949. r->barNoteIdx,
  1950. cmScEvtTypeIdToLabel(r->type),
  1951. cmMidiToSciPitch(r->pitch,NULL,0),
  1952. cmIsFlag(r->flags,kEvenScFl) ? 'e' : ' ',
  1953. cmIsFlag(r->flags,kTempoScFl) ? 't' : ' ',
  1954. cmIsFlag(r->flags,kDynScFl) ? 'd' : ' ',
  1955. cmIsFlag(r->flags,kDynScFl) ? cmScDynIdToLabel(r->dynVal) : "");
  1956. break;
  1957. default:
  1958. break;
  1959. }
  1960. }
  1961. }
  1962. cmScRC_t cmScoreGraphicAlloc( cmScH_t h, cmScGraphic_t** vRef, unsigned* nRef)
  1963. {
  1964. cmScRC_t rc = kOkScRC;
  1965. cmSc_t* p = _cmScHandleToPtr(h);
  1966. cmScGraphic_t* v = cmMemAllocZ(cmScGraphic_t,p->cnt);
  1967. unsigned i,j,k,k0;
  1968. unsigned bordH = 5;
  1969. unsigned bordW = 5;
  1970. unsigned noteW = 30;
  1971. unsigned noteH = 30;
  1972. unsigned left = bordH;
  1973. unsigned top = bordW;
  1974. // for each score location
  1975. for(i=0,k=0; i<p->locCnt; ++i)
  1976. {
  1977. left += k0!=k ? noteW + bordW : 0;
  1978. top = noteH + 2*bordH;
  1979. k0 = k;
  1980. // for each event in location i
  1981. for(j=0; j<p->loc[i].evtCnt; ++j)
  1982. {
  1983. const cmScoreEvt_t* e = p->loc[i].evtArray[j];
  1984. switch( e->type)
  1985. {
  1986. case kBarEvtScId:
  1987. top = bordH;
  1988. case kNonEvtScId:
  1989. assert( k < p->cnt );
  1990. v[k].type = e->type;
  1991. v[k].csvEventId = e->csvEventId;
  1992. v[k].left = left;
  1993. v[k].top = top;
  1994. v[k].width = noteW;
  1995. v[k].height = noteH;
  1996. if( e->type == kBarEvtScId )
  1997. v[k].text = cmTsPrintfP(NULL,"%i",e->barNumb);
  1998. else
  1999. v[k].text = cmMemAllocStr( cmMidiToSciPitch( e->pitch, NULL, 0));
  2000. top += noteH + bordH;
  2001. k += 1;
  2002. break;
  2003. }
  2004. }
  2005. }
  2006. *nRef = k;
  2007. *vRef = v;
  2008. return rc;
  2009. }
  2010. cmScRC_t cmScoreGraphicRelease( cmScH_t h, cmScGraphic_t** vRef, unsigned* nRef)
  2011. {
  2012. if( vRef == NULL || nRef==NULL )
  2013. return kOkScRC;
  2014. unsigned i;
  2015. cmScGraphic_t* v = *vRef;
  2016. unsigned n = *nRef;
  2017. for(i=0; i<n; ++i)
  2018. cmMemFree((cmChar_t*)v[i].text);
  2019. cmMemFree(v);
  2020. *vRef = NULL;
  2021. *nRef = 0;
  2022. return kOkScRC;
  2023. }
  2024. cmScRC_t cmScoreGraphicWriteF( cmScH_t h, const cmChar_t* fn, cmScGraphic_t* v, unsigned n )
  2025. {
  2026. cmScRC_t rc = kOkScRC;
  2027. cmSc_t* p = _cmScHandleToPtr(h);
  2028. cmFileH_t fH = cmFileNullHandle;
  2029. unsigned i;
  2030. if( cmFileOpen(&fH,fn,kWriteFileFl,p->err.rpt) != kOkFileRC )
  2031. return cmErrMsg(&p->err,kFileFailScRC,"Graphic file create failed for '%s'.",cmStringNullGuard(fn));
  2032. unsigned svgWidth = v[n-1].left + v[n-1].width + 10;
  2033. unsigned svgHeight = 0;
  2034. for(i=0; i<n; ++i)
  2035. if( v[i].top + v[i].height > svgHeight )
  2036. svgHeight = v[i].top + v[i].height;
  2037. svgHeight += 10;
  2038. cmFilePrintf(fH,"<!DOCTYPE html>\n<html>\n<head><link rel=\"stylesheet\" type=\"text/css\" href=\"score0.css\"></head><body>\n<svg width=\"%i\" height=\"%i\">\n",svgWidth,svgHeight);
  2039. if((rc != cmScoreGraphicWrite(h,fH,v,n)) != kOkScRC )
  2040. goto errLabel;
  2041. cmFilePrint(fH,"</svg>\n</body>\n</html>\n");
  2042. errLabel:
  2043. cmFileClose(&fH);
  2044. return rc;
  2045. }
  2046. cmScRC_t cmScoreGraphicWrite( cmScH_t h, cmFileH_t fH, cmScGraphic_t* v, unsigned n )
  2047. {
  2048. cmSc_t* p = _cmScHandleToPtr(h);
  2049. unsigned i;
  2050. for(i=0; i<n; ++i)
  2051. {
  2052. const cmScGraphic_t* g = v + i;
  2053. if( cmFilePrintf(fH,"<rect x=\"%i\" y=\"%i\" width=\"%i\" height=\"%i\" class=\"score\"/>\n",g->left,g->top,g->width,g->height) != kOkFileRC )
  2054. return cmErrMsg(&p->err,kFileFailScRC,"File write failed on graphic file output.");
  2055. if( g->text != NULL )
  2056. {
  2057. unsigned tx = g->left + g->width/2;
  2058. unsigned ty = g->top + 20; //g->height/2;
  2059. if( cmFilePrintf(fH,"<text x=\"%i\" y=\"%i\" text-anchor=\"middle\" class=\"stext\">%s</text>\n",tx,ty,g->text) != kOkFileRC )
  2060. return cmErrMsg(&p->err,kFileFailScRC,"File write failed on graphic file output.");
  2061. }
  2062. //<rect x="0" y="0" width="200" height="100" stroke="red" stroke-width="3px" fill="white"/>
  2063. //<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">TEXT</text>
  2064. }
  2065. return kOkScRC;
  2066. }
  2067. cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn )
  2068. {
  2069. cmScRC_t rc = kOkScRC;
  2070. cmMidiFileH_t mfH = cmMidiFileNullHandle;
  2071. cmCsvH_t csvH = cmCsvNullHandle;
  2072. cmErr_t err;
  2073. cmChar_t* titles[] = {"id","trk","evt","opcode","dticks","micros","status","meta","ch","d0","d1","arg0","arg1","bar","skip","even","grace","tempo","t frac","dyn","section","remark", NULL };
  2074. cmErrSetup(&err,&ctx->rpt,"MIDI to Score");
  2075. if( cmMidiFileOpen(ctx, &mfH, midiFn ) != kOkMfRC )
  2076. return cmErrMsg(&err,kMidiFileFailScRC,"Unable to open the MIDI file '%s'.",midiFn);
  2077. if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
  2078. {
  2079. cmErrMsg(&err,kCsvFailScRC,"Unable to initialize the CSV file: '%s'.",scoreFn);
  2080. goto errLabel;
  2081. }
  2082. //printf("secs:%f smps:%f\n",cmMidiFileDurSecs(mfH),cmMidiFileDurSecs(mfH)*96000);
  2083. unsigned msgCnt = cmMidiFileMsgCount(mfH);
  2084. unsigned i;
  2085. const cmMidiTrackMsg_t** tmpp = cmMidiFileMsgArray(mfH);
  2086. double acc_secs = 0;
  2087. unsigned lexTId = 0;
  2088. cmCsvCell_t* cp = NULL;
  2089. if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymText(csvH,titles[0]), kStrCsvTFl, lexTId ) != kOkCsvRC )
  2090. {
  2091. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
  2092. goto errLabel;
  2093. }
  2094. for(i=1; titles[i]!=NULL; ++i)
  2095. {
  2096. if( cmCsvInsertIdentColAfter(csvH, cp, &cp, titles[i], lexTId ) != kOkCsvRC )
  2097. {
  2098. cmErrMsg(&err,kCsvFailScRC,"Error inserting column index '%i' label in '%s'.",i,cmStringNullGuard(scoreFn));
  2099. goto errLabel;
  2100. }
  2101. }
  2102. for(i=0; i<msgCnt; ++i)
  2103. {
  2104. const cmMidiTrackMsg_t* tmp = tmpp[i];
  2105. const cmChar_t* opStr = NULL;
  2106. unsigned midiCh = 0;
  2107. unsigned d0 = 0;
  2108. unsigned d1 = 0;
  2109. unsigned metaId = 0;
  2110. double dsecs = (double)tmp->amicro / 1000000.0;
  2111. acc_secs += dsecs;
  2112. if( tmp->status == kMetaStId )
  2113. {
  2114. //opStr = cmMidiMetaStatusToLabel(tmp->metaId);
  2115. opStr = cmScStatusToOpString(tmp->metaId);
  2116. metaId = tmp->metaId;
  2117. switch( tmp->metaId )
  2118. {
  2119. case kTempoMdId:
  2120. d0 = tmp->u.iVal;
  2121. }
  2122. }
  2123. else
  2124. {
  2125. //opStr = cmMidiStatusToLabel(tmp->status);
  2126. opStr = cmScStatusToOpString(tmp->status);
  2127. if( cmMidiIsChStatus( tmp->status ) )
  2128. {
  2129. midiCh = tmp->u.chMsgPtr->ch;
  2130. d0 = tmp->u.chMsgPtr->d0;
  2131. d1 = tmp->u.chMsgPtr->d1;
  2132. }
  2133. }
  2134. cp = NULL;
  2135. // skip note-off messages
  2136. if( tmp->status == kNoteOffMdId )
  2137. continue;
  2138. if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymUInt(csvH,i), kIntCsvTFl, lexTId ) != kOkCsvRC )
  2139. {
  2140. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
  2141. goto errLabel;
  2142. }
  2143. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->trkIdx, lexTId ) != kOkCsvRC )
  2144. {
  2145. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'trk' column in '%s'.",cmStringNullGuard(scoreFn));
  2146. goto errLabel;
  2147. }
  2148. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 0, lexTId ) != kOkCsvRC )
  2149. {
  2150. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'evt' column in '%s'.",cmStringNullGuard(scoreFn));
  2151. goto errLabel;
  2152. }
  2153. if( cmCsvInsertQTextColAfter(csvH, cp, &cp, opStr, lexTId ) != kOkCsvRC )
  2154. {
  2155. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
  2156. goto errLabel;
  2157. }
  2158. if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, dsecs, lexTId ) != kOkCsvRC )
  2159. {
  2160. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'dticks' column in '%s'.",cmStringNullGuard(scoreFn));
  2161. goto errLabel;
  2162. }
  2163. if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, acc_secs, lexTId ) != kOkCsvRC )
  2164. {
  2165. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'micros' column in '%s'.",cmStringNullGuard(scoreFn));
  2166. goto errLabel;
  2167. }
  2168. if( cmCsvInsertHexColAfter(csvH, cp, &cp, tmp->status, lexTId ) != kOkCsvRC )
  2169. {
  2170. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'status' column in '%s'.",cmStringNullGuard(scoreFn));
  2171. goto errLabel;
  2172. }
  2173. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, metaId, lexTId ) != kOkCsvRC )
  2174. {
  2175. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'meta' column in '%s'.",cmStringNullGuard(scoreFn));
  2176. goto errLabel;
  2177. }
  2178. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, midiCh, lexTId ) != kOkCsvRC )
  2179. {
  2180. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'ch' column in '%s'.",cmStringNullGuard(scoreFn));
  2181. goto errLabel;
  2182. }
  2183. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d0, lexTId ) != kOkCsvRC )
  2184. {
  2185. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd0' column in '%s'.",cmStringNullGuard(scoreFn));
  2186. goto errLabel;
  2187. }
  2188. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d1, lexTId ) != kOkCsvRC )
  2189. {
  2190. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd1' column in '%s'.",cmStringNullGuard(scoreFn));
  2191. goto errLabel;
  2192. }
  2193. switch( tmp->status )
  2194. {
  2195. case kNoteOnMdId:
  2196. if( cmCsvInsertQTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
  2197. {
  2198. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
  2199. goto errLabel;
  2200. }
  2201. case kMetaStId:
  2202. switch( tmp->metaId )
  2203. {
  2204. case kTimeSigMdId:
  2205. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
  2206. {
  2207. cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
  2208. goto errLabel;
  2209. }
  2210. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
  2211. {
  2212. cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
  2213. goto errLabel;
  2214. }
  2215. break;
  2216. case kTempoMdId:
  2217. if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
  2218. {
  2219. cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
  2220. goto errLabel;
  2221. }
  2222. break;
  2223. }
  2224. }
  2225. }
  2226. if( cmCsvWrite(csvH,scoreFn) != kOkCsvRC )
  2227. {
  2228. cmErrMsg(&err,kCsvFailScRC,"The score output file '%s' could not be written.",cmStringNullGuard(scoreFn));
  2229. goto errLabel;
  2230. }
  2231. errLabel:
  2232. cmMidiFileClose(&mfH);
  2233. cmCsvFinalize(&csvH);
  2234. return rc;
  2235. }
  2236. void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
  2237. {
  2238. cmScH_t h = cmScNullHandle;
  2239. if( cmScoreInitialize(ctx,&h,fn,0,NULL,0,NULL,NULL, cmSymTblNullHandle ) != kOkScRC )
  2240. return;
  2241. cmScorePrint(h,&ctx->rpt);
  2242. cmScoreFinalize(&h);
  2243. }
  2244. // 1. Fix absolute message time which was incorrect on original score file.
  2245. // 2.
  2246. void cmScoreFix( cmCtx_t* ctx )
  2247. {
  2248. const cmChar_t* mfn = "/home/kevin/src/cmgv/src/gv/data/ImaginaryThemes.mid";
  2249. const cmChar_t* crfn = "/home/kevin/src/cmgv/src/gv/data/mod0a.txt";
  2250. const cmChar_t* cwfn = "/home/kevin/src/cmgv/src/gv/data/mod1.csv";
  2251. cmMidiFileH_t mfH = cmMidiFileNullHandle;
  2252. cmCsvH_t csvH = cmCsvNullHandle;
  2253. const cmMidiTrackMsg_t** msg = NULL;
  2254. double secs = 0.0;
  2255. int ci,mi,crn,mn;
  2256. bool errFl = true;
  2257. unsigned handCnt = 0;
  2258. unsigned midiMissCnt = 0;
  2259. if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
  2260. goto errLabel;
  2261. if( cmCsvLexRegisterMatcher(csvH, cmCsvLexNextAvailId(csvH), _cmScLexSciPitchMatcher ) != kOkCsvRC )
  2262. goto errLabel;
  2263. if( cmCsvParseFile(csvH, crfn, 0 ) != kOkCsvRC )
  2264. goto errLabel;
  2265. if( cmMidiFileOpen(ctx,&mfH,mfn) != kOkMfRC )
  2266. goto errLabel;
  2267. mn = cmMidiFileMsgCount(mfH);
  2268. msg = cmMidiFileMsgArray(mfH);
  2269. crn = cmCsvRowCount(csvH);
  2270. // for each row in the score file
  2271. for(ci=1,mi=0; ci<crn && cmCsvLastRC(csvH)==kOkCsvRC; ++ci)
  2272. {
  2273. unsigned id;
  2274. // zero the duration column
  2275. if( cmCsvCellPtr(csvH, ci, kDSecsColScIdx ) != NULL )
  2276. cmCsvSetCellUInt( csvH, ci, kDSecsColScIdx, 0 );
  2277. // get the MIDI file event id for this row
  2278. if((id = cmCsvCellUInt(csvH,ci,kMidiFileIdColScIdx)) == UINT_MAX)
  2279. {
  2280. // this is a hand-entered event - so it has no event id
  2281. ++handCnt;
  2282. }
  2283. else
  2284. {
  2285. for(; mi<mn; ++mi)
  2286. {
  2287. const cmMidiTrackMsg_t* m = msg[mi];
  2288. assert( mi+1 <= id );
  2289. secs += m->amicro/1000000.0;
  2290. if( mi+1 != id )
  2291. {
  2292. if( m->status == kNoteOnMdId && m->u.chMsgPtr->d1>0 )
  2293. {
  2294. // this MIDI note-on does not have a corresponding score event
  2295. ++midiMissCnt;
  2296. }
  2297. }
  2298. else
  2299. {
  2300. cmCsvSetCellDouble( csvH, ci, kSecsColScIdx, secs );
  2301. ++mi;
  2302. if( m->status == kNoteOnMdId )
  2303. cmCsvSetCellDouble( csvH, ci, kDSecsColScIdx, m->u.chMsgPtr->durMicros /1000000.0 );
  2304. break;
  2305. }
  2306. }
  2307. if( mi==mn)
  2308. printf("done on row:%i\n",ci);
  2309. }
  2310. }
  2311. if( cmCsvLastRC(csvH) != kOkCsvRC )
  2312. goto errLabel;
  2313. if( cmCsvWrite(csvH,cwfn) != kOkCsvRC )
  2314. goto errLabel;
  2315. errFl = false;
  2316. errLabel:
  2317. if( errFl )
  2318. printf("Score fix failed.\n");
  2319. else
  2320. printf("Score fix done! hand:%i miss:%i\n",handCnt,midiMissCnt);
  2321. cmMidiFileClose(&mfH);
  2322. cmCsvFinalize(&csvH);
  2323. }