Created
May 19, 2018 17:21
-
-
Save maximecb/f440c1db489177c1037ec4f158cf5e4f to your computer and use it in GitHub Desktop.
Python program to sequence MIDI music using a CSV spreadsheet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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