# SPDX-License-Identifier: BSD-3-Clause # # Generate comparison MIDI file. # # The comparison MIDI is used for testing and tweaking the similarity # groups in the configuration file. In each group, the instruments in # the group should sound broadly similar, and the first in the group # should be able to substitute for any member of the group. # # Each similarity group is played in order, with a pause between each # instrument. A programme of the instruments is printed to stdout so # that the user can identify each instrument in order. # # To use the comparison MIDI, use a port that supports Timidity for # MIDI playback, and configure it to use the GUS patch set (use # music/dgguspat.zip from the idgames archive). Use the "full" # configuration file (timidity.cfg in the .zip) so that every # instrument is used for playback. Rename comparison.mid to # d_runnin.lmp and run with '-file d_runnin.lmp -warp 1', so that the # music plays. from config import * import midi def instrument_num(instrument): """Given a GUS patch name, get the MIDI instrument number. For percussion instruments, the instrument number is offset by 128. """ for key, name in GUS_INSTR_PATCHES.items(): if name == instrument: return key raise Exception('Unknown instrument %s' % instrument) pattern = midi.Pattern(resolution=48) track = midi.Track() track.append(midi.ControlChangeEvent(tick=0, channel=9, data=[7, 92])) time = 500 for group in SIMILAR_GROUPS: # Don't bother with special effects. #if group[0] == 'blank': # continue print "Group: " empty = True for instrument in group: inum = instrument_num(instrument) # For normal instruments, play a couple of different notes. # For percussion instruments, play a couple of note on # the percussion channel. if inum <= 128: print "\t%s (%i)" % (instrument, inum) track.extend([ midi.ProgramChangeEvent(tick=time, channel=0, data=[inum]), midi.NoteOnEvent(tick=0, channel=0, velocity=92, pitch=midi.A_3), midi.NoteOffEvent(tick=50, channel=0, velocity=92, pitch=midi.A_3), midi.NoteOnEvent(tick=0, channel=0, velocity=92, pitch=midi.B_3), midi.NoteOffEvent(tick=50, channel=0, velocity=92, pitch=midi.B_3), ]) else: print "\t%s (percussion %i)" % (instrument, inum-128) track.extend([ midi.NoteOnEvent(tick=time, channel=9, velocity=92, pitch=inum-128), midi.NoteOffEvent(tick=50, channel=9, pitch=inum-128), midi.NoteOnEvent(tick=0, channel=9, velocity=92, pitch=inum-128), midi.NoteOffEvent(tick=50, channel=9, pitch=inum-128), ]) empty = False time = 100 if not empty: time = 500 # Four drumbeats indicate the end of the track and that the music is # going to loop. for i in range(4): track.extend([ midi.NoteOnEvent(tick=20, channel=9, velocity=92, pitch=35), midi.NoteOffEvent(tick=20, channel=9, pitch=35), ]) track.append(midi.EndOfTrackEvent(tick=1)) pattern.append(track) # Save the pattern to disk midi.write_midifile("comparison.mid", pattern)