Last active
May 4, 2024 20:27
-
-
Save avinmathew/35d18c718e6fb9fd11c6521776661152 to your computer and use it in GitHub Desktop.
Find overlapping MIDI notes
This file contains 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
# Checks a MIDI file to see if there are any overlapping notes | |
# An overlapping note is defined as two MIDI on events in sequence | |
import math | |
from mido import MidiFile, tick2second | |
input_midi = MidiFile(r'my_midi_file.mid') | |
notes = {} # stores which note is being held when iterating through each event | |
tempo = 120 # default, tempo will be read from the file | |
numerator = 4 # default, will be read from the file | |
absolute_ticks = 0 # contains the current time when processing each event | |
def note_to_name(note): | |
notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | |
octave = math.floor((note / 12) - 1) | |
note_index = (note % 12) | |
note = notes[note_index] | |
return f'{note}{octave}' | |
# process MIDI messages | |
for original_track in input_midi.tracks: | |
for msg in original_track: | |
if msg.type == 'time_signature': | |
numerator = msg.numerator | |
if msg.type != 'end_of_track': | |
absolute_ticks += msg.time | |
if msg.type == 'set_tempo': | |
tempo = msg.tempo | |
if msg.type == 'note_off' or msg.type == 'note_on' and msg.velocity == 0: | |
try: | |
del notes[msg.note] | |
except: | |
pass | |
if msg.type == 'note_on': | |
if msg.note in notes: | |
print(f'Overlapping note {note_to_name(msg.note)} at bar {absolute_ticks / input_midi.ticks_per_beat / numerator + 1}') | |
notes[msg.note] = msg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment