016593ab72f10920f44bc25f1e167c2ef0d581b5
[minwii.git] / src / songs / musicxmltosong.py
1 """
2 converstion d'un fichier musicxml en objet song minwii.
3
4 $Id$
5 $URL$
6 """
7 import sys
8 from types import StringTypes
9 from xml.dom.minidom import parse
10 from optparse import OptionParser
11
12 # Do4 <=> midi 60
13 OCTAVE_REF = 4
14 DIATO_SCALE = {'C' : 60,
15 'D' : 62,
16 'E' : 64,
17 'F' : 65,
18 'G' : 67,
19 'A' : 69,
20 'B' : 71}
21 _marker = []
22
23
24 class Note(object) :
25 def __init__(self, node, divisions) :
26 self.name = _getNodeValue(node, 'pitch/step')
27 self.octave = int(_getNodeValue(node, 'pitch/octave'))
28 self._duration = float(_getNodeValue(node, 'duration'))
29 self.divisions = divisions
30
31 @property
32 def midi(self) :
33 mid = DIATO_SCALE[self.name]
34 mid = mid + (self.octave - OCTAVE_REF) * 12
35 return mid
36
37 @property
38 def duration(self) :
39 return self._duration / self.divisions
40
41
42
43 def _getNodeValue(node, path, default=_marker) :
44 try :
45 for name in path.split('/') :
46 node = node.getElementsByTagName(name)[0]
47 return node.firstChild.nodeValue
48 except :
49 if default is _marker :
50 raise
51 else :
52 return default
53
54 def musicXml2Song(input, output) :
55 if isinstance(input, StringTypes) :
56 input = open(input, 'r')
57
58 d = parse(input)
59 doc = d.documentElement
60
61 # TODO conversion préalable score-timewise -> score-partwise
62 assert doc.nodeName == u'score-partwise'
63
64 parts = doc.getElementsByTagName('part')
65 # on suppose que la première partie est le chant
66 leadPart = parts[0]
67
68 # divisions de la noire
69 divisions = 0
70 for measureNode in leadPart.getElementsByTagName('measure') :
71 divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
72 for noteNode in measureNode.getElementsByTagName('note') :
73 note = Note(noteNode, divisions)
74 print note.name, note.octave, note.midi, note.duration
75
76
77 def main() :
78 usage = "%prog musicXmlFile.xml outputSongFile.smwi [options]"
79 op = OptionParser(usage)
80
81 options, args = op.parse_args()
82 if len(args) != 2 :
83 raise SystemExit(op.format_help())
84
85 musicXml2Song(*args)
86
87
88
89 if __name__ == '__main__' :
90 sys.exit(main())