Kaynağa Gözat

cmXScore.h/c : Completed note, metronome, section label, color, and pedal parsing. Added per measure time sorted note list.

master
Kevin Larke 8 yıl önce
ebeveyn
işleme
304ff25285
2 değiştirilmiş dosya ile 375 ekleme ve 106 silme
  1. 369
    102
      app/cmXScore.c
  2. 6
    4
      app/cmXScore.h

+ 369
- 102
app/cmXScore.c Dosyayı Görüntüle

@@ -17,22 +17,35 @@ cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
17 17
 
18 18
 enum
19 19
 {
20
-  kRestXsFl    = 0x0001,
21
-  kGraceXsFl   = 0x0002,
22
-  kDotXsFl     = 0x0004
20
+  kSectionXsFl   = 0x0001,  // rvalue holds section number
21
+  kBarXsFl       = 0x0002,
22
+  kRestXsFl      = 0x0004,
23
+  kGraceXsFl     = 0x0008,
24
+  kDotXsFl       = 0x0010,
25
+  kChordXsFl     = 0x0020,
26
+  kDynXsFl       = 0x0040,
27
+  kEvenXsFl      = 0x0080,
28
+  kTempoXsFl     = 0x0100,
29
+  kPedalDnXsFl   = 0x0200,
30
+  kPedalUpXsFl   = 0x0400,
31
+  kPedalUpDnXsFl = 0x0800,
32
+  kMetronomeXsFl = 0x1000  // duration holds BPM 
23 33
 };
24 34
 
25 35
 
36
+
26 37
 typedef struct cmXsNote_str
27 38
 {
28
-  unsigned flags;
29
-  unsigned pitch;     // midi pitch
30
-  unsigned duration;  // duration in ticks
31
-  unsigned rvalue;    // 1/type = rythmic value (1/4=quarter note, 1/8=eighth note, ...)
32
-  struct cmXsNote_str* link;
33
-  
39
+  unsigned             flags;    // See k???XsFl 
40
+  unsigned             pitch;    // midi pitch
41
+  unsigned             tick;     // 
42
+  unsigned             duration; // duration in ticks
43
+  unsigned             rvalue;   // 1/type = rythmic value (1/4=quarter note, 1/8=eighth note, ...)
44
+  struct cmXsNote_str* mlink;    // measure note list 
45
+  struct cmXsNote_str* slink;    // time sorted event list
34 46
 } cmXsNote_t;
35 47
 
48
+
36 49
 typedef struct cmXsVoice_str
37 50
 {
38 51
   unsigned              id;    // Voice id
@@ -49,6 +62,7 @@ typedef struct cmXsMeas_str
49 62
   unsigned             beat_type;
50 63
   
51 64
   cmXsVoice_t*         voiceL;  // List of voices in this measure   
65
+  cmXsNote_t*          noteL;   // List of time sorted notes in this measure
52 66
   
53 67
   struct cmXsMeas_str* link;    // Link to other measures in this part.
54 68
 } cmXsMeas_t;
@@ -92,12 +106,9 @@ cmXsRC_t _cmXScoreFinalize( cmXScore_t* p )
92 106
   return rc;
93 107
 }
94 108
 
95
-cmXsRC_t _cmXScoreMissingNode( cmXScore_t* p, const cmChar_t* label, const cmXmlAttr_t* attr )
109
+cmXsRC_t _cmXScoreMissingNode( cmXScore_t* p, const cmXmlNode_t* parent, const cmChar_t* label )
96 110
 {
97
-  if( attr == NULL )
98
-    return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Missing XML node '%s'.",label);
99
-
100
-  return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Missing XML node '%s' - Attribute:%s=%s",label,attr->label,attr->value);
111
+  return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Missing XML node '%s'. Parent line:%i",label,parent->line);
101 112
 }
102 113
 
103 114
 cmXsRC_t _cmXScoreMissingAttribute( cmXScore_t* p, const cmXmlNode_t* np, const cmChar_t* attrLabel )
@@ -105,6 +116,55 @@ cmXsRC_t _cmXScoreMissingAttribute( cmXScore_t* p, const cmXmlNode_t* np, const
105 116
   return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Missing XML attribute '%s' from node '%s'.",attrLabel,np->label);
106 117
 }
107 118
 
119
+cmXsVoice_t* _cmXScoreIdToVoice( cmXsMeas_t* meas, unsigned voiceId )
120
+{
121
+  cmXsVoice_t* v = meas->voiceL;
122
+  for(; v!=NULL; v=v->link)
123
+    if( v->id == voiceId )
124
+      return v;
125
+
126
+  return NULL;
127
+}
128
+
129
+cmXsRC_t _cmXScorePushNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned voiceId, cmXsNote_t* note )
130
+{
131
+  cmXsVoice_t* v;
132
+
133
+  // get the voice recd
134
+  if((v = _cmXScoreIdToVoice(meas,voiceId)) == NULL)
135
+  {
136
+    // the voice recd doesn't exist for this voiceId - allocate one
137
+    v = cmLhAllocZ(p->lhH,cmXsVoice_t,1);
138
+    v->id = voiceId;
139
+
140
+    // add the voice record to the meas->voiceL
141
+    if( meas->voiceL == NULL )
142
+      meas->voiceL = v;
143
+    else
144
+    {
145
+      cmXsVoice_t* vp =  meas->voiceL;
146
+      while( vp->link!=NULL )
147
+        vp = vp->link;
148
+
149
+      vp->link = v;      
150
+    }
151
+  }
152
+
153
+  // add the note record to the end of meas->voiceL
154
+  if( v->noteL == NULL )
155
+    v->noteL = note;
156
+  else
157
+  {
158
+    cmXsNote_t* n = v->noteL;
159
+    while( n->mlink != NULL )
160
+      n = n->mlink;
161
+
162
+    n->mlink = note;
163
+  }
164
+
165
+  return kOkXsRC;
166
+}
167
+
108 168
 cmXsRC_t _cmXScoreParsePartList( cmXScore_t* p )
109 169
 {
110 170
   cmXsRC_t           rc          = kOkXsRC;
@@ -113,7 +173,7 @@ cmXsRC_t _cmXScoreParsePartList( cmXScore_t* p )
113 173
 
114 174
   // find the 'part-list'
115 175
   if((xnp = cmXmlSearch( cmXmlRoot(p->xmlH), "part-list", NULL, 0)) == NULL )
116
-    return _cmXScoreMissingNode(p,"part-list",NULL);
176
+    return _cmXScoreMissingNode(p,cmXmlRoot(p->xmlH),"part-list");
117 177
   
118 178
   const cmXmlNode_t* cnp = xnp->children;
119 179
 
@@ -152,10 +212,10 @@ cmXsRC_t  _cmXScoreParsePitch( cmXScore_t* p, const cmXmlNode_t* nnp, unsigned*
152 212
   const cmChar_t* step   = NULL;
153 213
 
154 214
   if((step = cmXmlNodeValue(nnp,"pitch","step",NULL)) == NULL )
155
-    return _cmXScoreMissingNode(p,"step",NULL);
215
+    return _cmXScoreMissingNode(p,nnp,"step");
156 216
   
157 217
   if((rc = cmXmlNodeUInt( nnp,&octave,"pitch","octave",NULL)) != kOkXmlRC )
158
-    return _cmXScoreMissingNode(p,"octave",NULL);
218
+    return _cmXScoreMissingNode(p,nnp,"octave");
159 219
   
160 220
   cmXmlNodeDouble( nnp,&alter,"pitch","alter",NULL);
161 221
 
@@ -171,7 +231,7 @@ cmXsRC_t  _cmXScoreParsePitch( cmXScore_t* p, const cmXmlNode_t* nnp, unsigned*
171 231
   return rc;  
172 232
 }
173 233
 
174
-unsigned _cmXScoreParseNoteType( const cmXmlNode_t* nnp )
234
+unsigned _cmXScoreParseNoteRValue( cmXScore_t* p, const cmXmlNode_t* nnp, const cmChar_t* label )
175 235
 {
176 236
   typedef struct map_str
177 237
   {
@@ -181,118 +241,206 @@ unsigned _cmXScoreParseNoteType( const cmXmlNode_t* nnp )
181 241
 
182 242
   map_t mapV[] =
183 243
   {
184
-    { 1, "whole" },
185
-    { 2, "half"  },
186
-    { 4, "quarter" },
187
-    { 8, "eighth" },
188
-    { 16,"16th"},
189
-    { 32,"32nd"},
190
-    { 64,"64th"},
191
-    {128,"128th"},
192
-    {0,""}
244
+    {   1, "whole"   },
245
+    {   2, "half"    },
246
+    {   4, "quarter" },
247
+    {   8, "eighth"  },
248
+    {  16, "16th"    },
249
+    {  32, "32nd"    },
250
+    {  64, "64th"    },
251
+    { 128, "128th"   },
252
+    {   0, ""        }
193 253
   };
194 254
 
195
-  if( cmXmlNodeHasChild(nnp,"type") )
196
-  {
197
-    const cmChar_t* str;
198
-    if((str = cmXmlNodeValue(nnp,"type",NULL)) == NULL)
199
-    {
200
-      unsigned i;
201
-      for(i=0; mapV[i].rvalue!=0; ++i)
202
-        if( cmTextCmp(mapV[i].label,str) == 0 )
203
-          return mapV[i].rvalue;
204
-    }
205
-
206
-  }
207
-
255
+  const cmChar_t* str;
256
+  if((str = cmXmlNodeValue(nnp,label,NULL)) == NULL)
257
+    return 0;
258
+  
259
+  unsigned i;
260
+  for(i=0; mapV[i].rvalue!=0; ++i)
261
+    if( cmTextCmp(mapV[i].label,str) == 0 )
262
+      return mapV[i].rvalue;
263
+  
208 264
   return 0;
209 265
 }
210 266
 
211
-cmXsVoice_t* _cmXScoreIdToVoice( cmXsMeas_t* meas, unsigned voiceId )
267
+cmXsRC_t  _cmXScoreParseColor( cmXScore_t* p, const cmXmlNode_t* nnp, cmXsNote_t* note )
212 268
 {
213
-  cmXsVoice_t* v = meas->voiceL;
214
-  for(; v!=NULL; v=v->link)
215
-    if( v->id == voiceId )
216
-      return v;
217
-
218
-  return NULL;
219
-}
269
+  cmXsRC_t rc = kOkXsRC;
270
+  const cmXmlAttr_t* a;
220 271
 
221
-cmXsRC_t _cmXScorePushNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned voiceId, cmXsNote_t* note )
222
-{
223
-  cmXsVoice_t* v;
224
-  if((v = _cmXScoreIdToVoice(meas,voiceId)) == NULL)
272
+   typedef struct map_str
225 273
   {
226
-    v = cmLhAllocZ(p->lhH,cmXsVoice_t,1);
227
-    v->id = voiceId;
228
-    
229
-    if( meas->voiceL == NULL )
230
-      meas->voiceL = v;
231
-    else
232
-    {
233
-      cmXsVoice_t* vp =  meas->voiceL;
234
-      while( vp->link!=NULL )
235
-        vp = vp->link;
236
-
237
-      vp->link = v;      
238
-    }
239
-  }
274
+    unsigned        value;
275
+    const cmChar_t* label;
276
+  } map_t;
240 277
 
241
-  if( v->noteL == NULL )
242
-    v->noteL = note;
243
-  else
278
+  map_t mapV[] =
244 279
   {
245
-    cmXsNote_t* n = v->noteL;
246
-    while( n != NULL )
247
-      n = n->link;
280
+    { kEvenXsFl,                         "#0000FF" },
281
+    { kTempoXsFl,                        "#00FF00" },
282
+    { kDynXsFl,                          "#FF0000" },
283
+    { kTempoXsFl | kEvenXsFl,            "#00FFFF" },
284
+    { kDynXsFl   | kEvenXsFl,            "#FF00FF" },    
285
+    { kDynXsFl   | kTempoXsFl,           "#FF7F00" },
286
+    { kTempoXsFl | kEvenXsFl | kDynXsFl, "#996633" },
287
+    { 0, "" }
288
+  };
289
+  
290
+  if((a = cmXmlFindAttrib(nnp, "color" )) != NULL )
291
+  {
292
+    unsigned i;
293
+    for(i=0; mapV[i].value != 0; ++i)
294
+      if( cmTextCmp(a->value,mapV[i].label) == 0 )
295
+      {
296
+        note->flags += mapV[i].value;
297
+        break;
298
+      }
248 299
 
249
-    n->link = note;
300
+    if( mapV[i].value == 0 )
301
+      rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The note color '%s' was not found.",a->value);
250 302
   }
251 303
 
252
-  return kOkXsRC;
304
+  return rc;
253 305
 }
254 306
 
255
-cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t* nnp)
307
+cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t* nnp, unsigned* tickRef )
256 308
 {
257 309
   cmXsRC_t    rc   = kOkXsRC;
258
-  
259 310
   cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
260
-  unsigned voiceId;
311
+  unsigned    voiceId;
261 312
 
262 313
   // get the voice id for this node
263 314
   if( cmXmlNodeUInt(nnp,&voiceId,"voice",NULL) != kOkXmlRC )
264
-    return _cmXScoreMissingNode(p,"voice",NULL);
315
+    return _cmXScoreMissingNode(p,nnp,"voice");
265 316
 
266
-  
267 317
   // if this note has a pitch
268
-  if( cmXmlNodeHasChild(nnp,"pitch") )
318
+  if( cmXmlNodeHasChild(nnp,"pitch",NULL) )
269 319
     if((rc = _cmXScoreParsePitch(p,nnp,&note->pitch)) != kOkXsRC )
270 320
       return rc;
271 321
 
322
+  // get the note duration
323
+  cmXmlNodeUInt(nnp,&note->duration,"duration",NULL);
324
+  
272 325
   // is 'rest'
273
-  if( cmXmlNodeHasChild(nnp,"rest") )
326
+  if( cmXmlNodeHasChild(nnp,"rest",NULL) )
274 327
     note->flags |= kRestXsFl;
275 328
 
276 329
   // is 'grace'
277
-  if( cmXmlNodeHasChild(nnp,"grace") )
330
+  if( cmXmlNodeHasChild(nnp,"grace",NULL) )
278 331
     note->flags |= kGraceXsFl;
279 332
 
280 333
   // is 'dot'
281
-  if( cmXmlNodeHasChild(nnp,"dot") )
334
+  if( cmXmlNodeHasChild(nnp,"dot",NULL) )
282 335
     note->flags |= kDotXsFl;
283 336
 
284
-  if((note->rvalue =  _cmXScoreParseNoteType(nnp)) == 0 )
285
-    return _cmXScoreMissingNode(nnp,"type",NULL);
337
+  // is 'chord'
338
+  if( cmXmlNodeHasChild(nnp,"chord",NULL) )
339
+    note->flags |= kChordXsFl;
340
+
341
+  // set color coded flags
342
+  if((rc = _cmXScoreParseColor(p, nnp, note )) != kOkXsRC )
343
+    return rc;
344
+  
345
+  // get the note's rythmic value
346
+  if((note->rvalue =  _cmXScoreParseNoteRValue(p,nnp,"type")) == 0 )
347
+    return _cmXScoreMissingNode(p,nnp,"type");
348
+
349
+  note->tick = *tickRef;
350
+
351
+  if( cmIsNotFlag(note->flags,kChordXsFl) )
352
+    *tickRef += note->duration;
353
+  
354
+  return _cmXScorePushNote(p, meas, voiceId, note );
355
+}
356
+
357
+cmXsRC_t _cmXScorePushNonNote( cmXScore_t* p, cmXsMeas_t* meas, unsigned tick, unsigned duration, unsigned rvalue, unsigned flags )
358
+{
359
+  cmXsNote_t* note    = cmLhAllocZ(p->lhH,cmXsNote_t,1);
360
+  unsigned    voiceId = 0;    // non-note's are always assigned to voiceId=0;
361
+  
362
+  note->tick     = tick;
363
+  note->flags    = flags;
364
+  note->rvalue   = rvalue;
365
+  note->duration = duration;
366
+  
367
+  return _cmXScorePushNote(p, meas, voiceId, note );
368
+}
369
+
370
+cmXsRC_t  _cmXScoreParseDirection(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t* dnp, unsigned tick)
371
+{
372
+  const cmXmlNode_t* np = NULL;
373
+  const cmXmlAttr_t* a = NULL;
374
+  unsigned           flags    = 0;
375
+  int                offset   = 0;
376
+  unsigned           rvalue   = 0;
377
+  unsigned           duration = 0;
378
+
379
+  
380
+  cmXmlNodeInt(dnp, &offset, "offset", NULL );
381
+   
382
+ 
383
+  // if this is a metronome direction
384
+  if((np = cmXmlSearch( dnp, "metronome", NULL, 0)) != NULL )
385
+  {
386
+    
387
+    if( cmXmlNodeUInt(np,&duration,"per-minute",NULL) != kOkXmlRC )
388
+      return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The 'per-minute' metronome value is missing on line %i.",np->line);
389
+
390
+    if((rvalue = _cmXScoreParseNoteRValue(p,np,"beat-unit")) == 0 )
391
+      return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The 'beat-unit' metronome value is missing on line %i.",np->line);
392
+
393
+    flags = kMetronomeXsFl;
394
+  }
395
+  else
396
+
397
+  // if this is a pedal direction
398
+  if((np = cmXmlSearch( dnp, "pedal",NULL,0)) != NULL )
399
+  {
286 400
     
401
+    if((a = cmXmlFindAttrib(np,"type")) == NULL )
402
+      return _cmXScoreMissingAttribute(p, np, "type" );
403
+
404
+    if( cmTextCmp(a->value,"start") == 0 )
405
+      flags = kPedalDnXsFl;
406
+    else
407
+      if( cmTextCmp(a->value,"change") == 0 )
408
+        flags = kPedalUpDnXsFl;
409
+      else
410
+        if( cmTextCmp(a->value,"stop") == 0 )
411
+          flags = kPedalUpXsFl;
412
+        else
413
+          return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Unrecognized pedal type:'%s'.",cmStringNullGuard(a->value));
414
+  }
415
+  else
416
+  
417
+  // if this is a 'words' direction
418
+  if((np = cmXmlSearch( dnp, "words", NULL, 0)) != NULL )
419
+  {
420
+    if((a = cmXmlFindAttrib(np,"enclosure")) != NULL && cmTextCmp(a->value,"rectangle")==0 )
421
+    {
422
+      if( cmXmlNodeUInt(np,&rvalue,NULL) != kOkXsRC )
423
+        return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Error reading section number on line %i.",np->line);
424
+
425
+      printf("rvalue=%i\n",rvalue);
426
+      
427
+      flags = kSectionXsFl;
428
+    }
429
+  }
430
+
431
+  return _cmXScorePushNonNote(p,meas,tick+offset,duration,rvalue,flags);            
432
+      
287 433
 }
288 434
 
435
+
289 436
 cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t* mnp)
290 437
 {
291
-  cmXsRC_t rc = kOkXsRC;
438
+  cmXsRC_t           rc   = kOkXsRC;
439
+  const cmXmlNode_t* np   = NULL;  
440
+  unsigned           tick = 0;
292 441
 
293 442
   // allocate the 'measure' record
294 443
   cmXsMeas_t* meas = cmLhAllocZ(p->lhH,cmXsMeas_t,1);
295
-  const cmXmlNode_t* np;
296 444
 
297 445
   // get measure number
298 446
   if( cmXmlAttrUInt(mnp,"number", &meas->number) != kOkXmlRC )
@@ -305,30 +453,50 @@ cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t*
305 453
     cmXsMeas_t* m = pp->measL;
306 454
     while( m->link != NULL )
307 455
       m = m->link;
308
-    m->link = meas;
456
+    
457
+    m->link       = meas;
309 458
   }
310 459
   
311 460
   // get measure attributes node
312 461
   if((np = cmXmlSearch(mnp,"attributes",NULL,0)) == NULL)
313
-    return rc; // (this measure does not have any attributes)
462
+    return rc;                  // (this measure does not have any attributes)
463
+
314 464
 
315 465
   cmXmlNodeUInt(np,&meas->divisions,"divisions",NULL);
