exécution de la chanson avec alternance couplets / refrains.
[minwii.git] / src / songs / musicxmltosong.py
index 25822b3..00903a1 100755 (executable)
@@ -24,31 +24,79 @@ _marker = []
 
 class Part(object) :
     
 
 class Part(object) :
     
-    def __init__(self, node) :
+    def __init__(self, node, autoDetectChorus=True) :
         self.node = node
         self.notes = []
         self._parseMusic()
         self.node = node
         self.notes = []
         self._parseMusic()
+        self.verses = [[]]
+        self.chorus = []
+        if autoDetectChorus :
+            self._findChorus()
+        self._findVersesLoops()
     
     def _parseMusic(self) :
         divisions = 0
     
     def _parseMusic(self) :
         divisions = 0
-        
+        noteIndex = 0
+        next = previous = None
         for measureNode in self.node.getElementsByTagName('measure') :
         for measureNode in self.node.getElementsByTagName('measure') :
+            # divisions de la noire
             divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
             divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
-            next = previous = None
-            for i, noteNode in enumerate(measureNode.getElementsByTagName('note')) :
+            for noteNode in measureNode.getElementsByTagName('note') :
                 note = Note(noteNode, divisions, previous)
                 self.notes.append(note)
                 try :
                 note = Note(noteNode, divisions, previous)
                 self.notes.append(note)
                 try :
-                    self.notes[i-1].next = note
+                    self.notes[noteIndex-1].next = note
                 except IndexError:
                     pass
                 previous = note
                 except IndexError:
                     pass
                 previous = note
+                noteIndex += 1
+
+    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 self.verses :
+            repeats = len(verse[0].lyrics)
+            if repeats > 1 :
+                for i in range(repeats) :
+                    # couplet
+                    for note in verse :
+                        yield note, i
+                    # refrain
+                    for note in self.chorus :
+                        yield note, 0
+            else :
+                for note in verse :
+                    yield note, 0
+        
     def pprint(self) :
     def pprint(self) :
-        for note in self.notes :
-            print note.name, note.midi, note.duration, note.lyrics
-                
-                
+        for note, verseIndex in self.iterNotes() :
+            print note.name, note.midi, note.duration, note.lyrics[verseIndex]