Skip to content

Instantly share code, notes, and snippets.

Created October 27, 2023 14:15
Show Gist options
  • Save xavriley/c9cdd7bb910246a730a3dab6109237ef to your computer and use it in GitHub Desktop.
Save xavriley/c9cdd7bb910246a730a3dab6109237ef to your computer and use it in GitHub Desktop.
Add downbeats to midi using PrettyMIDI for use in Logic X
import pretty_midi as pm
import json
def get_syncpoint_downbeat_times(syncpoints):
downbeat_times = []
for syncpoint in syncpoints:
if len(syncpoint) == 2 or syncpoint[2] == 0:
return downbeat_times
def main(midi_file_path, syncpoints_file_path):
syncpoints = json.load(open(syncpoints_file_path))
downbeat_times = get_syncpoint_downbeat_times(syncpoints)
midi_data = pm.PrettyMIDI(midi_file_path)
# resolution - 1024 for music21, 220 for Logic Pro X
output_midi = pm.PrettyMIDI(initial_tempo=120, resolution=1024)
guitar = pm.Instrument(program=25)
output_midi.time_signature_changes.append(pm.TimeSignature(4, 4, 0))
first_db = syncpoints[0][1]
if first_db != 0:
# this would be the proper way to do it, but it blows up the tick resolution
# and the MIDI file won't save
# output_midi._tick_scales.append((0, (60/(first_db / 4))*output_midi.resolution))
# output_midi._update_tick_to_time(int(pm.MAX_TICK))
# so instead we just force the first downbeat to be at 0
downbeat_times[0] = 0
for (db, n_db) in zip(downbeat_times, downbeat_times[1:]):
if not n_db:
n_db = midi_data.get_end_time()
new_tempo = 60.0 / ((n_db - db) / 4)
60 / (new_tempo * output_midi.resolution)))
# output_midi.time_signature_changes.append(pm.TimeSignature(4, 4, db))
for instrument in midi_data.instruments:
for note in instrument.notes:
if __name__ == '__main__':
midi_file_path = 'mona-lisa-transcribed.mid'
syncpoints_file_path = 'mona-lisa-syncpoints.json'
main(midi_file_path, syncpoints_file_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment