Skip to content

Instantly share code, notes, and snippets.

@maximecb
Created May 19, 2018 17:21
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save maximecb/f440c1db489177c1037ec4f158cf5e4f to your computer and use it in GitHub Desktop.
Save maximecb/f440c1db489177c1037ec4f158cf5e4f to your computer and use it in GitHub Desktop.
Python program to sequence MIDI music using a CSV spreadsheet
X kick snare
X
X
X
X kick
X
X
X
X kick snare clap
X
X
X kick
X
X
X
X kick snare
X
X
X
X kick
X
X
X
X kick snare clap
X
X
X kick hat
X hat
X hat
X hat
X kick snare
X
X
X
X kick
X
X
X
X kick snare clap
X
X hat
hat
X kick
X hat
X hat
X hat
#!/usr/bin/env python3
import time
import csv
import mido
##############################################################################
def get_out_port(dev_name):
out_port = None
outputNames = mido.get_output_names()
for outputName in outputNames:
if dev_name in outputName.lower():
print('Connecting to %s' % outputName)
out_port = mido.open_output(outputName)
break
return out_port
bass_station = get_out_port("bass station")
drumbrute = get_out_port("drumbrute")
##############################################################################
MIDDLE_C = 60
# Semitone intervals for different scales
SCALE_INTERVS = {
'major': [2, 2, 1, 2, 2, 2],
'natural minor': [2, 1, 2, 2, 1, 2],
'major pentatonic': [2, 2, 3, 2],
'minor pentatonic': [3, 2, 2, 3],
'blues': [3, 2, 1, 1, 3],
'chromatic': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
}
def gen_scale(root_note, scale, num_octaves=1):
"""
Generate the notes of a scale based on a root note
"""
# Get the intervals for this type of chord
intervs = SCALE_INTERVS[scale]
# List of generated notes
notes = []
# For each octave
for oct_no in range(0, num_octaves):
oct_root = root_note + 12 * oct_no
# Add the root note to the scale
notes.append(oct_root)
# Add the scale notes
for i in range(0, len(intervs)):
prevNote = notes[-1]
interv = intervs[i]
notes.append(prevNote + interv)
# Add the note closing the last octave
notes.append(root_note + 12 * num_octaves)
return notes
##############################################################################
scale = gen_scale(MIDDLE_C, 'natural minor')
print('scale:', scale)
def play_music():
with open('music.csv', 'rt') as csvfile:
reader = csv.reader(csvfile, delimiter=',', quotechar='"')
rows = list(reader)
for step_idx, row in enumerate(rows):
if "kick" in row:
drumbrute.send(mido.Message('note_on', note=36, velocity=127, channel=1))
if "snare" in row:
drumbrute.send(mido.Message('note_on', note=38, velocity=127, channel=1))
if "clap" in row:
drumbrute.send(mido.Message('note_on', note=39, velocity=127, channel=1))
if "hat" in row:
drumbrute.send(mido.Message('note_on', note=42, velocity=127, channel=1))
note_no = None
if "X" in row:
degree = row.index("X")
note_no = scale[degree]
if note_no:
note_no = scale[degree]
bass_station.send(mido.Message('note_on', velocity=127, note=note_no))
time.sleep(0.07)
if note_no:
bass_station.send(mido.Message('note_off', velocity=127, note=note_no))
time.sleep(0.05)
try:
while True:
play_music()
except KeyboardInterrupt:
# Send all-notes-off message
bass_station.reset()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment