+# -*- coding: utf-8 -*-
"""
converstion d'un fichier musicxml en objet song minwii.
$Id$
$URL$
"""
+import sys
+from types import StringTypes
+from xml.dom.minidom import parse
+from optparse import OptionParser
+from Song import Song
+# Do4 <=> midi 60
+OCTAVE_REF = 4
+DIATO_SCALE = {'C' : 60,
+ 'D' : 62,
+ 'E' : 64,
+ 'F' : 65,
+ 'G' : 67,
+ 'A' : 69,
+ 'B' : 71}
+_marker = []
+
+class Note(object) :
+ def __init__(self, node, divisions) :
+ self.step = _getNodeValue(node, 'pitch/step')
+ self.octave = int(_getNodeValue(node, 'pitch/octave'))
+ self.alter = int(_getNodeValue(node, 'pitch/alter', 0))
+ self._duration = float(_getNodeValue(node, 'duration'))
+ self.lyric = _getNodeValue(node, 'lyric/text', '')
+
+ self.divisions = divisions
+
+ @property
+ def midi(self) :
+ mid = DIATO_SCALE[self.step]
+ mid = mid + (self.octave - OCTAVE_REF) * 12
+ mid = mid + self.alter
+ return mid
+
+ @property
+ def duration(self) :
+ return self._duration / self.divisions
+
+ @property
+ def name(self) :
+ name = '%s%d' % (self.step, self.octave)
+ if self.alter < 0 :
+ alterext = 'b'
+ else :
+ alterext = '#'
+ name = '%s%s' % (name, abs(self.alter) * alterext)
+ return name
+
+
+
+
+def _getNodeValue(node, path, default=_marker) :
+ try :
+ for name in path.split('/') :
+ node = node.getElementsByTagName(name)[0]
+ return node.firstChild.nodeValue
+ except :
+ if default is _marker :
+ raise
+ else :
+ return default
+
+def musicXml2Song(input, output, partIndex=0, printNotes=False) :
+ if isinstance(input, StringTypes) :
+ input = open(input, 'r')
+
+ d = parse(input)
+ doc = d.documentElement
+
+ # TODO conversion préalable score-timewise -> score-partwise
+ assert doc.nodeName == u'score-partwise'
+
+ parts = doc.getElementsByTagName('part')
+ leadPart = parts[partIndex]
+
+ # divisions de la noire
+ divisions = 0
+ midiNotes, durations, lyrics = [], [], []
+
+ for measureNode in leadPart.getElementsByTagName('measure') :
+ divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
+ for noteNode in measureNode.getElementsByTagName('note') :
+ note = Note(noteNode, divisions)
+ if printNotes :
+ print note.name, note.midi, note.duration, note.lyric
+ midiNotes.append(note.midi)
+ durations.append(note.duration)
+ lyrics.append(note.lyric)
+
+ song = Song(None,
+ midiNoteNumbers = midiNotes,
+ noteLengths = durations,
+ lyrics = lyrics,
+ notesInExtendedScale=None)
+ song.save(output)
+
+
def main() :
- pass
+ usage = "%prog musicXmlFile.xml outputSongFile.smwi [options]"
+ op = OptionParser(usage)
+ op.add_option("-i", "--part-index", dest="partIndex"
+ , default = 0
+ , help = "Index de la partie qui contient le champ.")
+ op.add_option("-p", '--print', dest='printNotes'
+ , action="store_true"
+ , default = False
+ , help = "Affiche les notes sur la sortie standard (debug)")
+
+ options, args = op.parse_args()
+
+ if len(args) != 2 :
+ raise SystemExit(op.format_help())
+
+ musicXml2Song(args[0], args[1], partIndex=options.partIndex, printNotes=options.printNotes)
+
if __name__ == '__main__' :
- main()
\ No newline at end of file
+ sys.exit(main())