Skip to content

Instantly share code, notes, and snippets.

@RoadrunnerWMC
Created September 29, 2019 10:09
Show Gist options
  • Save RoadrunnerWMC/667c56be1ce16b7bd59ba133110af376 to your computer and use it in GitHub Desktop.
Save RoadrunnerWMC/667c56be1ce16b7bd59ba133110af376 to your computer and use it in GitHub Desktop.
Remap instruments in a MIDI, to import into Zelda Ocarina of Time using Seq64
# MIT License
#
# Copyright (c) 2019 RoadrunnerWMC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import sys
import mydy # pip install mydy
INSTRUMENT_NAMES = { # for https://cdn.discordapp.com/attachments/389136586262183956/595364274935824404/OoT_Soundfont.sf2
0: 'Accordion',
1: 'Acoustic Guitar',
2: 'Banjo',
3: 'Bassoon',
4: 'Beat Kit',
5: 'Bell',
6: 'Bell Pad',
7: 'Bent Drum',
8: 'Chant',
9: 'Chant ALT',
10: 'Clap',
11: 'Clarinet',
12: 'Clocktown Bell',
13: 'Conga',
14: 'Cowbell',
15: 'Creaking',
16: 'Cuica',
17: 'Drum',
18: 'Ethnic Drum',
19: 'Ethnic Flute',
20: 'Ethnic Flute ALT',
21: 'Famous DC Sound',
22: 'Famous Wood Chime',
23: 'Female Choir',
24: 'Fiddle',
25: 'Flute',
26: 'Glockenspiel',
27: 'Gong / Wind Chimes',
28: 'Guitar',
29: 'Harmonica',
30: 'Harp',
31: 'Harpsichord',
32: 'Horn',
33: 'Jazz Guitar',
34: 'Jazz Guitar ALT',
35: 'Kalimba',
36: 'Koto',
37: 'Lute Kit',
38: 'Male Choir',
39: 'Malon',
40: 'Marimba',
41: 'Multipitch Flute',
42: 'Noise',
43: 'Oboe',
44: 'Ocarina',
45: 'Orchestra Kit',
46: 'Organ',
47: 'Pad',
48: 'Piano',
49: 'Pizz Strings',
50: 'Steel Drum',
51: 'Strings',
52: 'Synth Strings',
53: 'Tambourine Kit',
54: 'Trombone',
55: 'Trumpet',
56: 'Tuba',
57: 'Voice Pad',
58: 'Wind',
59: 'Wind Cricket',
60: 'Wind Roar',
61: 'Wood Chime / Shine',
}
def remap_instruments(pattern):
"""
Given a Mydy pattern, find every program change event and replace
each instrument ID with increasing whole numbers.
Return a list of the original instrument IDs that were replaced.
(If duplicate program change events are found, this function will
avoid creating duplicate remappings for the same instrument type.)
"""
back_map = {}
new_mapping = []
for track in pattern:
for event in track:
if isinstance(event, mydy.Events.ProgramChangeEvent):
true_inst_id = event.data[0]
if true_inst_id not in back_map:
back_map[true_inst_id] = len(new_mapping)
new_mapping.append(true_inst_id)
event.data = [back_map[true_inst_id]]
return new_mapping
def main(argv):
print('Zelda OoT MIDI instrument remapper for importing with Seq64')
print('2019, RoadrunnerWMC; licensed under MIT license')
if len(argv) < 2:
print('Usage: fix_midi_for_seq64.py infile [outfile]')
return
in_fn = argv[1]
if len(argv) >= 3:
out_fn = argv[2]
else:
out_fn = in_fn.split('.')
if len(out_fn) < 2:
out_fn.append('remapped.midi')
else:
out_fn.insert(-1, 'remapped')
out_fn = '.'.join(out_fn)
pattern = mydy.FileIO.read_midifile(in_fn)
remapping = remap_instruments(pattern)
for i, inst_id in enumerate(remapping):
print(f'Bank instrument {i}: {INSTRUMENT_NAMES[inst_id]}')
mydy.FileIO.write_midifile(out_fn, pattern)
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment