浏览代码

cmXScore.c : Updates to parse 'note' nodes.

master
kevin 8 年前
父节点
当前提交
3babaf428a
共有 1 个文件被更改,包括 173 次插入1 次删除
  1. 173
    1
      app/cmXScore.c

+ 173
- 1
app/cmXScore.c 查看文件

@@ -10,11 +10,27 @@
10 10
 #include "cmXml.h"
11 11
 #include "cmText.h"
12 12
 #include "cmXScore.h"
13
+#include "cmTime.h"
14
+#include "cmMidi.h"
13 15
 
14 16
 cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
15 17
 
18
+enum
19
+{
20
+  kRestXsFl    = 0x0001,
21
+  kGraceXsFl   = 0x0002,
22
+  kDotXsFl     = 0x0004
23
+};
24
+
25
+
16 26
 typedef struct cmXsNote_str
17 27
 {
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
+  
18 34
 } cmXsNote_t;
19 35
 
20 36
 typedef struct cmXsVoice_str
@@ -128,11 +144,153 @@ cmXsRC_t _cmXScoreParsePartList( cmXScore_t* p )
128 144
   return rc;
129 145
 }
130 146
 
147
+cmXsRC_t  _cmXScoreParsePitch( cmXScore_t* p, const cmXmlNode_t* nnp, unsigned* midiPitchRef )
148
+{
149
+  cmXsRC_t        rc     = kOkXsRC;
150
+  unsigned        octave = 0;
151
+  double          alter  = 0;
152
+  const cmChar_t* step   = NULL;
153
+
154
+  if((step = cmXmlNodeValue(nnp,"pitch","step",NULL)) == NULL )
155
+    return _cmXScoreMissingNode(p,"step",NULL);
156
+  
157
+  if((rc = cmXmlNodeUInt( nnp,&octave,"pitch","octave",NULL)) != kOkXmlRC )
158
+    return _cmXScoreMissingNode(p,"octave",NULL);
159
+  
160
+  cmXmlNodeDouble( nnp,&alter,"pitch","alter",NULL);
161
+
162
+  cmChar_t buf[3] = { *step, '0', '\0'};
163
+  unsigned midi = cmSciPitchToMidi(buf);
164
+
165
+  midi         += (12 * octave);
166
+
167
+  midi         += alter;
168
+
169
+  *midiPitchRef = midi;
170
+
171
+  return rc;  
172
+}
173
+
174
+unsigned _cmXScoreParseNoteType( const cmXmlNode_t* nnp )
175
+{
176
+  typedef struct map_str
177
+  {
178
+    unsigned        rvalue;
179
+    const cmChar_t* label;
180
+  } map_t;
181
+
182
+  map_t mapV[] =
183
+  {
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,""}
193
+  };
194
+
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
+
208
+  return 0;
209
+}
210
+
211
+cmXsVoice_t* _cmXScoreIdToVoice( cmXsMeas_t* meas, unsigned voiceId )
212
+{
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
+}
220
+
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)
225
+  {
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
+  }
240
+
241
+  if( v->noteL == NULL )
242
+    v->noteL = note;
243
+  else
244
+  {
245
+    cmXsNote_t* n = v->noteL;
246
+    while( n != NULL )
247
+      n = n->link;
248
+
249
+    n->link = note;
250
+  }
251
+
252
+  return kOkXsRC;
253
+}
254
+
255
+cmXsRC_t _cmXScoreParseNote(cmXScore_t* p, cmXsMeas_t* meas, const cmXmlNode_t* nnp)
256
+{
257
+  cmXsRC_t    rc   = kOkXsRC;
258
+  
259
+  cmXsNote_t* note = cmLhAllocZ(p->lhH,cmXsNote_t,1);
260
+  unsigned voiceId;
261
+
262
+  // get the voice id for this node
263
+  if( cmXmlNodeUInt(nnp,&voiceId,"voice",NULL) != kOkXmlRC )
264
+    return _cmXScoreMissingNode(p,"voice",NULL);
265
+
266
+  
267
+  // if this note has a pitch
268
+  if( cmXmlNodeHasChild(nnp,"pitch") )
269
+    if((rc = _cmXScoreParsePitch(p,nnp,&note->pitch)) != kOkXsRC )
270
+      return rc;
271
+
272
+  // is 'rest'
273
+  if( cmXmlNodeHasChild(nnp,"rest") )
274
+    note->flags |= kRestXsFl;
275
+
276
+  // is 'grace'
277
+  if( cmXmlNodeHasChild(nnp,"grace") )
278
+    note->flags |= kGraceXsFl;
279
+
280
+  // is 'dot'
281
+  if( cmXmlNodeHasChild(nnp,"dot") )
282
+    note->flags |= kDotXsFl;
283
+
284
+  if((note->rvalue =  _cmXScoreParseNoteType(nnp)) == 0 )
285
+    return _cmXScoreMissingNode(nnp,"type",NULL);
286
+    
287
+}
131 288
 
132
-cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t* mnp )
289
+cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t* mnp)
133 290
 {
134 291
   cmXsRC_t rc = kOkXsRC;
135 292
 
293
+  // allocate the 'measure' record
136 294
   cmXsMeas_t* meas = cmLhAllocZ(p->lhH,cmXsMeas_t,1);
137 295
   const cmXmlNode_t* np;
138 296
 
@@ -157,6 +315,20 @@ cmXsRC_t _cmXScoreParseMeasure(cmXScore_t* p, cmXsPart_t* pp, const cmXmlNode_t*
157 315
   cmXmlNodeUInt(np,&meas->divisions,"divisions",NULL);
158 316
   cmXmlNodeUInt(np,&meas->beats,"time","beats",NULL);
159 317
   cmXmlNodeUInt(np,&meas->beat_type,"time","beat-type",NULL);
318
+
319
+  int tick = 0;
320
+  
321
+  np = mnp->children;
322
+  for(; np!=NULL; np=np->sibling)
323
+    if( cmTextCmp(np->label,"note") )
324
+    {
325
+      rc = _cmXScoreParseNote(p,meas,mnp);
326
+    }
327
+    else
328
+      if( cmTextCmp(np->label,"backup") )
329
+      {
330
+      }
331
+  
160 332
   
161 333
   return rc;
162 334
 }

正在加载...
取消
保存