Created
March 18, 2024 12:22
-
-
Save sumpygump/de33e8242569499679a6b57b8869bf41 to your computer and use it in GitHub Desktop.
Merge midi channels
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
"""Merge midi data""" | |
import argparse | |
import csv | |
import glob | |
import os | |
import subprocess | |
import sys | |
POS_TRACK = 0 | |
POS_TIME = 1 | |
POS_TYPE = 2 | |
POS_CHANNEL = 3 | |
POS_NOTE = 4 | |
POS_VELOCITY = 5 | |
POS_PROGRAM = 4 | |
def collect_filenames(path): | |
"""Collect filenames from a path that may be a directory""" | |
if os.path.isdir(path): | |
files = glob.glob(f"{path}/*.mid") | |
return files | |
return [path] | |
def merge_midi(path, mode="single_channel"): | |
"""Merge midi channel/track data""" | |
all_files = collect_filenames(path) | |
for filename in all_files: | |
print(filename, end="") | |
csv_filename = f"{filename}.csv" | |
cmd = ["midicsv", filename, csv_filename] | |
subprocess.run(cmd, check=False) | |
data = read_csv(csv_filename) | |
for event in data: | |
if event[POS_TYPE] in ["Note_on_c", "Note_off_c"]: | |
event[POS_CHANNEL] = 0 | |
elif event[POS_TYPE] in ["Program_c"]: | |
event[POS_CHANNEL] = 0 | |
event[POS_PROGRAM] = 1 # Force to piano | |
write_csv(data, csv_filename) | |
out_filename = filename.replace(".mid", "_single_channel.mid") | |
cmd = ["csvmidi", csv_filename, out_filename] | |
subprocess.run(cmd, check=False) | |
print(" > Wrote to file", out_filename) | |
os.unlink(csv_filename) | |
def read_csv(filename): | |
"""Read midi csv file""" | |
events = [] | |
with open(filename, encoding="ISO-8859-1", newline="") as csvfile: | |
reader = csv.reader(csvfile, quotechar='"', skipinitialspace=True) | |
for row in reader: | |
events.append(row) | |
return events | |
def write_csv(data, filename): | |
"""Write midi csv file""" | |
with open(filename, "w", encoding="ISO-8859-1", newline="\n") as csvfile: | |
writer = csv.writer(csvfile) | |
for row in data: | |
writer.writerow(row) | |
return filename | |
if __name__ == "__main__": | |
if len(sys.argv) == 1: | |
print("Usage: merge_midi [--mode=<mode>] <path>") | |
sys.exit(1) | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
"-m", | |
"--mode", | |
default="single_channel", | |
help="Set mode for merge strategy", | |
) | |
parser.add_argument("path", help="Midi filename or path") | |
# Returns tuple of known args and unknown args | |
(args, _) = parser.parse_known_args(sys.argv[1:]) | |
print("Mode:", args.mode) | |
merge_midi(args.path, mode=args.mode) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment