lumps: Autogenerate optimized DMXGUS lump.

Replace the current poor-quality handcrafted GUS configuration with
a script that programatically generates an optimized configuration
file based on statistical analysis of music from various popular WAD
files.
This commit is contained in:
Simon Howard 2013-03-02 21:44:09 +00:00
parent 184be5bf61
commit 64198d7af1
8 changed files with 682 additions and 410 deletions

View file

@ -1,5 +1,5 @@
all : freedoom.lmp freedm.lmp misc-lumps genmidi-lump
all : freedoom.lmp freedm.lmp misc-lumps genmidi-lump dmxgus.lmp
misc-lumps:
make -C cph/misc-lumps
@ -7,6 +7,9 @@ misc-lumps:
genmidi-lump:
make -C genmidi
dmxgus.lmp:
make -C dmxgus
freedoom.lmp: force
echo $(VERSION) > freedoom.lmp
@ -18,4 +21,5 @@ force:
clean:
make -C cph/misc-lumps clean
make -C genmidi clean
make -C dmxgus clean

36
lumps/dmxgus/README Normal file
View file

@ -0,0 +1,36 @@
The script in this directory generates the GUS config file
(ultramid.ini) which is included in the IWAD as a lump named DMXGUS or
DMXGUSC.
The GUS config is mostly obsolete nowadays but it's still nice to
include anyway. The challenge is that each GUS card has a limited
amount of memory (256, 512, 768 or 1024KB). The GUS drivers come with
a complete set of patch files for all the General MIDI instruments,
but there is never enough RAM to fit all of them into the card's
memory. Patches must therefore be reused for multiple similar-sounding
instruments.
The config file looks like this (short extract):
31, 24, 31, 31, 31, gtrharm
32, 39, 32, 32, 32, acbass
33, 39, 33, 33, 33, fngrbass
34, 39, 34, 34, 34, pickbass
The second to fifth columns are the configurations for different
memory sizes. In this example, instrument 31 reuses instrument 24's
patch for the 256KB configuration, but in the 512KB configuration
there is enough space to load it properly.
The DMXGUS lumps used in the original Doom IWADs did not have a great
deal of attention paid to them, which lead some people to develop
optimized config files (see eg. GUS1M.WAD in idgames). The approach
taken here is to generate the configuration programatically:
statistics have been gathered about the use of different instruments
by analyzing the music found in various well-known WAD files. This is
used to prioritize which patches to load.
The generated config is still not great and could do with some
improvement. To improve the config, the best thing to tweak is the
similarity groups in config.py.

View file

@ -1,170 +0,0 @@
#!/usr/bin/env python
#
# Copyright (c) 2012
# Contributors to the Freedoom project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Sanity check script for DMXGUS lump.
# Please run this script after making any changes to ultramid.ini.
#
import sys
import re
# These are the sizes (in bytes) of the patch files distributed
# with the GUS drivers. Having these means we can calculate the
# size in RAM (roughly) of the patch set for a given configuration
# and check it is within the limit.
GUS_PATCH_SIZES = {
"acbass": 10829, "accordn": 19623, "acguitar": 52581,
"acpiano": 65259, "agogo": 27727, "agogohi": 7283,
"agogolo": 7283, "altosax": 11711, "applause": 60449,
"atmosphr": 63035, "aurora": 62503, "bagpipes": 16057,
"banjo": 64523, "barisax": 21739, "basslead": 53389,
"bassoon": 16723, "belltree": 64103, "blank": 3367,
"bongohi": 7233, "bongolo": 9201, "bottle": 25063,
"bowglass": 49691, "britepno": 72739, "cabasa": 17203,
"calliope": 46303, "carillon": 12089, "castinet": 12349,
"celeste": 20207, "cello": 18741, "charang": 90661,
"chiflead": 63381, "choir": 45353, "church": 4609,
"claps": 11719, "clarinet": 19161, "clave": 5035,
"clavinet": 3443, "cleangtr": 46027, "concrtna": 17981,
"congahi1": 8753, "congahi2": 9713, "congalo": 9713,
"contraba": 9723, "cowbell": 6645, "crystal": 60783,
"cuica1": 18995, "cuica2": 26017, "cymbell": 34815,
"cymchina": 48545, "cymcrsh1": 63353, "cymcrsh2": 62411,
"cymride1": 35655, "cymride2": 35655, "cymsplsh": 63353,
"distgtr": 38249, "doo": 17333, "echovox": 30287,
"englhorn": 24675, "epiano1": 15005, "epiano2": 44191,
"fantasia": 47229, "fiddle": 12309, "flute": 12383,
"fngrbass": 19797, "frenchrn": 28635, "freshair": 58307,
"fretless": 5605, "fx-blow": 57693, "fx-fret": 27631,
"ghostie": 63301, "glocken": 10695, "gtrharm": 10173,
"guiro1": 8561, "guiro2": 18821, "halopad": 60291,
"harmonca": 15301, "harp": 23927, "helicptr": 50327,
"highq": 3945, "hihatcl": 9453, "hihatop": 40417,
"hihatpd": 3925, "hitbrass": 63369, "homeorg": 2301,
"honky": 131905, "hrpschrd": 7709, "jazzgtr": 55923,
"jingles": 34219, "jungle": 27541, "kalimba": 4739,
"kick1": 9411, "kick2": 10377, "koto": 42079,
"lead5th": 13233, "maracas": 9433, "marcato": 122881,
"marimba": 4447, "metalpad": 60905, "metbell": 539,
"metclick": 539, "musicbox": 30947, "mutegtr": 34577,
"mutetrum": 19019, "nyguitar": 39211, "oboe": 9269,
"ocarina": 3537, "odguitar": 25845, "orchhit": 28751,
"percorg": 15435, "piccolo": 8945, "pickbass": 33213,
"pistol": 36595, "pizzcato": 40173, "polysyn": 60759,
"recorder": 5647, "reedorg": 3471, "revcym": 27391,
"rockorg": 60887, "santur": 43833, "sawwave": 54485,
"scratch1": 9091, "scratch2": 4883, "seashore": 62407,
"shakazul": 62589, "shaker": 6527, "shamisen": 26667,
"shannai": 20151, "sitar": 36979, "slap": 12031,
"slapbas1": 56133, "slapbas2": 41581, "slowstr": 36717,
"snare1": 17417, "snare2": 8503, "soundtrk": 40091,
"sprnosax": 14713, "sqrclick": 539, "sqrwave": 30439,
"startrak": 55085, "steeldrm": 24229, "stickrim": 6005,
"sticks": 8757, "surdo1": 19527, "surdo2": 19527,
"sweeper": 62745, "synbass1": 12627, "synbass2": 6191,
"synbras1": 61735, "synbras2": 60641, "synpiano": 11543,
"synstr1": 62763, "synstr2": 33165, "syntom": 61331,
"taiko": 37671, "tamborin": 18219, "telephon": 9157,
"tenorsax": 17367, "timbaleh": 10839, "timbalel": 19787,
"timpani": 14473, "tomhi1": 13467, "tomhi2": 13455,
"tomlo1": 13455, "tomlo2": 19527, "tommid1": 13455,
"tommid2": 13455, "toms": 13467, "tremstr": 122881,
"triangl1": 4781, "triangl2": 31901, "trombone": 26187,
"trumpet": 13621, "tuba": 11847, "tubebell": 18637,
"unicorn": 60505, "vibes": 21597, "vibslap": 19247,
"viola": 56465, "violin": 25061, "voices": 30287,
"voxlead": 30289, "warmpad": 36491, "whistle": 12053,
"whistle1": 4315, "whistle2": 2173, "woodblk": 7685,
"woodblk1": 5035, "woodblk2": 7685, "woodflut": 4191,
"xylophon": 19085
}
def patches_for_mapping(patches, mapping):
result = {}
for pnum in mapping.values():
patch = patches[pnum]
result[patch] = True
return sorted(result.keys())
def patch_set_size(patch_set):
result = 0
for patch in patch_set:
result += GUS_PATCH_SIZES[patch]
return result
def print_patch_set(title, patch_set):
print "%s:" % title
for patch in patch_set:
print "\t%-8s %i" % (patch, GUS_PATCH_SIZES[patch])
print "\t" + ("-" * 30)
print "\t%-8s %i" % ("TOTAL", patch_set_size(patch_set))
patches = {}
mappings = [ {}, {}, {}, {} ]
f = open("ultramid.ini")
for line in f:
line = line.strip()
if line.startswith("#"):
continue
fields = re.split(r"\s*,\s*", line)
instr = int(fields[0])
patches[instr] = fields[5]
for i in range(4):
mappings[i][instr] = int(fields[i + 1])
f.close()
# Check mappings:
MAPPING_SIZES = [ 256, 512, 768, 1024 ]
for i in range(4):
patch_set = patches_for_mapping(patches, mappings[i])
if patch_set_size(patch_set) > MAPPING_SIZES[i] * 1024:
print >> sys.stderr, \
"ERROR: Configuration for %iKB exceeds %iKB" % \
(MAPPING_SIZES[i], MAPPING_SIZES[i])
print_patch_set(MAPPING_SIZES[i], patch_set)
sys.exit(-1)

358
lumps/dmxgus/config.py Normal file
View file

@ -0,0 +1,358 @@
#
# Copyright (c) 2013 Contributors to the Freedoom project.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# --------------------------------------------------------------
#
# Config file for GUS config generator.
#
# Names of GUS instrument files to use for playing MIDI.
# These are the names of the .pat files in the \ultrasnd\midi directory
# that are loaded into the card.
GUS_INSTR_PATCHES = {
0: "acpiano", # #001 - Acoustic Grand Piano
1: "britepno", # #002 - Bright Acoustic Piano
2: "synpiano", # #003 - Electric Grand Piano
3: "honky", # #004 - Honky-tonk Piano
4: "epiano1", # #005 - Electric Piano 1
5: "epiano2", # #006 - Electric Piano 2
6: "hrpschrd", # #007 - Harpsichord
7: "clavinet", # #008 - Clavi
8: "celeste", # #009 - Celesta
9: "glocken", # #010 - Glockenspiel
10: "musicbox", # #011 - Music Box
11: "vibes", # #012 - Vibraphone
12: "marimba", # #013 - Marimba
13: "xylophon", # #014 - Xylophone
14: "tubebell", # #015 - Tubular Bells
15: "santur", # #016 - Dulcimer
16: "homeorg", # #017 - Drawbar Organ
17: "percorg", # #018 - Percussive Organ
18: "rockorg", # #019 - Rock Organ
19: "church", # #020 - Church Organ
20: "reedorg", # #021 - Reed Organ
21: "accordn", # #022 - Accordion
22: "harmonca", # #023 - Harmonica
23: "concrtna", # #024 - Tango Accordion
24: "nyguitar", # #025 - Acoustic Guitar (nylon)
25: "acguitar", # #026 - Acoustic Guitar (steel)
26: "jazzgtr", # #027 - Electric Guitar (jazz)
27: "cleangtr", # #028 - Electric Guitar (clean)
28: "mutegtr", # #029 - Electric Guitar (muted)
29: "odguitar", # #030 - Overdriven Guitar
30: "distgtr", # #031 - Distortion Guitar
31: "gtrharm", # #032 - Guitar harmonics
32: "acbass", # #033 - Acoustic Bass
33: "fngrbass", # #034 - Electric Bass (finger)
34: "pickbass", # #035 - Electric Bass (pick)
35: "fretless", # #036 - Fretless Bass
36: "slapbas1", # #037 - Slap Bass 1
37: "slapbas2", # #038 - Slap Bass 2
38: "synbass1", # #039 - Synth Bass 1
39: "synbass2", # #040 - Synth Bass 2
40: "violin", # #041 - Violin
41: "viola", # #042 - Viola
42: "cello", # #043 - Cello
43: "contraba", # #044 - Contrabass
44: "tremstr", # #045 - Tremolo Strings
45: "pizzcato", # #046 - Pizzicato Strings
46: "harp", # #047 - Orchestral Harp
47: "timpani", # #048 - Timpani
48: "marcato", # #049 - String Ensemble 1
49: "slowstr", # #050 - String Ensemble 2
50: "synstr1", # #051 - SynthStrings 1
51: "synstr2", # #052 - SynthStrings 2
52: "choir", # #053 - Choir Aahs
53: "doo", # #054 - Voice Oohs
54: "voices", # #055 - Synth Voice
55: "orchhit", # #056 - Orchestra Hit
56: "trumpet", # #057 - Trumpet
57: "trombone", # #058 - Trombone
58: "tuba", # #059 - Tuba
59: "mutetrum", # #060 - Muted Trumpet
60: "frenchrn", # #061 - French Horn
61: "hitbrass", # #062 - Brass Section
62: "synbras1", # #063 - SynthBrass 1
63: "synbras2", # #064 - SynthBrass 2
64: "sprnosax", # #065 - Soprano Sax
65: "altosax", # #066 - Alto Sax
66: "tenorsax", # #067 - Tenor Sax
67: "barisax", # #068 - Baritone Sax
68: "oboe", # #069 - Oboe
69: "englhorn", # #070 - English Horn
70: "bassoon", # #071 - Bassoon
71: "clarinet", # #072 - Clarinet
72: "piccolo", # #073 - Piccolo
73: "flute", # #074 - Flute
74: "recorder", # #075 - Recorder
75: "woodflut", # #076 - Pan Flute
76: "bottle", # #077 - Blown Bottle
77: "shakazul", # #078 - Shakuhachi
78: "whistle", # #079 - Whistle
79: "ocarina", # #080 - Ocarina
80: "sqrwave", # #081 - Lead 1 (square)
81: "sawwave", # #082 - Lead 2 (sawtooth)
82: "calliope", # #083 - Lead 3 (calliope)
83: "chiflead", # #084 - Lead 4 (chiff)
84: "charang", # #085 - Lead 5 (charang)
85: "voxlead", # #086 - Lead 6 (voice)
86: "lead5th", # #087 - Lead 7 (fifths)
87: "basslead", # #088 - Lead 8 (bass + lead)
88: "fantasia", # #089 - Pad 1 (new age)
89: "warmpad", # #090 - Pad 2 (warm)
90: "polysyn", # #091 - Pad 3 (polysynth)
91: "ghostie", # #092 - Pad 4 (choir)
92: "bowglass", # #093 - Pad 5 (bowed)
93: "metalpad", # #094 - Pad 6 (metallic)
94: "halopad", # #095 - Pad 7 (halo)
95: "sweeper", # #096 - Pad 8 (sweep)
96: "aurora", # #097 - FX 1 (rain)
97: "soundtrk", # #098 - FX 2 (soundtrack)
98: "crystal", # #099 - FX 3 (crystal)
99: "atmosphr", # #100 - FX 4 (atmosphere)
100: "freshair", # #101 - FX 5 (brightness)
101: "unicorn", # #102 - FX 6 (goblins)
102: "echovox", # #103 - FX 7 (echoes)
103: "startrak", # #104 - FX 8 (sci-fi)
104: "sitar", # #105 - Sitar
105: "banjo", # #106 - Banjo
106: "shamisen", # #107 - Shamisen
107: "koto", # #108 - Koto
108: "kalimba", # #109 - Kalimba
109: "bagpipes", # #110 - Bag pipe
110: "fiddle", # #111 - Fiddle
111: "shannai", # #112 - Shanai
112: "carillon", # #113 - Tinkle Bell
113: "agogo", # #114 - Agogo
114: "steeldrm", # #115 - Steel Drums
115: "woodblk", # #116 - Woodblock
116: "taiko", # #117 - Taiko Drum
117: "toms", # #118 - Melodic Tom
118: "syntom", # #119 - Synth Drum
119: "revcym", # #120 - Reverse Cymbal
120: "fx-fret", # #121 - Guitar Fret Noise
121: "fx-blow", # #122 - Breath Noise
122: "seashore", # #123 - Seashore
123: "jungle", # #124 - Bird Tweet
124: "telephon", # #125 - Telephone Ring
125: "helicptr", # #126 - Helicopter
126: "applause", # #127 - Applause
127: "pistol", # #128 - Gunshot
128: "blank",
162: "kick1", # #35 Acoustic Bass Drum
163: "kick2", # #36 Bass Drum 1
164: "stickrim", # #37 Side Stick
165: "snare1", # #38 Acoustic Snare
166: "claps", # #39 Hand Clap
167: "snare2", # #40 Electric Snare
168: "tomlo2", # #41 Low Floor Tom
169: "hihatcl", # #42 Closed Hi Hat
170: "tomlo1", # #43 High Floor Tom
171: "hihatpd", # #44 Pedal Hi-Hat
172: "tommid2", # #45 Low Tom
173: "hihatop", # #46 Open Hi-Hat
174: "tommid1", # #47 Low-Mid Tom
175: "tomhi2", # #48 Hi-Mid Tom
176: "cymcrsh1", # #49 Crash Cymbal 1
177: "tomhi1", # #50 High Tom
178: "cymride1", # #51 Ride Cymbal 1
179: "cymchina", # #52 Chinese Cymbal
180: "cymbell", # #53 Ride Bell
181: "tamborin", # #54 Tambourine
182: "cymsplsh", # #55 Splash Cymbal
183: "cowbell", # #56 Cowbell
184: "cymcrsh2", # #57 Crash Cymbal 2
185: "vibslap", # #58 Vibraslap
186: "cymride2", # #59 Ride Cymbal 2
187: "bongohi", # #60 Hi Bongo
188: "bongolo", # #61 Low Bongo
189: "congahi1", # #62 Mute Hi Conga
190: "congahi2", # #63 Open Hi Conga
191: "congalo", # #64 Low Conga
192: "timbaleh", # #65 High Timbale
193: "timbalel", # #66 Low Timbale
194: "agogohi", # #67 High Agogo
195: "agogolo", # #68 Low Agogo
196: "cabasa", # #69 Cabasa
197: "maracas", # #70 Maracas
198: "whistle1", # #71 Short Whistle
199: "whistle2", # #72 Long Whistle
200: "guiro1", # #73 Short Guiro
201: "guiro2", # #74 Long Guiro
202: "clave", # #75 Claves
203: "woodblk1", # #76 Hi Wood Block
204: "woodblk2", # #77 Low Wood Block
205: "cuica1", # #78 Mute Cuica
206: "cuica2", # #79 Open Cuica
207: "triangl1", # #80 Mute Triangle
208: "triangl2", # #81 Open Triangle
}
# These are the data sizes of the patch files distributed with the
# GUS drivers. These are used to calculate the size in RAM of the
# generated patch sets to check that they are within the limits.
# and check it is within the limit.
PATCH_FILE_SIZES = {
"acbass": 5248, "accordn": 9616, "acguitar": 26080,
"acpiano": 32256, "agogo": 13696, "agogohi": 3488,
"agogolo": 3488, "altosax": 5616, "applause": 30064,
"atmosphr": 31360, "aurora": 31088, "bagpipes": 7760,
"banjo": 32016, "barisax": 10544, "basslead": 26496,
"bassoon": 8000, "belltree": 31888, "blank": 1520,
"bongohi": 3456, "bongolo": 4448, "bottle": 12368,
"bowglass": 24688, "britepno": 36000, "cabasa": 8448,
"calliope": 22992, "carillon": 5888, "castinet": 6016,
"celeste": 9936, "cello": 9120, "charang": 45056,
"chiflead": 31536, "choir": 22480, "church": 2144,
"claps": 5696, "clarinet": 9184, "clave": 2352,
"clavinet": 1440, "cleangtr": 22768, "concrtna": 8784,
"congahi1": 4224, "congahi2": 4704, "congalo": 4704,
"contraba": 4704, "cowbell": 3168, "crystal": 30224,
"cuica1": 9344, "cuica2": 12848, "cymbell": 17248,
"cymchina": 24112, "cymcrsh1": 31520, "cymcrsh2": 31040,
"cymride1": 17664, "cymride2": 17664, "cymsplsh": 31520,
"distgtr": 18848, "doo": 8464, "echovox": 14976,
"englhorn": 12096, "epiano1": 7344, "epiano2": 21936,
"fantasia": 23456, "fiddle": 5904, "flute": 6032,
"fngrbass": 9744, "frenchrn": 14128, "freshair": 28992,
"fretless": 2640, "fx-blow": 28688, "fx-fret": 13648,
"ghostie": 31488, "glocken": 5184, "gtrharm": 4928,
"guiro1": 4128, "guiro2": 9248, "halopad": 29984,
"harmonca": 7408, "harp": 11728, "helicptr": 25008,
"highq": 1808, "hihatcl": 4560, "hihatop": 20048,
"hihatpd": 1808, "hitbrass": 31520, "homeorg": 992,
"honky": 65680, "hrpschrd": 3584, "jazzgtr": 27712,
"jingles": 16944, "jungle": 13616, "kalimba": 2208,
"kick1": 4544, "kick2": 5024, "koto": 20832,
"lead5th": 6464, "maracas": 4560, "marcato": 61232,
"marimba": 2064, "metalpad": 30288, "metbell": 112,
"metclick": 112, "musicbox": 15312, "mutegtr": 17008,
"mutetrum": 9168, "nyguitar": 19200, "oboe": 3952,
"ocarina": 1616, "odguitar": 12640, "orchhit": 14208,
"percorg": 7520, "piccolo": 4320, "pickbass": 16416,
"pistol": 18144, "pizzcato": 19888, "polysyn": 30224,
"recorder": 2656, "reedorg": 1568, "revcym": 13536,
"rockorg": 30288, "santur": 21760, "sawwave": 27056,
"scratch1": 4384, "scratch2": 2288, "seashore": 31040,
"shakazul": 31136, "shaker": 3104, "shamisen": 13136,
"shannai": 9792, "sitar": 18288, "slap": 5856,
"slapbas1": 27872, "slapbas2": 20592, "slowstr": 18192,
"snare1": 8544, "snare2": 4096, "soundtrk": 19888,
"sprnosax": 7072, "sqrclick": 112, "sqrwave": 15056,
"startrak": 27376, "steeldrm": 11952, "stickrim": 2848,
"sticks": 4224, "surdo1": 9600, "surdo2": 9600,
"sweeper": 31216, "synbass1": 6160, "synbass2": 2928,
"synbras1": 30704, "synbras2": 30160, "synpiano": 5456,
"synstr1": 31216, "synstr2": 16416, "syntom": 30512,
"taiko": 18672, "tamborin": 8944, "telephon": 4416,
"tenorsax": 8448, "timbaleh": 5264, "timbalel": 9728,
"timpani": 7072, "tomhi1": 6576, "tomhi2": 6560,
"tomlo1": 6560, "tomlo2": 9600, "tommid1": 6560,
"tommid2": 6560, "toms": 6576, "tremstr": 61232,
"triangl1": 2224, "triangl2": 15792, "trombone": 12896,
"trumpet": 6608, "tuba": 5760, "tubebell": 9120,
"unicorn": 30096, "vibes": 10640, "vibslap": 9456,
"viola": 27952, "violin": 12160, "voices": 14976,
"voxlead": 14992, "warmpad": 18080, "whistle": 5872,
"whistle1": 2000, "whistle2": 928, "woodblk": 3680,
"woodblk1": 2352, "woodblk2": 3680, "woodflut": 1936,
"xylophon": 9376,
}
# Groups of "similar sounding" instruments. The first instrument in each
# group is the "leader" and will be used as the fallback for other
# instruments in the group if they are not popular enough to be included.
# These groups are based on inaccurate stereotypes about musical instruments.
# If you're looking to improve the config, here's where to start.
SIMILAR_GROUPS = [
# Pianos.
('acpiano', 'britepno', 'synpiano', 'honky', 'epiano1', 'epiano2',
'hrpschrd', 'clavinet', 'celeste', 'glocken'),
# Xylophone etc.
('marimba', 'musicbox', 'vibes', 'xylophon', 'tubebell', 'santur',
'kalimba'),
# Organs.
('homeorg', 'percorg', 'rockorg', 'church', 'reedorg', 'accordn',
'harmonca', 'concrtna'),
# Guitars.
('nyguitar', 'acguitar', 'jazzgtr', 'cleangtr', 'mutegtr', 'odguitar',
'distgtr', 'gtrharm'),
# Basses.
('synbass2', 'acbass', 'fngrbass', 'pickbass', 'fretless', 'slapbas1',
'slapbas2', 'synbass1'),
# Violin and similar string instruments.
('violin', 'viola', 'cello', 'contraba', 'tremstr', 'pizzcato', 'harp',
'timpani'),
# Other stringed (?)
('marcato', 'slowstr', 'synstr1', 'synstr2', 'choir', 'doo', 'voices',
'orchhit'),
# Trumpet and other brass.
('trumpet', 'trombone', 'tuba', 'mutetrum', 'frenchrn', 'hitbrass',
'synbras1', 'synbras2'),
# Reed instruments.
('sprnosax', 'altosax', 'tenorsax', 'barisax', 'oboe', 'englhorn',
'bassoon', 'clarinet'),
# Pipe instruments.
('flute', 'piccolo', 'recorder', 'woodflut', 'bottle', 'shakazul',
'whistle', 'ocarina', 'bagpipes', 'fiddle', 'shannai'),
# Leads.
('sqrwave', 'sawwave', 'calliope', 'chiflead', 'charang', 'voxlead',
'lead5th', 'basslead', 'sitar', 'banjo', 'shamisen', 'koto'),
# Special effects. Blank unless popular enough to appear.
('blank','fantasia', 'warmpad', 'polysyn', 'ghostie', 'bowglass',
'metalpad', 'halopad', 'sweeper', 'aurora', 'soundtrk', 'crystal',
'atmosphr', 'freshair', 'unicorn', 'echovox', 'startrak', 'fx-fret',
'fx-blow', 'seashore', 'jungle', 'telephon', 'helicptr', 'applause',
'pistol'),
# -- Percussion effects. This is probably where the current config is
# worst and in dire need of improvement.
# Conga/kick
('kick1', 'steeldrm', 'taiko', 'kick2', 'congahi1', 'congahi2',
'congalo', 'clave'),
# Snare drums
('snare1', 'stickrim', 'claps', 'snare2', 'tamborin', 'vibslap',
'bongohi', 'bongolo', 'timbaleh', 'timbalel', 'maracas', 'woodblk1',
'woodblk2'),
# Hi-hat
('hihatpd', 'carillon', 'agogo', 'woodblk', 'hihatcl', 'hihatop',
'cowbell', 'agogohi', 'agogolo', 'cabasa', 'whistle1', 'whistle2',
'guiro1', 'guiro2', 'cuica1', 'cuica2', 'triangl1', 'triangl2'),
# Toms
('tommid1', 'toms', 'syntom', 'tomlo2', 'tomlo1', 'tommid2', 'tomhi2',
'tomhi1'),
# Cymbals.
('cymcrsh1', 'revcym', 'cymride1', 'cymchina', 'cymbell', 'cymsplsh',
'cymcrsh2', 'cymride2'),
]

View file

@ -0,0 +1,83 @@
#!/usr/bin/env python
#
# Copyright (c) 2013 Contributors to the Freedoom project.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ----------------------------------------------------------------------
#
# Script to gather statistics from MIDI files about instrument usage.
# Generates stats.py which is used as input for the ultramid.ini
# generator script.
#
# This script requires python-midi; see here:
# https://github.com/vishnubob/python-midi
#
import midi
import sys
def get_instr_stats(filename):
"""Get a set of instruments used by the specified MIDI file."""
result = set()
midfile = midi.read_midifile(filename)
for track in midfile:
for event in track:
if isinstance(event, midi.ProgramChangeEvent) \
and event.channel != 9:
instr = event.data[0]
result.add(instr)
# Percussion:
if isinstance(event, midi.NoteOnEvent) \
and event.channel == 9:
instr = event.data[0] + 128
result.add(instr)
return result
total_stats = [0] * 217
for filename in sys.argv[1:]:
print "Processing %s" % filename
stats = get_instr_stats(filename)
print sorted(stats)
for instrument in stats:
total_stats[instrument] += 1
with open("stats.py", "w") as f:
f.write("# Instrument stats, autogenerated by gather_stats.py\n\n")
f.write("INSTRUMENT_STATS = [\n\t")
for index, stat in enumerate(total_stats):
f.write("% 5i," % stat)
if (index % 10) == 9:
f.write("\n\t")
f.write("\n]\n")

174
lumps/dmxgus/gen-ultramid Executable file
View file

@ -0,0 +1,174 @@
#!/usr/bin/env python
#
# Copyright (c) 2013 Contributors to the Freedoom project.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ----------------------------------------------------------------------
#
# Config file generator for the DMXGUS lump / config file.
#
# This script generates a GUS config file with instrument mappings for
# 256,512,768 and 1024KB cards. This is done automatically from the config
# in config.py. The instruments to include are selected using statistics
# processed from a collection of well-known Doom WAD files.
#
import re
import sys
import config
import stats
def normalize_stats(stats):
"""Normalize the gathered instrument statistics.
Percussion instruments tend to be more widely used, which can give
them a disproportionate priority. Therefore, generate a "normalized"
set of statistics that adjust the percussion instruments to be
roughly equal to the main instruments.
"""
main_stats = stats[0:128]
perc_stats = stats[128:]
main_av = sum(main_stats) / len(main_stats)
perc_av = sum(perc_stats) / (len(perc_stats) - 35)
def adjusted_priority(stat):
return (float(stat) * main_av) / perc_av
adjusted_perc_stats = map(adjusted_priority, perc_stats)
return main_stats + list(adjusted_perc_stats)
def ranked_patches():
"""Get a list of GUS patches ranked by priority.
This uses the gathered statistics about use of different instruments
in Doom WADs and orders them by benefit/cost ratio (where cost is
the size that the instrument file will occupy in RAM).
"""
adjusted_stats = normalize_stats(stats.INSTRUMENT_STATS)
result = []
for instr_id, name in config.GUS_INSTR_PATCHES.items():
priority = float(adjusted_stats[instr_id]) \
/ config.PATCH_FILE_SIZES[name]
result.append((priority, name))
return list(map(lambda x: x[1], reversed(sorted(result))))
def midi_instr_for_name(name):
"""Given a GUS patch name, find the associated MIDI instrument."""
for instr_id, instr_name in config.GUS_INSTR_PATCHES.items():
if name == instr_name:
return instr_id
raise KeyError("Unknown instrument: %s" % name)
def patchset_size(mapping):
"""Given an instrument-instrument mapping patch set, calculate its
size.
"""
result = 0
for i1, i2 in mapping.items():
if i1 == i2:
name = config.GUS_INSTR_PATCHES[i1]
result += config.PATCH_FILE_SIZES[name]
return result
def mapping_for_size(size):
"""Select a set of patches for the given RAM size.
Args:
size: Size in bytes of the GUS RAM.
Returns:
Dictionary mapping from instrument number to instrument number.
An instrument that maps to itself is included in the output.
"""
# Leave some extra space. The ultramid.ini distributed with the
# GUS drivers says this:
# The libraries are built in such a way as to leave 8K+32bytes
# after the patches are loaded for digital audio.
size -= 32*1024 + 8
# Get a list of patches sorted by decreasing priority.
patches = ranked_patches()
# Start by processing the similarity groups and pointing all
# instruments in a group to their group leader.
result = {}
for group in config.SIMILAR_GROUPS:
leader = group[0]
leader_index = midi_instr_for_name(leader)
for patch in group:
patch_index = midi_instr_for_name(patch)
result[patch_index] = leader_index
# We now have a mapping that should cover every instrument with
# a fallback. Go through the patches in order of priority and add
# patches that will fit.
curr_size = patchset_size(result)
assert curr_size < size, \
"Minimal config for %s will not fit in RAM!" % size
for patch in patches:
patch_index = midi_instr_for_name(patch)
patch_size = config.PATCH_FILE_SIZES[patch]
if result[patch_index] != patch_index \
and curr_size + patch_size < size:
result[patch_index] = patch_index
curr_size += patch_size
return result
if len(sys.argv) != 2:
print "Usage: %s <filename>" % sys.argv[0]
sys.exit(1)
mappings = (
mapping_for_size(256 * 1024),
mapping_for_size(512 * 1024),
mapping_for_size(768 * 1024),
mapping_for_size(1024 * 1024)
)
with open(sys.argv[1], "w") as output:
output.write("# Freedoom GUS config.\n"
"# Autogenerated by gen-ultramid\n\n")
for instr_id, name in sorted(config.GUS_INSTR_PATCHES.items()):
line = "%i, %i, %i, %i, %i, %s" % (
instr_id,
mappings[0][instr_id],
mappings[1][instr_id],
mappings[2][instr_id],
mappings[3][instr_id],
name
)
output.write(line + "\n")

26
lumps/dmxgus/stats.py Normal file
View file

@ -0,0 +1,26 @@
# Instrument stats, autogenerated by gather_stats.py
INSTRUMENT_STATS = [
40, 21, 7, 2, 9, 5, 22, 13, 26, 8,
12, 24, 27, 10, 60, 16, 8, 6, 26, 26,
6, 0, 0, 0, 13, 16, 4, 37, 49, 111,
188, 21, 32, 67, 99, 40, 42, 25, 50, 39,
9, 8, 15, 14, 41, 70, 56, 129, 198, 49,
45, 33, 70, 8, 13, 33, 9, 6, 1, 0,
32, 46, 18, 15, 3, 4, 2, 5, 13, 0,
6, 12, 5, 18, 3, 6, 3, 1, 9, 16,
68, 95, 19, 3, 11, 7, 3, 34, 25, 29,
29, 14, 10, 20, 26, 29, 14, 17, 5, 15,
31, 9, 8, 17, 9, 2, 4, 8, 12, 6,
3, 1, 3, 2, 2, 4, 21, 15, 12, 34,
13, 4, 8, 2, 1, 2, 1, 6, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 6, 25, 1, 1, 7,
0, 7, 2, 136, 313, 19, 206, 12, 249, 192,
265, 197, 112, 184, 265, 152, 124, 251, 85, 168,
193, 128, 75, 145, 24, 237, 25, 80, 27, 30,
36, 30, 31, 14, 14, 4, 7, 42, 27, 0,
1, 29, 17, 37, 11, 9, 2, 0, 33, 44,
25, 5, 11, 12, 4, 2, 2,
]

