Saturday, December 26, 2009

How high do your singers need to sing to do this piece?

Here's one way of figuring it out:

(see the original blog post if your reposting turns this code into goobley-gook...)

import copy
import music21
from music21 import corpus, meter, stream

score = corpus.parseWork('bach/bwv366')
ts = score.flat.getElementsByClass(meter.TimeSignature)[0]
ts.beat.partition(3)

found = stream.Stream()
for part in score:
found.append(part.flat.getElementsByClass(music21.clef.Clef)[0])
highestNoteNum = 0
for m in part.measures:
for n in m.notes:
if n.midi > highestNoteNum:
highestNoteNum = n.midi
highestNote = copy.deepcopy(n) # optional

# These two lines will keep the look of the original
# note values but make each note 1 4/4 measure long:
highestNote.duration.components[0].unlink()
highestNote.quarterLength = 4

highestNote.lyric = '%s: M. %s: beat %s' % (
part.getInstrument().partName[0],
m.measureNumber, ts.getBeat(n.offset))
found.append(highestNote)

found.show()


... which generates this snippet of notation...



...showing that for at least one piece, Bach was (probably accidentally) using the old medieval authentic, plagal, lower-octave-authentic, lower-octave-plagal, range designations!

This code is still needlessly complicated -- we're still working on simplifying it (notes will know their own clefs and beats; '3/4' will know that it should be divided into 1+1+1), but just a little taste of what's possible.

Oh, and just for fun, all the C#s in the piece with this code snippet substitution:. Or discover that all the raised leading tones in this d-minor composition happen on the two strongest beat of a measure:


if n.name == 'C#':
...
found.append(n)


No comments:

Post a Comment