Browse Source

Added simple sequencer

This sequencer only does one-second-long intervals and doesn't try to time it exactly.
master
Macoy Madson 6 years ago
parent
commit
3605b560bb
  1. 129
      sequencer.py

129
sequencer.py

@ -6,6 +6,7 @@ mido.get_input_names()
mido.get_output_names()
"""
def testOutput():
outputs = mido.get_output_names()
lmmsOutPort = None
@ -17,20 +18,120 @@ def testOutput():
return
with mido.open_output(lmmsOutPort) as lmmsOut:
for i in range(1, 10):
song = [100, 80, 40, 80, 100]
for note in song:
testNote = mido.Message('note_on', note=note, velocity=127, time=0.1)
lmmsOut.send(testNote)
testNote = mido.Message('note_on', note=20, velocity=127, time=0.1)
lmmsOut.send(testNote)
time.sleep(0.1)
testNote = mido.Message('note_off', note=note, velocity=127, time=0.2)
lmmsOut.send(testNote)
testNote = mido.Message('note_off', note=20, velocity=127, time=0.2)
lmmsOut.send(testNote)
time.sleep(0.1)
for i in range(1, 10):
song = [100, 80, 40, 80, 100]
for note in song:
testNote = mido.Message(
'note_on', note=note, velocity=127, time=0.1)
lmmsOut.send(testNote)
testNote = mido.Message(
'note_on', note=20, velocity=127, time=0.1)
lmmsOut.send(testNote)
time.sleep(0.1)
testNote = mido.Message('note_off', note=note,
velocity=127, time=0.2)
lmmsOut.send(testNote)
testNote = mido.Message(
'note_off', note=20, velocity=127, time=0.2)
lmmsOut.send(testNote)
time.sleep(0.1)
def chooseDevice(devices, searchString):
matchingDevice = None
for device in devices:
if searchString.lower() in device.lower():
matchingDevice = device
return matchingDevice
def testIO():
#synthOutPort = chooseDevice(mido.get_output_names(), 'LMMS')
synthOutPort = chooseDevice(mido.get_output_names(), 'OP-1')
keyboardInPort = chooseDevice(mido.get_input_names(), 'CH345')
if not synthOutPort or not keyboardInPort:
return
with mido.open_output(synthOutPort) as synthOut:
with mido.open_input(keyboardInPort) as keyboardIn:
while True:
message = keyboardIn.receive()
print(message)
synthOut.send(message)
def simpleSequencer():
#synthOutPort = chooseDevice(mido.get_output_names(), 'LMMS')
synthOutPort = chooseDevice(mido.get_output_names(), 'OP-1')
keyboardInPort = chooseDevice(mido.get_input_names(), 'CH345')
if not synthOutPort or not keyboardInPort:
return
with mido.open_output(synthOutPort) as synthOut, mido.open_input(keyboardInPort) as keyboardIn:
# 16th notes at 240 bpm should be fine
frameRate = (60 / 240) / 4
# Prevent the program from locking up if the frame rate gets too bad
maximumCatchupTime = 0.25
timeRoomForError = 0.0001
sequence = []
sequenceLastStartTime = 0.0
sequenceTimeLength = 1.0
sequenceLastNotePlayedTime = 0.0
lastTime = time.time()
timeAccumulated = 0.0
try:
while True:
currentTime = time.time()
sequenceTime = currentTime - sequenceLastStartTime
frameDelta = currentTime - lastTime
if frameDelta > maximumCatchupTime:
frameDelta = maximumCatchupTime
lastTime = currentTime
timeAccumulated += frameDelta
print(frameDelta)
while timeAccumulated >= frameRate:
print('Updated')
# Poll input
message = keyboardIn.poll()
while message:
print(message)
sequence.append((message, sequenceTime))
synthOut.send(message)
message = keyboardIn.poll()
# Play sequencer notes if it's time
# TODO: sort notes by time
for note in sequence:
# TODO: this comparison should have a margin of error equal
# to the frame rate
if note[1] <= sequenceTime and note[1] >= sequenceLastNotePlayedTime:
synthOut.send(note[0])
sequenceLastNotePlayedTime = max(sequenceLastNotePlayedTime, note[1])
# Restart sequence if necessary
if sequenceTime >= sequenceTimeLength:
sequenceLastStartTime = currentTime
sequenceLastNotePlayedTime = 0.0
timeAccumulated -= frameRate
timeAccumulated = max(0.0, timeAccumulated)
sleepTime = frameRate - timeAccumulated - timeRoomForError
if sleepTime > 0:
print('Sleep ' + str(sleepTime))
time.sleep(sleepTime)
finally:
print('Resetting synth due to exception')
synthOut.reset()
#synthOut.panic()
if __name__ == '__main__':
testOutput()
# testOutput()
# testIO()
simpleSequencer()

Loading…
Cancel
Save