View file

@ -1,239 +0,0 @@
# Copyright (c) 2012
# Contributors to the Freedoom project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# GUS patch mappings.
#
# This is a *terrible* configuration file. I threw it together in an
# hour just so that Freedoom would have a DMXGUS lump. It's based on
# inaccurate stereotypes, ignorance of musical instruments and wild
# guesses. So if you think you can improve it, feel free to do so.
# If you are a musician and are annoyed by this awful configuration
# or the comments within it, YHBT :-)
#
# Designed to use as few patches as possible to fit within a GUS
# with 256K of RAM, but no attempt has been made to improve this for
# the higher configurations!
#
#
# GM 256K 512K 768K 1024K patch name
#------------------------------------------------
# "All pianos sound the same, right?"
0, 2, 2, 2, 2, acpiano
1, 2, 2, 2, 2, britepno
2, 2, 2, 2, 2, synpiano
3, 2, 2, 2, 2, honky
4, 2, 2, 2, 2, epiano1
5, 2, 2, 2, 2, epiano2
6, 2, 2, 2, 2, hrpschrd
7, 2, 2, 2, 2, clavinet
8, 2, 2, 2, 2, celeste
9, 2, 2, 2, 2, glocken
# Xylophone etc.
10, 13, 13, 13, 13, musicbox
11, 13, 13, 13, 13, vibes
12, 13, 13, 13, 13, marimba
13, 13, 13, 13, 13, xylophon
14, 13, 13, 13, 13, tubebell
15, 13, 13, 13, 13, santur
# "Organ? You mean like in a church?"
16, 16, 16, 16, 16, homeorg
17, 16, 16, 16, 16, percorg
18, 16, 16, 16, 16, rockorg
19, 16, 16, 16, 16, church
20, 16, 16, 16, 16, reedorg
21, 16, 16, 16, 16, accordn
22, 16, 16, 16, 16, harmonca
23, 16, 16, 16, 16, concrtna
# "Any guitar, I just want to be a rock star"
24, 30, 30, 30, 30, nyguitar
25, 30, 30, 30, 30, acguitar
26, 30, 30, 30, 30, jazzgtr
27, 30, 30, 30, 30, cleangtr
28, 30, 30, 30, 30, mutegtr
29, 30, 30, 30, 30, odguitar
30, 30, 30, 30, 30, distgtr
31, 30, 30, 30, 30, gtrharm
# Bass:
32, 35, 35, 35, 35, acbass
33, 35, 35, 35, 35, fngrbass
34, 35, 35, 35, 35, pickbass
35, 35, 35, 35, 35, fretless
36, 35, 35, 35, 35, slapbas1
37, 35, 35, 35, 35, slapbas2
38, 35, 35, 35, 35, synbass1
39, 35, 35, 35, 35, synbass2
# Violin:
40, 40, 40, 40, 40, violin
41, 40, 40, 40, 40, viola
42, 40, 40, 40, 40, cello
43, 40, 40, 40, 40, contraba
44, 40, 40, 40, 40, tremstr
45, 40, 40, 40, 40, pizzcato
46, 40, 40, 40, 40, harp
47, 40, 40, 40, 40, timpani
# Strings:
48, 55, 55, 55, 55, marcato
49, 55, 55, 55, 55, slowstr
50, 55, 55, 55, 55, synstr1
51, 55, 55, 55, 55, synstr2
52, 55, 55, 55, 55, choir
53, 55, 55, 55, 55, doo
54, 55, 55, 55, 55, voices
55, 55, 55, 55, 55, orchhit
# Trumpet:
56, 56, 56, 56, 56, trumpet
57, 56, 56, 56, 56, trombone
58, 56, 56, 56, 56, tuba
59, 56, 56, 56, 56, mutetrum
60, 56, 56, 56, 56, frenchrn
61, 56, 56, 56, 56, hitbrass
62, 56, 56, 56, 56, synbras1
63, 56, 56, 56, 56, synbras2
# Reed:
64, 71, 71, 71, 71, sprnosax
65, 71, 71, 71, 71, altosax
66, 71, 71, 71, 71, tenorsax
67, 71, 71, 71, 71, barisax
68, 71, 71, 71, 71, oboe
69, 71, 71, 71, 71, englhorn
70, 71, 71, 71, 71, bassoon
71, 71, 71, 71, 71, clarinet
# Pipe. Same thing as reed, right?
72, 71, 71, 71, 71, piccolo
73, 71, 71, 71, 71, flute
74, 71, 71, 71, 71, recorder
75, 71, 71, 71, 71, woodflut
76, 71, 71, 71, 71, bottle
77, 71, 71, 71, 71, shakazul
78, 71, 71, 71, 71, whistle
79, 71, 71, 71, 71, ocarina
# "Lead? You mean a lead guitar, right?"
80, 30, 30, 30, 30, sqrwave
81, 30, 30, 30, 30, sawwave
82, 30, 30, 30, 30, calliope
83, 30, 30, 30, 30, chiflead
84, 30, 30, 30, 30, charang
85, 30, 30, 30, 30, voxlead
86, 30, 30, 30, 30, lead5th
87, 30, 30, 30, 30, basslead
# Nobody really uses this shit:
88, 128, 128, 128, 128, fantasia
89, 128, 128, 128, 128, warmpad
90, 128, 128, 128, 128, polysyn
91, 128, 128, 128, 128, ghostie
92, 128, 128, 128, 128, bowglass
93, 128, 128, 128, 128, metalpad
94, 128, 128, 128, 128, halopad
95, 128, 128, 128, 128, sweeper
96, 128, 128, 128, 128, aurora
97, 128, 128, 128, 128, soundtrk
98, 128, 128, 128, 128, crystal
99, 128, 128, 128, 128, atmosphr
100, 128, 128, 128, 128, freshair
101, 128, 128, 128, 128, unicorn
102, 128, 128, 128, 128, echovox
103, 128, 128, 128, 128, startrak
# Lazy guesses at things these sound like:
104, 30, 30, 30, 30, sitar
105, 30, 30, 30, 30, banjo
106, 30, 30, 30, 30, shamisen
107, 30, 30, 30, 30, koto
108, 13, 13, 13, 13, kalimba
109, 71, 71, 71, 71, bagpipes
110, 71, 71, 71, 71, fiddle
111, 71, 71, 71, 71, Shannai
# Percussion.
112, 171, 171, 171, 171, carillon
113, 171, 171, 171, 171, agogo
114, 163, 163, 163, 163, steeldrm
115, 171, 171, 171, 171, woodblk
116, 163, 163, 163, 163, taiko
117, 174, 174, 174, 174, toms
118, 174, 174, 174, 174, syntom
119, 178, 178, 178, 178, revcym
# No.
120, 128, 128, 128, 128, fx-fret
121, 128, 128, 128, 128, fx-blow
122, 128, 128, 128, 128, seashore
123, 128, 128, 128, 128, jungle
124, 128, 128, 128, 128, telephon
125, 128, 128, 128, 128, helicptr
126, 128, 128, 128, 128, applause
127, 128, 128, 128, 128, pistol
128, 128, 128, 128, 128, blank
# Every percussion instrument ever invented is one of either:
# cymbal, tom, bass drum, snare or hi-hat. Everything else is
# just a variant on these themes. Correct?
162, 163, 163, 163, 163, kick1
163, 163, 163, 163, 163, kick2
164, 165, 165, 165, 165, stickrim
165, 165, 165, 165, 165, snare1
166, 165, 165, 165, 165, claps
167, 165, 165, 165, 165, snare2
168, 174, 174, 174, 174, tomlo2
169, 171, 171, 171, 171, hihatcl
170, 174, 174, 174, 174, tomlo1
171, 171, 171, 171, 171, hihatpd
172, 174, 174, 174, 174, tommid2
173, 171, 171, 171, 171, hihatop
174, 174, 174, 174, 174, tommid1
175, 174, 174, 174, 174, tomhi2
176, 178, 178, 178, 178, cymcrsh1
177, 174, 174, 174, 174, tomhi1
178, 178, 178, 178, 178, cymride1
179, 178, 178, 178, 178, cymchina
180, 178, 178, 178, 178, cymbell
181, 165, 165, 165, 165, tamborin
182, 178, 178, 178, 178, cymsplsh
183, 171, 171, 171, 171, cowbell
184, 178, 178, 178, 178, cymcrsh2
185, 165, 165, 165, 165, vibslap
186, 178, 178, 178, 178, cymride2
187, 165, 165, 165, 165, bongohi
188, 165, 165, 165, 165, bongolo
189, 163, 163, 163, 163, congahi1
190, 163, 163, 163, 163, congahi2
191, 163, 163, 163, 163, congalo
192, 165, 165, 165, 165, timbaleh
193, 165, 165, 165, 165, timbalel
194, 171, 171, 171, 171, agogohi
195, 171, 171, 171, 171, agogolo
196, 171, 171, 171, 171, cabasa
197, 165, 165, 165, 165, maracas
198, 171, 171, 171, 171, whistle1
199, 171, 171, 171, 171, whistle2
200, 171, 171, 171, 171, guiro1
201, 171, 171, 171, 171, guiro2
202, 163, 163, 163, 163, clave
203, 165, 165, 165, 165, woodblk1
204, 165, 165, 165, 165, woodblk2
205, 171, 171, 171, 171, cuica1
206, 171, 171, 171, 171, cuica2
207, 171, 171, 171, 171, triangl1
208, 171, 171, 171, 171, triangl2