prise en charge des notes prolongées (<tied/>).
git-svn-id: https://svn.cri.ensmp.fr/svn/minwii/trunk@88
fe552daf-6dbe-4428-90eb-
1537e0879342
#app.run(home)
#app.close(home)
#app.run(home)
#app.close(home)
- song = musicXml2Song('/Users/pinbe/dev/minwii/src/songs/chansons/quinquin.xml')
+ song = musicXml2Song('/Users/pinbe/dev/minwii/src/songs/chansons/etoile_neige.xml', printNotes=True)
playingScreen = SongPlayingScreen(synth, song)
#playingScreen = PlayingScreen(synth)
playingScreen.run()
playingScreen = SongPlayingScreen(synth, song)
#playingScreen = PlayingScreen(synth)
playingScreen.run()
divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
for noteNode in measureNode.getElementsByTagName('note') :
note = Note(noteNode, divisions, previous)
divisions = int(_getNodeValue(measureNode, 'attributes/divisions', divisions))
for noteNode in measureNode.getElementsByTagName('note') :
note = Note(noteNode, divisions, previous)
+ if (not note.isRest) and (not note.tiedStop) :
measureNotes.append(note)
if previous :
previous.next = note
measureNotes.append(note)
if previous :
previous.next = note
+ elif note.tiedStop :
+ assert previous.tiedStart
+ previous.addDuration(note)
+ continue
else :
previous.addDuration(note)
continue
else :
previous.addDuration(note)
continue
elif start is not None and ll > 1 :
stop = i
break
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"
def _findVersesLoops(self) :
"recherche des couplets / boucles"
def __init__(self, node, divisions, previous) :
self.node = node
self.isRest = False
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'))
self.step = _getNodeValue(node, 'pitch/step', None)
if self.step is not None :
self.octave = int(_getNodeValue(node, 'pitch/octave'))
class Lyric(object) :
_syllabicModifiers = {
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) :
}
def __init__(self, node) :
self.syllabic = _getNodeValue(node, 'syllabic', 'single')
self.text = _getNodeValue(node, 'text')
self.syllabic = _getNodeValue(node, 'syllabic', 'single')
self.text = _getNodeValue(node, 'text')
- def syllabus(self, encoding='utf-8'):
text = self._syllabicModifiers[self.syllabic] % self.text
text = self._syllabicModifiers[self.syllabic] % self.text
- return text.encode(encoding)
+ return self.syllabus().encode('utf-8')
-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')
if isinstance(input, StringTypes) :
input = open(input, 'r')
parts = doc.getElementsByTagName('part')
leadPart = parts[partIndex]
parts = doc.getElementsByTagName('part')
leadPart = parts[partIndex]
+ part = Part(leadPart, autoDetectChorus=autoDetectChorus)
if printNotes :
part.pprint()
if printNotes :
part.pprint()
op.add_option("-i", "--part-index", dest="partIndex"
, default = 0
, help = "Index de la partie qui contient le champ.")
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("-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())
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__' :
if __name__ == '__main__' :
if self.currentColumn:
self.currentColumn.update(False)
note, verseIndex = self.noteIterator.next()
if self.currentColumn:
self.currentColumn.update(False)
note, verseIndex = self.noteIterator.next()
- syllabus = note.lyrics[verseIndex].syllabus(encoding="iso-8859-1")
+ syllabus = note.lyrics[verseIndex].syllabus()
column = self.columns[note.midi]
column.update(True, syllabus)
self.currentColumn = column
column = self.columns[note.midi]
column.update(True, syllabus)
self.currentColumn = column
$URL$
"""
import fluidsynth
$URL$
"""
import fluidsynth
-from musicxmltosong import musicXml2Song
+from app.musicxml import musicXml2Song
from time import sleep
import sys
from optparse import OptionParser
from time import sleep
import sys
from optparse import OptionParser
def play(self) :
fs = self.fs
for note, verseIndex in self.part.iterNotes(indefinitely=False) :
def play(self) :
fs = self.fs
for note, verseIndex in self.part.iterNotes(indefinitely=False) :
- print note, note.lyrics[verseIndex]
+ try :
+ print note, note.lyrics[verseIndex]
+ except IndexError :
+ print note, '?'
fs.noteon(0, note.midi, 64)
duration = note.duration * self.quarterNoteDuration / 1000
sleep(duration)
fs.noteon(0, note.midi, 64)
duration = note.duration * self.quarterNoteDuration / 1000
sleep(duration)
op.add_option("-i", "--part-index", dest="partIndex"
, default = 0
, help = "Index de la partie qui contient le champ.")
op.add_option("-i", "--part-index", dest="partIndex"
, default = 0
, help = "Index de la partie qui contient le champ.")
+
+ op.add_option("-c", '--no-chorus', dest='autoDetectChorus'
+ , action="store_false"
+ , default = True
+ , help = "désactive la détection du refrain")
+
op.add_option("-q", "--quarter-note-duration", dest="quarterNoteDuration"
, type="int", default=400
, help="Durée de la noire [default] (en millisecondes)"
)
op.add_option("-q", "--quarter-note-duration", dest="quarterNoteDuration"
, type="int", default=400
, help="Durée de la noire [default] (en millisecondes)"
)
op.add_option("-b", "--bank", dest="bank"
, type="int", default="0"
, help="midi bank [default]")
op.add_option("-b", "--bank", dest="bank"
, type="int", default="0"
, help="midi bank [default]")
op.add_option("-p", "--preset", dest="preset"
, type="int", default="0"
, help="midi preset [default]")
op.add_option("-p", "--preset", dest="preset"
, type="int", default="0"
, help="midi preset [default]")
if len(args) != 1 :
raise SystemExit(op.format_help())
if len(args) != 1 :
raise SystemExit(op.format_help())
- song = musicXml2Song(args[0], partIndex=options.partIndex)
+ song = musicXml2Song(args[0],
+ partIndex=options.partIndex,
+ autoDetectChorus=options.autoDetectChorus)
sp = SongPlayer(song,
'/Users/pinbe/dev/minwii/fluid-soundfont-3.1/FluidR3_GM.sf2',
quarterNoteDuration=options.quarterNoteDuration,
sp = SongPlayer(song,
'/Users/pinbe/dev/minwii/fluid-soundfont-3.1/FluidR3_GM.sf2',
quarterNoteDuration=options.quarterNoteDuration,