X-Git-Url: https://scm.cri.mines-paristech.fr/git/minwii.git/blobdiff_plain/1bdf29a0b4412135ee91f6165e3c3125e05096f8..ca8b7eef543b27ef0c8928494a6e138d0f938aa1:/src/app/musicxml.py?ds=sidebyside diff --git a/src/app/musicxml.py b/src/app/musicxml.py index 49e1984..ab6dbf9 100755 --- a/src/app/musicxml.py +++ b/src/app/musicxml.py @@ -73,10 +73,14 @@ class Part(object) : divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions)) for noteNode in measureNode.getElementsByTagName('note') : note = Note(noteNode, divisions, previous) - if not note.isRest : + if (not note.isRest) and (not note.tiedStop) : measureNotes.append(note) if previous : previous.next = note + elif note.tiedStop : + assert previous.tiedStart + previous.addDuration(note) + continue else : previous.addDuration(note) continue @@ -114,7 +118,10 @@ class Part(object) : elif start is not None and ll > 1 : stop = i break - self.chorus = self.notes[start:stop] + if not (start or stop) : + self.chorus = [] + else : + self.chorus = self.notes[start:stop] def _findVersesLoops(self) : "recherche des couplets / boucles" @@ -252,6 +259,16 @@ class Note(Tone) : def __init__(self, node, divisions, previous) : self.node = node self.isRest = False + self.tiedStart = False + self.tiedStop = False + + tieds = _getElementsByPath(node, 'notations/tied', []) + for tied in tieds : + if tied.getAttribute('type') == 'start' : + self.tiedStart = True + elif tied.getAttribute('type') == 'stop' : + self.tiedStop = True + self.step = _getNodeValue(node, 'pitch/step', None) if self.step is not None : self.octave = int(_getNodeValue(node, 'pitch/octave')) @@ -292,10 +309,10 @@ class Note(Tone) : class Lyric(object) : _syllabicModifiers = { - 'single' : '%s', - 'begin' : '%s -', - 'middle' : '- %s -', - 'end' : '- %s' + 'single' : u'%s', + 'begin' : u'%s -', + 'middle' : u'- %s -', + 'end' : u'- %s' } def __init__(self, node) : @@ -303,12 +320,12 @@ class Lyric(object) : self.syllabic = _getNodeValue(node, 'syllabic', 'single') self.text = _getNodeValue(node, 'text') - def syllabus(self, encoding='utf-8'): + def syllabus(self): text = self._syllabicModifiers[self.syllabic] % self.text - return text.encode(encoding) + return text def __str__(self) : - return self.syllabus() + return self.syllabus().encode('utf-8') __repr__ = __str__ @@ -325,7 +342,19 @@ def _getNodeValue(node, path, default=_marker) : else : return default -def musicXml2Song(input, partIndex=0, printNotes=False) : +def _getElementsByPath(node, path, default=_marker) : + try : + parts = path.split('/') + for name in parts[:-1] : + node = node.getElementsByTagName(name)[0] + return node.getElementsByTagName(parts[-1]) + except IndexError : + if default is _marker : + raise + else : + return default + +def musicXml2Song(input, partIndex=0, autoDetectChorus=True, printNotes=False) : if isinstance(input, StringTypes) : input = open(input, 'r') @@ -338,7 +367,7 @@ def musicXml2Song(input, partIndex=0, printNotes=False) : parts = doc.getElementsByTagName('part') leadPart = parts[partIndex] - part = Part(leadPart) + part = Part(leadPart, autoDetectChorus=autoDetectChorus) if printNotes : part.pprint() @@ -353,18 +382,27 @@ def main() : 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)") + + op.add_option("-c", '--no-chorus', dest='autoDetectChorus' + , action="store_false" + , default = True + , help = "désactive la détection du refrain") + options, args = op.parse_args() if len(args) != 1 : raise SystemExit(op.format_help()) - musicXml2Song(args[0], partIndex=options.partIndex, printNotes=options.printNotes) - + musicXml2Song(args[0], + partIndex=options.partIndex, + autoDetectChorus=options.autoDetectChorus, + printNotes=options.printNotes) if __name__ == '__main__' :