%load_ext music21.ipython21.ipExtension
from music21 import *
def getTransposeAmount(position):
    if position == 0:
        return 0
    transposeList = [None, 1, 1, -1, None, 1, -1, -1]
    transposeAmount = transposeList[position % 8]
    if transposeAmount is None:
        return getTransposeAmount(position / 4)
    else:
        return transposeAmount
def getNoteNameFromTransposition(transpose):
    noteList = ['C','D#','E','G','A-','B'] # A2, m2, m3, m2, A2 ...
    octave = 4 + transpose/6
    noteName = noteList[transpose % 6] + str(octave)
    return noteName

def getNoteFromTransposition(transpose):
    noteName = getNoteNameFromTransposition(transpose)
    noteObj = note.Note(noteName, type ='16th')
    if noteObj.name == 'B':
        noteObj.accidental = pitch.Accidental('natural')
        noteObj.accidental.displayType = 'always'
    return noteObj
def getNotesForLength(totalNotes, appendStream = None):
    currentNoteType = 0
    if appendStream is None:
        retStream = stream.Part()
        retStream.insert(0, meter.TimeSignature('2/4'))
    else:
        retStream = appendStream

    firstNoteIndex = len(retStream)
    for i in range(1, totalNotes+1):
        noteObj = getNoteFromTransposition(currentNoteType)
        retStream._appendCore(noteObj)
        currentNoteType += getTransposeAmount(i)

    retStream._elementsChanged()
    if totalNotes == 1:
        retStream[-1].duration.type = 'half'
    elif totalNotes == 3:
        retStream[-1].duration.quarterLength = 1.5
    else:
        retStream[-1].duration.type = 'eighth'
    retStream[firstNoteIndex].addLyric(str(totalNotes))

    return retStream
s = getNotesForLength(31)
s.show()
../_images/MersenneDemo_5_0.png
def makeMersenneMelody(maxPowerOfTwo):
    retStream = stream.Part()
    retStream.insert(0, meter.TimeSignature('2/4'))
    for i in range(1, maxPowerOfTwo):
        retStream.repeatAppend(note.Rest(type='half'), 3)
        totalNotes = (2**i)-1
        getNotesForLength(totalNotes, retStream)
    for i in range(maxPowerOfTwo, 0, -1):
        retStream.repeatAppend(note.Rest(type='half'), 3)
        totalNotes = (2**i)-1
        getNotesForLength(totalNotes, retStream)
    retStream.repeatAppend(note.Rest(type='half'), 3)
    return retStream
s2 = makeMersenneMelody(4)
s2.show()
../_images/MersenneDemo_8_0.png
def makeMersenneScore(maxPowerOfTwo):
    p1 = makeMersenneMelody(maxPowerOfTwo)
    p2 = stream.Part()
    p2.insert(0, clef.BassClef())
    p2.insert(0, meter.TimeSignature('2/4'))
    p1Measures = p1.duration.quarterLength / 2
    for i in range(0, int(p1Measures)):
        p2._appendCore(note.Note('E2', type='eighth'))
        p2._appendCore(note.Note('B2', type='eighth'))
        p2._appendCore(note.Note('E3', type='eighth'))
        p2._appendCore(note.Note('B2', type='eighth'))
    p2._elementsChanged()
    s = stream.Score()
    s.insert(0, p1)
    s.insert(0, p2)
    return s
s3 = makeMersenneScore(9)
s3.show()
../_images/MersenneDemo_11_0.png
s3.show('midi')