Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/usr/env python
from collections import defaultdict
from mido import MidiFile, bpm2tempo, second2tick
from midi_maps import GENERAL_MIDI_DRUMS
# First pass, handle drum loops
fn = '/Users/brian/Dropbox/M_U_S_I_C/audio/drum loops/IndieRockDrums_MIDILoops/Akron_98/Akron_Grv_1.mid'
# Akron 98 has 3 drums:
# 36, 38, 43
time = 0.0
open_notes = {}
midi_tempo = bpm2tempo(98) # MIDI File tempo
# TODO get from file / this has rounding error ^
midi_tempo = 612244
midi_ticks_per_beat = MidiFile(fn).ticks_per_beat
tracks_durations = defaultdict(list)
tracks_cue_times = defaultdict(list)
tracks_sonic_pi_ats = defaultdict(list)
def slugify(name):
return name.lower().replace(' ', '_')
def _note_name(note):
return slugify(GENERAL_MIDI_DRUMS[note])
for msg in MidiFile(fn):
time += msg.time
if msg.is_meta:
print(msg)
if msg.type == 'note_on':
if _note_name(msg.note) in open_notes:
raise Exception('Note already started')
open_notes[_note_name(msg.note)] = time
tracks_cue_times[_note_name(msg.note)].append(time)
tracks_sonic_pi_ats[_note_name(msg.note)].append(second2tick(time, midi_ticks_per_beat, midi_tempo) / midi_ticks_per_beat)
elif msg.type == 'note_off':
tracks_durations[_note_name(msg.note)].append(time - open_notes[_note_name(msg.note)])
del open_notes[_note_name(msg.note)]
#print(tracks_cue_times)
print(tracks_sonic_pi_ats)
#print(tracks_durations)
#print(tracks_durations_as_beats)
assert(len(tracks_cue_times[36]) == len(tracks_durations[36]))
# TODO figure out first rest before each note
# TODO figure out rests between each note
# TODO capture velocity and translate to :amp
# TODO get the note duration in beats
# TODO map for sample names to GM drum
# TODO output BPM
# TODO keep the compact arrays form
# TODO save to sonic-pi dirs
at_template = \
"""
at {beat_counts} do
cue :{instrument}
end
"""
live_loop_sync_template = \
"""
live_loop :{loop_name} do
sync :{cue_name}
sample :the_sample
end
"""
live_loop_template = \
"""
live_loop :{loop_name}_loop do
sleep {first_sleep}
{sample_sleep_layout}
end
"""
sample_sleep_layout = \
"""
sample :{sample_name}
sleep {next_sleep}
"""
sample_sync_layout = \
"""
sample :{sample_name}
sync :loop_window
"""
print('use_bpm 98')
for track in tracks_sonic_pi_ats.keys():
ssblocks = []
for idx, beat_cue in enumerate(tracks_sonic_pi_ats[track]):
#get next sleep
if idx+1 == len(tracks_sonic_pi_ats[track]):
next_sleep = 8.0 - tracks_sonic_pi_ats[track][idx]
ssblocks.append(sample_sync_layout.format(sample_name='drum_bass_hard'))
else:
next_sleep = (tracks_sonic_pi_ats[track][idx+1]) - beat_cue
ssblocks.append(sample_sleep_layout.format(sample_name='drum_bass_hard', next_sleep=next_sleep))
print(live_loop_template.format(loop_name=track, first_sleep=tracks_sonic_pi_ats[track][0] - 0.0, sample_sleep_layout=''.join(ssblocks)))
print("""
live_loop :loop_window do
8.times do
sleep 1
end
end
""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.