316
-  cmXmlNodeUInt(np,&meas->beats,"time","beats",NULL);
466
+  cmXmlNodeUInt(np,&meas->beats,    "time","beats",NULL);
317 467
   cmXmlNodeUInt(np,&meas->beat_type,"time","beat-type",NULL);
318 468
 
319
-  int tick = 0;
469
+  // store the bar line
470
+  if((rc = _cmXScorePushNonNote(p,meas,tick,0,0,kBarXsFl)) != kOkXsRC )
471
+    return rc;
472
+
320 473
   
321 474
   np = mnp->children;
322
-  for(; np!=NULL; np=np->sibling)
323
-    if( cmTextCmp(np->label,"note") )
475
+
476
+  // for each child of the 'meas' XML node
477
+  for(; rc==kOkXsRC && np!=NULL; np=np->sibling)
478
+  {
479
+    // if this is a 'note' node
480
+    if( cmTextCmp(np->label,"note") == 0 )
324 481
     {
325
-      rc = _cmXScoreParseNote(p,meas,mnp);
482
+      rc = _cmXScoreParseNote(p,meas,np,&tick);
326 483
     }
327 484
     else
328
-      if( cmTextCmp(np->label,"backup") )
485
+      // if this is a 'backup' node
486
+      if( cmTextCmp(np->label,"backup") == 0 )
329 487
       {
488
+        unsigned backup;
489
+        cmXmlNodeUInt(np,&backup,"duration",NULL);
490
+        tick -= backup;
330 491
       }
492
+      else
493
+        // if this is a 'direction' node
494
+        if( cmTextCmp(np->label,"direction") == 0 )
495
+        {
496
+          rc = _cmXScoreParseDirection(p,meas,np,tick);
497
+        }
331 498
   
499
+  }
332 500
   
333 501
   return rc;
334 502
 }
@@ -341,7 +509,7 @@ cmXsRC_t _cmXScoreParsePart( cmXScore_t* p, cmXsPart_t* pp )
341 509
   
342 510
   // find the 'part'
343 511
   if((xnp = cmXmlSearch( cmXmlRoot(p->xmlH), "part", &partAttr, 1)) == NULL )
344
-    return _cmXScoreMissingNode(p,"part",&partAttr);
512
+    return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The part '%s' was not found.",pp->idStr);
345 513
 
346 514
   // for each child of this part - find each measure
347 515
   const cmXmlNode_t* cnp = xnp->children;
@@ -353,6 +521,58 @@ cmXsRC_t _cmXScoreParsePart( cmXScore_t* p, cmXsPart_t* pp )
353 521
   return rc;
354 522
 }
355 523
 
524
+cmXsNote_t*  _cmXScoreInsertSortedNote( cmXsNote_t* s0, cmXsNote_t* np )
525
+{
526
+  if( s0 == NULL )
527
+    return np;
528
+
529
+  if( np->tick < s0->tick )
530
+  {
531
+    np->slink = s0;
532
+    return np;
533
+  }
534
+
535
+  cmXsNote_t* s1 = s0;
536
+  cmXsNote_t* s2 = s0->slink;
537
+
538
+  while( s2 != NULL )
539
+  {
540
+    if( s2->tick > np->tick )
541
+    {
542
+      s1->slink = np;
543
+      np->slink = s2;
544
+      return s0;
545
+    }
546
+    
547
+    s1 = s2;
548
+    s2 = s2->slink;
549
+  }
550
+
551
+  s1->slink = np;
552
+  
553
+  return s0;
554
+}
555
+
556
+void _cmXScoreSort( cmXScore_t* p )
557
+{
558
+  cmXsPart_t* pp = p->partL;
559
+  for(; pp!=NULL; pp=pp->link)
560
+  {
561
+    cmXsMeas_t* mp = pp->measL;
562
+    for(; mp!=NULL; mp=mp->link)
563
+    {   
564
+      // for each voice in this measure
565
+      cmXsVoice_t* vp = mp->voiceL;
566
+      for(; vp!=NULL; vp=vp->link)
567
+      {
568
+        cmXsNote_t* np = vp->noteL;
569
+        for(; np!=NULL; np=np->mlink)
570
+          mp->noteL = _cmXScoreInsertSortedNote(mp->noteL,np);        
571
+      }      
572
+    }
573
+  }
574
+}
575
+
356 576
 cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn )
357 577
 {
358 578
   cmXsRC_t rc = kOkXsRC;
@@ -379,11 +599,14 @@ cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn )
379 599
   if((rc = _cmXScoreParsePartList( p )) != kOkXsRC )
380 600
     goto errLabel;
381 601
 
602
+  // parse each score 'part'
382 603
   cmXsPart_t* pp = p->partL;
383 604
   for(; pp!=NULL; pp=pp->link)
384 605
     if((rc = _cmXScoreParsePart(p,pp)) != kOkXsRC )
385 606
       goto errLabel;
386 607
 
608
+  // fill in the note->slink chain to link the notes in each measure in time order
609
+  _cmXScoreSort(p); 
387 610
   
388 611
  errLabel:
389 612
   if( rc != kOkXsRC )
@@ -408,15 +631,37 @@ cmXsRC_t cmXScoreFinalize( cmXsH_t* hp )
408 631
 
409 632
   hp->h = NULL;
410 633
 
411
-  return rc;
412
-  
634
+  return rc;  
413 635
 }
414 636
 
415 637
 
416 638
 bool     cmXScoreIsValid( cmXsH_t h )
417 639
 { return h.h != NULL; }
418 640
 
419
-void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt )
641
+void _cmXScoreReportNote( cmRpt_t* rpt, const cmXsNote_t* note )
642
+{
643
+  const cmChar_t* B = cmIsFlag(note->flags,kBarXsFl)       ? "|" : "-";
644
+  const cmChar_t* R = cmIsFlag(note->flags,kRestXsFl)      ? "R" : "-";
645
+  const cmChar_t* G = cmIsFlag(note->flags,kGraceXsFl)     ? "G" : "-";
646
+  const cmChar_t* D = cmIsFlag(note->flags,kDotXsFl)       ? "D" : "-";
647
+  const cmChar_t* C = cmIsFlag(note->flags,kChordXsFl)     ? "C" : "-";
648
+  const cmChar_t* e = cmIsFlag(note->flags,kEvenXsFl)      ? "e" : "-";
649
+  const cmChar_t* d = cmIsFlag(note->flags,kDynXsFl)       ? "d" : "-";
650
+  const cmChar_t* t = cmIsFlag(note->flags,kTempoXsFl)     ? "t" : "-";
651
+  const cmChar_t* P = cmIsFlag(note->flags,kPedalDnXsFl)   ? "V" : "-";
652
+  P = cmIsFlag(note->flags,kPedalUpXsFl)   ? "^" : P;
653
+  P = cmIsFlag(note->flags,kPedalUpDnXsFl) ? "X" : P;
654
+  const cmChar_t* N = note->pitch==0 ? " " : cmMidiToSciPitch( note->pitch, NULL, 0 );
655
+  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);
656
+
657
+  if( cmIsFlag(note->flags,kSectionXsFl) )
658
+    cmRptPrintf(rpt," %i",note->rvalue);
659
+
660
+  printf("\n");
661
+  
662
+}
663
+
664
+void  cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
420 665
 {
421 666
   cmXScore_t* p = _cmXScoreHandleToPtr(h);
422 667
 
@@ -427,9 +672,31 @@ void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt )
427 672
 
428 673
     const cmXsMeas_t* meas = pp->measL;
429 674
     for(; meas!=NULL; meas=meas->link)
675
+    {
430 676
       cmRptPrintf(rpt,"  %i : div:%i beat:%i beat-type:%i\n",meas->number,meas->divisions,meas->beats,meas->beat_type);
431
-  }
432
-  
677
+
678
+      if( sortFl )
679
+      {
680
+        const cmXsNote_t* note = meas->noteL;
681
+        for(; note!=NULL; note=note->slink)
682
+          _cmXScoreReportNote(rpt,note);        
683
+      }
684
+      else
685
+      {
686
+      
687
+        const cmXsVoice_t* v = meas->voiceL;
688
+        for(; v!=NULL; v=v->link)
689
+        {        
690
+          const cmXsNote_t* note = v->noteL;
691
+          
692
+          cmRptPrintf(rpt,"    voice:%i\n",v->id);
693
+          
694
+          for(; note!=NULL; note=note->mlink)
695
+            _cmXScoreReportNote(rpt,note);
696
+        }
697
+      }      
698
+    }
699
+  }  
433 700
 }
434 701
 
435 702
 
@@ -441,7 +708,7 @@ cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
441 708
   if((rc = cmXScoreInitialize( ctx, &h, fn)) != kOkXsRC )
442 709
     return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
443 710
 
444
-  cmXScoreReport(h,&ctx->rpt);
711
+  cmXScoreReport(h,&ctx->rpt,true);
445 712
   
446 713
   return cmXScoreFinalize(&h);
447 714
 

+ 6
- 4
app/cmXScore.h Dosyayı Görüntüle

@@ -7,11 +7,11 @@ extern "C" {
7 7
 
8 8
   enum
9 9
   {
10
-  kOkXsRC = cmOkRC,
10
+    kOkXsRC = cmOkRC,
11 11
     kXmlFailXsRC,
12 12
     kLHeapFailXsRC,
13 13
     kSyntaxErrorXsRC
14
-    };
14
+  };
15 15
 
16 16
   typedef cmRC_t     cmXsRC_t;
17 17
   typedef cmHandle_t cmXsH_t;
@@ -25,14 +25,16 @@ extern "C" {
25 25
   //       b. Emacs C-x <RET> f utf-8 <RET>
26 26
   //
27 27
   // 2) Replace "DoletSibelius Unknown Symbol Index" with "DoletSibelius unknownSymIdx"
28
-  
28
+  //
29
+  // 3) How to assigned dynamic markings.
30
+  // 4) Tempo syntax is inconsistent.
29 31
 
30 32
   cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn );
31 33
   cmXsRC_t cmXScoreFinalize( cmXsH_t* hp );
32 34
 
33 35
   bool     cmXScoreIsValid( cmXsH_t h );
34 36
 
35
-  void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt );
37
+  void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl );
36 38
 
37 39
   cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
38 40
   

Loading…
İptal
Kaydet