X-Git-Url: https://svn.cri.ensmp.fr/git/minwii.git/blobdiff_plain/e5335f94e64a4a312512be3953a212a5593c18ba..5f7bb1f72565a54cf49b2b3b39f13cc2bbabc112:/src/songs/musicxmltosong.py?ds=sidebyside diff --git a/src/songs/musicxmltosong.py b/src/songs/musicxmltosong.py index ffb5247..d24d81a 100755 --- a/src/songs/musicxmltosong.py +++ b/src/songs/musicxmltosong.py @@ -9,7 +9,8 @@ import sys from types import StringTypes from xml.dom.minidom import parse from optparse import OptionParser -from Song import Song +from itertools import cycle +#from Song import Song # Do4 <=> midi 60 OCTAVE_REF = 4 @@ -20,18 +21,191 @@ DIATO_SCALE = {'C' : 60, 'G' : 67, 'A' : 69, 'B' : 71} + +FR_NOTES = {'C' : u'Do', + 'D' : u'Ré', + 'E' : u'Mi', + 'F' : u'Fa', + 'G' : u'Sol', + 'A' : u'La', + 'B' : u'Si'} + _marker = [] +class Part(object) : + + requiresExtendedScale = False + scale = [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72] + quarterNoteLength = 400 + + def __init__(self, node, autoDetectChorus=True) : + self.node = node + self.notes = [] + self.repeats = [] + self._parseMusic() + self.verses = [[]] + self.chorus = [] + if autoDetectChorus : + self._findChorus() + self._findVersesLoops() + + def _parseMusic(self) : + divisions = 0 + previous = None + + for measureNode in self.node.getElementsByTagName('measure') : + measureNotes = [] + + # iteration sur les notes + # divisions de la noire + divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions)) + for noteNode in measureNode.getElementsByTagName('note') : + note = Note(noteNode, divisions, previous) + if not note.isRest : + measureNotes.append(note) + if previous : + previous.next = note + else : + previous.addDuration(note) + continue + previous = note + self.notes.extend(measureNotes) + + # barres de reprises + try : + barlineNode = measureNode.getElementsByTagName('barline')[0] + except IndexError : + continue + + barline = Barline(barlineNode, measureNotes) + if barline.repeat : + self.repeats.append(barline) + + def _findChorus(self): + """ le refrain correspond aux notes pour lesquelles + il n'existe q'une seule syllable attachée. + """ + start = stop = None + for i, note in enumerate(self.notes) : + ll = len(note.lyrics) + if start is None and ll == 1 : + start = i + elif start is not None and ll > 1 : + stop = i + break + self.chorus = self.notes[start:stop] + + def _findVersesLoops(self) : + "recherche des couplets / boucles" + verse = self.verses[0] + for note in self.notes[:-1] : + verse.append(note) + ll = len(note.lyrics) + nll = len(note.next.lyrics) + if ll != nll : + verse = [] + self.verses.append(verse) + verse.append(self.notes[-1]) + + + def iterNotes(self) : + "exécution de la chanson avec l'alternance couplets / refrains" + for verse in cycle(self.verses) : + print "---partie---" + repeats = len(verse[0].lyrics) + if repeats > 1 : + for i in range(repeats) : + # couplet + print "---couplet%d---" % i + for note in verse : + yield note, i + # refrain + print "---refrain---" + for note in self.chorus : + yield note, 0 + else : + for note in verse : + yield note, 0 + + def pprint(self) : + for note, verseIndex in self.iterNotes() : + print note, note.lyrics[verseIndex] + + + def assignNotesFromMidiNoteNumbers(self): + # TODO faire le mapping bande hauteur midi + for i in range(len(self.midiNoteNumbers)): + noteInExtendedScale = 0 + while self.midiNoteNumbers[i] > self.scale[noteInExtendedScale] and noteInExtendedScale < len(self.scale)-1: + noteInExtendedScale += 1 + if self.midiNoteNumbers[i]