X-Git-Url: https://scm.cri.mines-paristech.fr/git/minwii.git/blobdiff_plain/55fc862ddb0c20e92bbd88621f92525131b5b215..2f28e378d5a9cc0f85d15c91f75711db48d91cee:/src/app/musicxml.py diff --git a/src/app/musicxml.py b/src/app/musicxml.py index 36a65bc..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')) @@ -280,37 +297,10 @@ class Note(Tone) : self._duration = self.duration + note.duration self.divisions = 1 -# @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 -# -# @property -# def nom(self) : -# name = FR_NOTES[self.step] -# if self.alter < 0 : -# alterext = 'b' -# else : -# alterext = '#' -# name = '%s%s' % (name, abs(self.alter) * alterext) -# return name - @property def column(self): return self.scale.index(self.midi) @@ -319,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) : @@ -330,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__ @@ -352,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') @@ -365,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() @@ -380,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__' :