|
@@ -28,10 +28,11 @@ enum
|
28
|
28
|
kDynXsFl = 0x0040,
|
29
|
29
|
kEvenXsFl = 0x0080,
|
30
|
30
|
kTempoXsFl = 0x0100,
|
31
|
|
- kPedalDnXsFl = 0x0200,
|
32
|
|
- kPedalUpXsFl = 0x0400,
|
33
|
|
- kPedalUpDnXsFl = 0x0800,
|
34
|
|
- kMetronomeXsFl = 0x1000 // duration holds BPM
|
|
31
|
+ kHeelXsFl = 0x0200,
|
|
32
|
+ kPedalDnXsFl = 0x0400,
|
|
33
|
+ kPedalUpXsFl = 0x0800,
|
|
34
|
+ kPedalUpDnXsFl = 0x1000,
|
|
35
|
+ kMetronomeXsFl = 0x2000 // duration holds BPM
|
35
|
36
|
};
|
36
|
37
|
|
37
|
38
|
|
|
@@ -41,7 +42,7 @@ typedef struct cmXsNote_str
|
41
|
42
|
unsigned pitch; // midi pitch
|
42
|
43
|
unsigned tick; //
|
43
|
44
|
unsigned duration; // duration in ticks
|
44
|
|
- unsigned rvalue; // 1/type = rythmic value (1/4=quarter note, 1/8=eighth note, ...)
|
|
45
|
+ double rvalue; // 1/rvalue = rythmic value (1/0.5 double whole 1/1 whole 1/2 half 1/4=quarter note, 1/8=eighth note, ...)
|
45
|
46
|
const cmChar_t* tvalue; // text value
|
46
|
47
|
struct cmXsNote_str* mlink; // measure note list
|
47
|
48
|
struct cmXsNote_str* slink; // time sorted event list
|
|
@@ -233,46 +234,57 @@ cmXsRC_t _cmXScoreParsePitch( cmXScore_t* p, const cmXmlNode_t* nnp, unsigned*
|
233
|
234
|
return rc;
|
234
|
235
|
}
|
235
|
236
|
|
236
|
|
-unsigned _cmXScoreParseNoteRValue( cmXScore_t* p, const cmXmlNode_t* nnp, const cmChar_t* label )
|
|
237
|
+cmXsRC_t _cmXScoreParseNoteRValue( cmXScore_t* p, const cmXmlNode_t* nnp, const cmChar_t* label, double* rvalueRef )
|
237
|
238
|
{
|
238
|
239
|
typedef struct map_str
|
239
|
240
|
{
|
240
|
|
- unsigned rvalue;
|
|
241
|
+ double rvalue;
|
241
|
242
|
const cmChar_t* label;
|
242
|
243
|
} map_t;
|
243
|
244
|
|
244
|
245
|
map_t mapV[] =
|
245
|
246
|
{
|
246
|
|
- { -1, "measure" }, // whole measure rest
|
247
|
|
- { 1, "whole" },
|
248
|
|
- { 2, "half" },
|
249
|
|
- { 4, "quarter" },
|
250
|
|
- { 8, "eighth" },
|
251
|
|
- { 16, "16th" },
|
252
|
|
- { 32, "32nd" },
|
253
|
|
- { 64, "64th" },
|
254
|
|
- { 128, "128th" },
|
255
|
|
- { 0, "" }
|
|
247
|
+ {-1.0, "measure" }, // whole measure rest
|
|
248
|
+ { 0.5, "breve" }, // double whole
|
|
249
|
+ { 1.0, "whole" },
|
|
250
|
+ { 2.0, "half" },
|
|
251
|
+ { 4.0, "quarter" },
|
|
252
|
+ { 8.0, "eighth" },
|
|
253
|
+ {16.0, "16th" },
|
|
254
|
+ {32.0, "32nd" },
|
|
255
|
+ { 64.0, "64th" },
|
|
256
|
+ {128.0, "128th" },
|
|
257
|
+ { 0.0, "" }
|
256
|
258
|
};
|
257
|
259
|
|
258
|
260
|
const cmChar_t* str;
|
|
261
|
+ // get the XML rvalue label
|
259
|
262
|
if((str = cmXmlNodeValue(nnp,label,NULL)) == NULL)
|
260
|
263
|
{
|
261
|
264
|
if((nnp = cmXmlSearch(nnp,"rest",NULL,0)) != NULL )
|
262
|
265
|
{
|
263
|
266
|
const cmXmlAttr_t* a;
|
264
|
267
|
if((a = cmXmlFindAttrib(nnp,"measure")) != NULL && cmTextCmp(a->value,"yes")==0)
|
265
|
|
- return -1;
|
|
268
|
+ {
|
|
269
|
+ *rvalueRef = -1;
|
|
270
|
+ return kOkXsRC;
|
|
271
|
+ }
|
266
|
272
|
}
|
267
|
|
- return 0;
|
|
273
|
+
|
|
274
|
+ return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The 'beat-unit' metronome value is missing on line %i.",nnp->line);
|
268
|
275
|
}
|
269
|
276
|
|
270
|
277
|
unsigned i;
|
|
278
|
+ // lookup the rvalue numeric value from the mapV[] table
|
271
|
279
|
for(i=0; mapV[i].rvalue!=0; ++i)
|
272
|
280
|
if( cmTextCmp(mapV[i].label,str) == 0 )
|
273
|
|
- return mapV[i].rvalue;
|
|
281
|
+ {
|
|
282
|
+ *rvalueRef = mapV[i].rvalue;
|
|
283
|
+ return kOkXsRC;
|
|
284
|
+ }
|
274
|
285
|
|
275
|
|
- return 0;
|
|
286
|
+ // the rvalue label was not found
|
|
287
|
+ return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Unknown rvalue type='%s'.",str);
|
276
|
288
|
}
|
277
|
289
|
|
278
|
290
|
cmXsRC_t _cmXScoreParseColor( cmXScore_t* p, const cmXmlNode_t* nnp, cmXsNote_t* note )
|
|
@@ -288,28 +300,51 @@ cmXsRC_t _cmXScoreParseColor( cmXScore_t* p, const cmXmlNode_t* nnp, cmXsNote_t
|
288
|
300
|
|
289
|
301
|
map_t mapV[] =
|
290
|
302
|
{
|
291
|
|
- { kEvenXsFl, "#0000FF" },
|
292
|
|
- { kTempoXsFl, "#00FF00" },
|
293
|
|
- { kDynXsFl, "#FF0000" },
|
294
|
|
- { kTempoXsFl | kEvenXsFl, "#00FFFF" },
|
295
|
|
- { kDynXsFl | kEvenXsFl, "#FF00FF" },
|
296
|
|
- { kDynXsFl | kTempoXsFl, "#FF7F00" },
|
297
|
|
- { kTempoXsFl | kEvenXsFl | kDynXsFl, "#996633" },
|
298
|
|
- { 0, "" }
|
|
303
|
+ { kEvenXsFl, "#0000FF" }, // blue (even)
|
|
304
|
+ { kTempoXsFl, "#00FF00" }, // green (tempo)
|
|
305
|
+ { kDynXsFl, "#FF0000" }, // red (dynamics)
|
|
306
|
+ { kTempoXsFl | kEvenXsFl, "#00FFFF" }, // green + blue (turquoise)
|
|
307
|
+ { kDynXsFl | kEvenXsFl, "#FF00FF" }, // red + blue
|
|
308
|
+ { kDynXsFl | kEvenXsFl, "#FF0CF7" }, // magenta (even+dyn)
|
|
309
|
+ { kDynXsFl | kTempoXsFl, "#FF7F00" }, // red + green (brown)
|
|
310
|
+ { kTempoXsFl | kEvenXsFl | kDynXsFl, "#996633" }, // (purple)
|
|
311
|
+ { kDynXsFl, "#FF6A03" }, // 176 orange (dynamics)
|
|
312
|
+ { kEvenXsFl, "#2F00E8" }, // 1001 blue (even)
|
|
313
|
+ { kTempoXsFl, "#01CD1F" }, // 1196 green (tempo)
|
|
314
|
+ { kEvenXsFl, "#3600E8" }, // 1627 blue (even)
|
|
315
|
+ { kDynXsFl | kTempoXsFl, "#9E8F15" }, // 8827 brown (dyn + tempo)
|
|
316
|
+ { kEvenXsFl, "#2E00E6" }, // 5393 blue (even)
|
|
317
|
+ { kEvenXsFl, "#2C00DD" }, // 5895 blue (even)
|
|
318
|
+ { kDynXsFl, "#FF5B03" }, // 6498 orange (dyn)
|
|
319
|
+ { kDynXsFl, "#FF6104" }, // 6896 orange
|
|
320
|
+ { kEvenXsFl, "#2A00E6" }, // 7781 blue
|
|
321
|
+ { kEvenXsFl, "#2300DD" }, // 8300 blue (even)
|
|
322
|
+ { kTempoXsFl, "#03CD22" }, // 10820 green (tempo)
|
|
323
|
+ { kEvenXsFl, "#3400DB" }, // 11627 blue (dyn)
|
|
324
|
+ { -1, "" }
|
299
|
325
|
};
|
|
326
|
+
|
|
327
|
+ /*
|
|
328
|
+ orange #FF6A03
|
|
329
|
+ magenta #FF0CF7
|
|
330
|
+ blue #2F00E8
|
|
331
|
+ green #01CD1F
|
|
332
|
+ gold #9E8F15
|
|
333
|
+ green #03CD22
|
|
334
|
+ */
|
300
|
335
|
|
301
|
336
|
if((a = cmXmlFindAttrib(nnp, "color" )) != NULL )
|
302
|
337
|
{
|
303
|
338
|
unsigned i;
|
304
|
|
- for(i=0; mapV[i].value != 0; ++i)
|
|
339
|
+ for(i=0; mapV[i].value != -1; ++i)
|
305
|
340
|
if( cmTextCmp(a->value,mapV[i].label) == 0 )
|
306
|
341
|
{
|
307
|
342
|
note->flags += mapV[i].value;
|
308
|
343
|
break;
|
309
|
344
|
}
|
310
|
345
|
|
311
|
|
- if( mapV[i].value == 0 )
|
312
|
|
- rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The note color '%s' was not found.",a->value);
|
|
346
|
+ if( mapV[i].value == -1 )
|
|
347
|
+ cmErrMsg(&p->err,kSyntaxErrorXsRC,"The note color '%s' was not found on line %i.",a->value,nnp->line);
|
313
|
348
|
}
|
314
|
349
|
|
315
|
350
|
return rc;
|
|
@@ -349,13 +384,17 @@ cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t*
|
349
|
384
|
if( cmXmlNodeHasChild(nnp,"chord",NULL) )
|
350
|
385
|
note->flags |= kChordXsFl;
|
351
|
386
|
|
|
387
|
+ // has 'heel' mark
|
|
388
|
+ if( cmXmlNodeHasChild(nnp,"notations","technical","heel",NULL) )
|
|
389
|
+ note->flags |= kHeelXsFl;
|
|
390
|
+
|
352
|
391
|
// set color coded flags
|
353
|
392
|
if((rc = _cmXScoreParseColor(p, nnp, note )) != kOkXsRC )
|
354
|
393
|
return rc;
|
355
|
394
|
|
356
|
395
|
// get the note's rythmic value
|
357
|
|
- if((note->rvalue = _cmXScoreParseNoteRValue(p,nnp,"type")) == 0 )
|
358
|
|
- return _cmXScoreMissingNode(p,nnp,"type");
|
|
396
|
+ if((rc = _cmXScoreParseNoteRValue(p,nnp,"type",¬e->rvalue)) != kOkXsRC )
|
|
397
|
+ return rc;
|
359
|
398
|
|
360
|
399
|
note->tick = *tickRef;
|
361
|
400
|
|
|
@@ -365,7 +404,7 @@ cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t*
|
365
|
404
|
return _cmXScorePushNote(p, meas, voiceId, note );
|
366
|
405
|
}
|
367
|
406
|
|
368
|
|
-cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, unsigned duration, unsigned rvalue, const cmChar_t* tvalue, unsigned flags )
|
|
407
|
+cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, unsigned duration, double rvalue, const cmChar_t* tvalue, unsigned flags )
|
369
|
408
|
{
|
370
|
409
|
cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
|
371
|
410
|
unsigned voiceId = 0; // non-note's are always assigned to voiceId=0;
|
|
@@ -381,18 +420,17 @@ cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, u
|
381
|
420
|
|
382
|
421
|
cmXsRC_t _cmXScoreParseDirection(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t* dnp, unsigned tick)
|
383
|
422
|
{
|
384
|
|
- const cmXmlNode_t* np = NULL;
|
385
|
|
- const cmXmlAttr_t* a = NULL;
|
|
423
|
+ cmXsRC_t rc = kOkXsRC;
|
|
424
|
+ const cmXmlNode_t* np = NULL;
|
|
425
|
+ const cmXmlAttr_t* a = NULL;
|
386
|
426
|
unsigned flags = 0;
|
387
|
427
|
int offset = 0;
|
388
|
|
- unsigned rvalue = 0;
|
|
428
|
+ double rvalue = 0;
|
389
|
429
|
const cmChar_t* tvalue = NULL;
|
390
|
430
|
unsigned duration = 0;
|
391
|
431
|
|
392
|
|
-
|
393
|
432
|
cmXmlNodeInt(dnp, &offset, "offset", NULL );
|
394
|
433
|
|
395
|
|
-
|
396
|
434
|
// if this is a metronome direction
|
397
|
435
|
if((np = cmXmlSearch( dnp, "metronome", NULL, 0)) != NULL )
|
398
|
436
|
{
|
|
@@ -400,9 +438,9 @@ cmXsRC_t _cmXScoreParseDirection(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNo
|
400
|
438
|
if( cmXmlNodeUInt(np,&duration,"per-minute",NULL) != kOkXmlRC )
|
401
|
439
|
return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The 'per-minute' metronome value is missing on line %i.",np->line);
|
402
|
440
|
|
403
|
|
- if((rvalue = _cmXScoreParseNoteRValue(p,np,"beat-unit")) == 0 )
|
404
|
|
- return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The 'beat-unit' metronome value is missing on line %i.",np->line);
|
405
|
|
-
|
|
441
|
+ if((rc = _cmXScoreParseNoteRValue(p,np,"beat-unit",&rvalue)) != kOkXsRC )
|
|
442
|
+ return rc;
|
|
443
|
+
|
406
|
444
|
flags = kMetronomeXsFl;
|
407
|
445
|
}
|
408
|
446
|
else
|
|
@@ -668,7 +706,7 @@ void _cmXScoreReportNote( cmRpt_t* rpt, const cmXsNote_t* note )
|
668
|
706
|
P = cmIsFlag(note->flags,kPedalUpXsFl) ? "^" : P;
|
669
|
707
|
P = cmIsFlag(note->flags,kPedalUpDnXsFl) ? "X" : P;
|
670
|
708
|
const cmChar_t* N = note->pitch==0 ? " " : cmMidiToSciPitch( note->pitch, NULL, 0 );
|
671
|
|
- cmRptPrintf(rpt," %5i %5i %2i %3s %s%s%s%s%s%s%s%s%s",note->tick,note->duration,note->rvalue,N,B,R,G,D,C,e,d,t,P);
|
|
709
|
+ cmRptPrintf(rpt," %5i %5i %4.1f %3s %s%s%s%s%s%s%s%s%s",note->tick,note->duration,note->rvalue,N,B,R,G,D,C,e,d,t,P);
|
672
|
710
|
|
673
|
711
|
if( cmIsFlag(note->flags,kSectionXsFl) )
|
674
|
712
|
cmRptPrintf(rpt," %i",cmStringNullGuard(note->tvalue));
|
|
@@ -1033,7 +1071,7 @@ cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
1033
|
1071
|
if((rc = cmXScoreInitialize( ctx, &h, fn)) != kOkXsRC )
|
1034
|
1072
|
return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
|
1035
|
1073
|
|
1036
|
|
- cmXScoreWriteCsv(h,"/home/kevin/temp/a0.csv");
|
|
1074
|
+ cmXScoreWriteCsv(h,"/Users/kevin/temp/a0.csv");
|
1037
|
1075
|
cmXScoreReport(h,&ctx->rpt,true);
|
1038
|
1076
|
|
1039
|
1077
|
return cmXScoreFinalize(&h);
|