Mercurial > SDL_sound_CoreAudio
annotate decoders/timidity/timidity.c @ 323:b5112525ebe9
added .cvsignore files
author | fingolfin |
---|---|
date | Fri, 10 May 2002 02:23:45 +0000 |
parents | a73c51c12452 |
children | 3da217bd0e48 |
rev | line source |
---|---|
199 | 1 /* |
2 | |
3 TiMidity -- Experimental MIDI to WAVE converter | |
4 Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi> | |
5 | |
6 This program is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 2 of the License, or | |
9 (at your option) any later version. | |
10 | |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; if not, write to the Free Software | |
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | |
20 */ | |
21 | |
22 #if HAVE_CONFIG_H | |
23 # include <config.h> | |
24 #endif | |
25 | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 | |
30 #include "SDL_sound.h" | |
31 | |
32 #define __SDL_SOUND_INTERNAL__ | |
33 #include "SDL_sound_internal.h" | |
34 | |
35 #include "timidity.h" | |
36 | |
37 #include "options.h" | |
38 #include "common.h" | |
39 #include "instrum.h" | |
40 #include "playmidi.h" | |
41 #include "readmidi.h" | |
42 #include "output.h" | |
43 | |
44 #include "tables.h" | |
45 | |
46 ToneBank *master_tonebank[128], *master_drumset[128]; | |
47 | |
48 static char def_instr_name[256] = ""; | |
49 | |
50 #define MAXWORDS 10 | |
51 | |
52 /* Quick-and-dirty fgets() replacement. */ | |
53 | |
54 static char *RWgets(SDL_RWops *rw, char *s, int size) | |
55 { | |
56 int num_read = 0; | |
57 int newline = 0; | |
58 | |
59 while (num_read < size && !newline) | |
60 { | |
61 if (SDL_RWread(rw, &s[num_read], 1, 1) != 1) | |
62 break; | |
63 | |
64 /* Unlike fgets(), don't store newline. Under Windows/DOS we'll | |
65 * probably get an extra blank line for every line that's being | |
66 * read, but that should be ok. | |
67 */ | |
68 if (s[num_read] == '\n' || s[num_read] == '\r') | |
69 { | |
70 s[num_read] = '\0'; | |
71 newline = 1; | |
72 } | |
73 | |
74 num_read++; | |
75 } | |
76 | |
77 s[num_read] = '\0'; | |
78 | |
79 return (num_read != 0) ? s : NULL; | |
80 } | |
81 | |
82 static int read_config_file(char *name) | |
83 { | |
84 SDL_RWops *rw; | |
85 char tmp[1024], *w[MAXWORDS], *cp; | |
86 ToneBank *bank=0; | |
87 int i, j, k, line=0, words; | |
88 static int rcf_count=0; | |
89 | |
90 if (rcf_count>50) | |
91 { | |
92 SNDDBG(("Probable source loop in configuration files\n")); | |
93 return (-1); | |
94 } | |
95 | |
96 if (!(rw=open_file(name))) | |
97 return -1; | |
98 | |
99 while (RWgets(rw, tmp, sizeof(tmp))) | |
100 { | |
101 line++; | |
102 w[words=0]=strtok(tmp, " \t\240"); | |
249
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
103 if (!w[0]) continue; |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
104 |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
105 /* Originally the TiMidity++ extensions were prefixed like this */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
106 if (strcmp(w[0], "#extension") == 0) |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
107 words = -1; |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
108 else if (*w[0] == '#') |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
109 continue; |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
110 |
199 | 111 while (w[words] && *w[words] != '#' && (words < MAXWORDS)) |
112 w[++words]=strtok(0," \t\240"); | |
249
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
113 |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
114 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
115 * TiMidity++ adds a number of extensions to the config file format. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
116 * Many of them are completely irrelevant to SDL_sound, but at least |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
117 * we shouldn't choke on them. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
118 * |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
119 * Unfortunately the documentation for these extensions is often quite |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
120 * vague, gramatically strange or completely absent. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
121 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
122 if ( |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
123 !strcmp(w[0], "comm") /* "comm" program second */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
124 || !strcmp(w[0], "HTTPproxy") /* "HTTPproxy" hostname:port */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
125 || !strcmp(w[0], "FTPproxy") /* "FTPproxy" hostname:port */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
126 || !strcmp(w[0], "mailaddr") /* "mailaddr" your-mail-address */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
127 || !strcmp(w[0], "opt") /* "opt" timidity-options */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
128 ) |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
129 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
130 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
131 * + "comm" sets some kind of comment -- the documentation is too |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
132 * vague for me to understand at this time. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
133 * + "HTTPproxy", "FTPproxy" and "mailaddr" are for reading data |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
134 * over a network, rather than from the file system. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
135 * + "opt" specifies default options for TiMidity++. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
136 * |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
137 * These are all quite useless for our version of TiMidity, so |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
138 * they can safely remain no-ops. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
139 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
140 } else if (!strcmp(w[0], "timeout")) /* "timeout" program second */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
141 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
142 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
143 * Specifies a timeout value of the program. A number of seconds |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
144 * before TiMidity kills the note. This may be useful to implement |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
145 * later, but I don't see any urgent need for it. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
146 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
147 SNDDBG(("FIXME: Implement \"timeout\" in TiMidity config.\n")); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
148 } else if (!strcmp(w[0], "copydrumset") /* "copydrumset" drumset */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
149 || !strcmp(w[0], "copybank")) /* "copybank" bank */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
150 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
151 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
152 * Copies all the settings of the specified drumset or bank to |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
153 * the current drumset or bank. May be useful later, but not a |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
154 * high priority. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
155 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
156 SNDDBG(("FIXME: Implement \"%s\" in TiMidity config.\n", w[0])); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
157 } else if (!strcmp(w[0], "undef")) /* "undef" progno */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
158 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
159 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
160 * Undefines the tone "progno" of the current tone bank (or |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
161 * drum set?). Not a high priority. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
162 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
163 SNDDBG(("FIXME: Implement \"undef\" in TiMidity config.\n")); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
164 } else if (!strcmp(w[0], "altassign")) /* "altassign" prog1 prog2 ... */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
165 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
166 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
167 * Sets the alternate assign for drum set. Whatever that's |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
168 * supposed to mean. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
169 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
170 SNDDBG(("FIXME: Implement \"altassign\" in TiMidity config.\n")); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
171 } else if (!strcmp(w[0], "soundfont") |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
172 || !strcmp(w[0], "font")) |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
173 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
174 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
175 * I can't find any documentation for these, but I guess they're |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
176 * an alternative way of loading/unloading instruments. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
177 * |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
178 * "soundfont" sf_file "remove" |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
179 * "soundfont" sf_file ["order=" order] ["cutoff=" cutoff] |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
180 * ["reso=" reso] ["amp=" amp] |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
181 * "font" "exclude" bank preset keynote |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
182 * "font" "order" order bank preset keynote |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
183 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
184 SNDDBG(("FIXME: Implmement \"%s\" in TiMidity config.\n", w[0])); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
185 } else if (!strcmp(w[0], "progbase")) |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
186 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
187 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
188 * The documentation for this makes absolutely no sense to me, but |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
189 * apparently it sets some sort of base offset for tone numbers. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
190 * Why anyone would want to do this is beyond me. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
191 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
192 SNDDBG(("FIXME: Implement \"progbase\" in TiMidity config.\n")); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
193 } else if (!strcmp(w[0], "map")) /* "map" name set1 elem1 set2 elem2 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
194 { |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
195 /* |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
196 * This extension is the one we will need to implement, as it is |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
197 * used by the "eawpats". Unfortunately I cannot find any |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
198 * documentation whatsoever for it, but it looks like it's used |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
199 * for remapping one instrument to another somehow. |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
200 */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
201 SNDDBG(("FIXME: Implement \"map\" in TiMidity config.\n")); |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
202 } |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
203 |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
204 /* Standard TiMidity config */ |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
205 |
e122de403a2d
Patch to not puke on Timidity++-specific config file directives.
Ryan C. Gordon <icculus@icculus.org>
parents:
199
diff
changeset
|
206 else if (!strcmp(w[0], "dir")) |
199 | 207 { |
208 if (words < 2) | |
209 { | |
210 SNDDBG(("%s: line %d: No directory given\n", name, line)); | |
211 return -2; | |
212 } | |
213 for (i=1; i<words; i++) | |
214 add_to_pathlist(w[i]); | |
215 } | |
216 else if (!strcmp(w[0], "source")) | |
217 { | |
218 if (words < 2) | |
219 { | |
220 SNDDBG(("%s: line %d: No file name given\n", name, line)); | |
221 return -2; | |
222 } | |
223 for (i=1; i<words; i++) | |
224 { | |
225 rcf_count++; | |
226 read_config_file(w[i]); | |
227 rcf_count--; | |
228 } | |
229 } | |
230 else if (!strcmp(w[0], "default")) | |
231 { | |
232 if (words != 2) | |
233 { | |
234 SNDDBG(("%s: line %d: Must specify exactly one patch name\n", | |
235 name, line)); | |
236 return -2; | |
237 } | |
238 strncpy(def_instr_name, w[1], 255); | |
239 def_instr_name[255]='\0'; | |
240 } | |
241 else if (!strcmp(w[0], "drumset")) | |
242 { | |
243 if (words < 2) | |
244 { | |
245 SNDDBG(("%s: line %d: No drum set number given\n", name, line)); | |
246 return -2; | |
247 } | |
248 i=atoi(w[1]); | |
249 if (i<0 || i>127) | |
250 { | |
251 SNDDBG(("%s: line %d: Drum set must be between 0 and 127\n", | |
252 name, line)); | |
253 return -2; | |
254 } | |
255 if (!master_drumset[i]) | |
256 { | |
257 master_drumset[i] = safe_malloc(sizeof(ToneBank)); | |
258 memset(master_drumset[i], 0, sizeof(ToneBank)); | |
259 master_drumset[i]->tone = safe_malloc(128 * sizeof(ToneBankElement)); | |
260 memset(master_drumset[i]->tone, 0, 128 * sizeof(ToneBankElement)); | |
261 } | |
262 bank=master_drumset[i]; | |
263 } | |
264 else if (!strcmp(w[0], "bank")) | |
265 { | |
266 if (words < 2) | |
267 { | |
268 SNDDBG(("%s: line %d: No bank number given\n", name, line)); | |
269 return -2; | |
270 } | |
271 i=atoi(w[1]); | |
272 if (i<0 || i>127) | |
273 { | |
274 SNDDBG(("%s: line %d: Tone bank must be between 0 and 127\n", | |
275 name, line)); | |
276 return -2; | |
277 } | |
278 if (!master_tonebank[i]) | |
279 { | |
280 master_tonebank[i] = safe_malloc(sizeof(ToneBank)); | |
281 memset(master_tonebank[i], 0, sizeof(ToneBank)); | |
282 master_tonebank[i]->tone = safe_malloc(128 * sizeof(ToneBankElement)); | |
283 memset(master_tonebank[i]->tone, 0, 128 * sizeof(ToneBankElement)); | |
284 } | |
285 bank=master_tonebank[i]; | |
286 } | |
287 else | |
288 { | |
289 if ((words < 2) || (*w[0] < '0' || *w[0] > '9')) | |
290 { | |
291 SNDDBG(("%s: line %d: syntax error\n", name, line)); | |
292 return -2; | |
293 } | |
294 i=atoi(w[0]); | |
295 if (i<0 || i>127) | |
296 { | |
297 SNDDBG(("%s: line %d: Program must be between 0 and 127\n", | |
298 name, line)); | |
299 return -2; | |
300 } | |
301 if (!bank) | |
302 { | |
303 SNDDBG(("%s: line %d: Must specify tone bank or drum set before assignment\n", | |
304 name, line)); | |
305 return -2; | |
306 } | |
307 if (bank->tone[i].name) | |
308 free(bank->tone[i].name); | |
309 strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]); | |
310 bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan= | |
311 bank->tone[i].strip_loop=bank->tone[i].strip_envelope= | |
312 bank->tone[i].strip_tail=-1; | |
313 | |
314 for (j=2; j<words; j++) | |
315 { | |
316 if (!(cp=strchr(w[j], '='))) | |
317 { | |
318 SNDDBG(("%s: line %d: bad patch option %s\n", name, line, w[j])); | |
319 return -2; | |
320 } | |
321 *cp++=0; | |
322 if (!strcmp(w[j], "amp")) | |
323 { | |
324 k=atoi(cp); | |
325 if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9')) | |
326 { | |
327 SNDDBG(("%s: line %d: amplification must be between 0 and %d\n", | |
328 name, line, MAX_AMPLIFICATION)); | |
329 return -2; | |
330 } | |
331 bank->tone[i].amp=k; | |
332 } | |
333 else if (!strcmp(w[j], "note")) | |
334 { | |
335 k=atoi(cp); | |
336 if ((k<0 || k>127) || (*cp < '0' || *cp > '9')) | |
337 { | |
338 SNDDBG(("%s: line %d: note must be between 0 and 127\n", | |
339 name, line)); | |
340 return -2; | |
341 } | |
342 bank->tone[i].note=k; | |
343 } | |
344 else if (!strcmp(w[j], "pan")) | |
345 { | |
346 if (!strcmp(cp, "center")) | |
347 k=64; | |
348 else if (!strcmp(cp, "left")) | |
349 k=0; | |
350 else if (!strcmp(cp, "right")) | |
351 k=127; | |
352 else | |
353 k=((atoi(cp)+100) * 100) / 157; | |
354 if ((k<0 || k>127) || (k==0 && *cp!='-' && (*cp < '0' || *cp > '9'))) | |
355 { | |
356 SNDDBG(("%s: line %d: panning must be left, right, center, or between -100 and 100\n", | |
357 name, line)); | |
358 return -2; | |
359 } | |
360 bank->tone[i].pan=k; | |
361 } | |
362 else if (!strcmp(w[j], "keep")) | |
363 { | |
364 if (!strcmp(cp, "env")) | |
365 bank->tone[i].strip_envelope=0; | |
366 else if (!strcmp(cp, "loop")) | |
367 bank->tone[i].strip_loop=0; | |
368 else | |
369 { | |
370 SNDDBG(("%s: line %d: keep must be env or loop\n", name, line)); | |
371 return -2; | |
372 } | |
373 } | |
374 else if (!strcmp(w[j], "strip")) | |
375 { | |
376 if (!strcmp(cp, "env")) | |
377 bank->tone[i].strip_envelope=1; | |
378 else if (!strcmp(cp, "loop")) | |
379 bank->tone[i].strip_loop=1; | |
380 else if (!strcmp(cp, "tail")) | |
381 bank->tone[i].strip_tail=1; | |
382 else | |
383 { | |
384 SNDDBG(("%s: line %d: strip must be env, loop, or tail\n", | |
385 name, line)); | |
386 return -2; | |
387 } | |
388 } | |
389 else | |
390 { | |
391 SNDDBG(("%s: line %d: bad patch option %s\n", name, line, w[j])); | |
392 return -2; | |
393 } | |
394 } | |
395 } | |
396 } | |
397 SDL_RWclose(rw); | |
398 return 0; | |
399 } | |
400 | |
401 int Timidity_Init() | |
402 { | |
403 /* !!! FIXME: This may be ugly, but slightly less so than requiring the | |
404 * default search path to have only one element. I think. | |
405 * | |
406 * We only need to include the likely locations for the config | |
407 * file itself since that file should contain any other directory | |
408 * that needs to be added to the search path. | |
409 */ | |
410 #ifdef WIN32 | |
411 add_to_pathlist("\\TIMIDITY"); | |
412 #else | |
413 add_to_pathlist("/usr/local/lib/timidity"); | |
414 add_to_pathlist("/etc"); | |
415 #endif | |
416 | |
417 /* Allocate memory for the standard tonebank and drumset */ | |
418 master_tonebank[0] = safe_malloc(sizeof(ToneBank)); | |
419 memset(master_tonebank[0], 0, sizeof(ToneBank)); | |
420 master_tonebank[0]->tone = safe_malloc(128 * sizeof(ToneBankElement)); | |
421 memset(master_tonebank[0]->tone, 0, 128 * sizeof(ToneBankElement)); | |
422 | |
423 master_drumset[0] = safe_malloc(sizeof(ToneBank)); | |
424 memset(master_drumset[0], 0, sizeof(ToneBank)); | |
425 master_drumset[0]->tone = safe_malloc(128 * sizeof(ToneBankElement)); | |
426 memset(master_drumset[0]->tone, 0, 128 * sizeof(ToneBankElement)); | |
427 | |
428 return read_config_file(CONFIG_FILE); | |
429 } | |
430 | |
431 MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio) | |
432 { | |
433 MidiSong *song; | |
434 Sint32 events; | |
435 int i; | |
436 | |
437 if (rw == NULL) | |
438 return NULL; | |
439 | |
440 /* Allocate memory for the song */ | |
441 song = (MidiSong *)safe_malloc(sizeof(*song)); | |
442 memset(song, 0, sizeof(*song)); | |
443 | |
444 for (i = 0; i < 128; i++) | |
445 { | |
446 if (master_tonebank[i]) | |
447 { | |
448 song->tonebank[i] = safe_malloc(sizeof(ToneBank)); | |
254 | 449 memset(song->tonebank[i], 0, sizeof(ToneBank)); |
199 | 450 song->tonebank[i]->tone = master_tonebank[i]->tone; |
451 } | |
452 if (master_drumset[i]) | |
453 { | |
454 song->drumset[i] = safe_malloc(sizeof(ToneBank)); | |
254 | 455 memset(song->drumset[i], 0, sizeof(ToneBank)); |
199 | 456 song->drumset[i]->tone = master_drumset[i]->tone; |
457 } | |
458 } | |
459 | |
460 song->amplification = DEFAULT_AMPLIFICATION; | |
461 song->voices = DEFAULT_VOICES; | |
462 song->drumchannels = DEFAULT_DRUMCHANNELS; | |
463 | |
464 song->rw = rw; | |
465 | |
466 song->rate = audio->freq; | |
467 song->encoding = 0; | |
468 if ((audio->format & 0xFF) == 16) | |
469 song->encoding |= PE_16BIT; | |
470 if (audio->format & 0x8000) | |
471 song->encoding |= PE_SIGNED; | |
472 if (audio->channels == 1) | |
473 song->encoding |= PE_MONO; | |
474 switch (audio->format) { | |
475 case AUDIO_S8: | |
476 song->write = s32tos8; | |
477 break; | |
478 case AUDIO_U8: | |
479 song->write = s32tou8; | |
480 break; | |
481 case AUDIO_S16LSB: | |
482 song->write = s32tos16l; | |
483 break; | |
484 case AUDIO_S16MSB: | |
485 song->write = s32tos16b; | |
486 break; | |
487 case AUDIO_U16LSB: | |
488 song->write = s32tou16l; | |
489 break; | |
490 default: | |
491 SNDDBG(("Unsupported audio format")); | |
492 song->write = s32tou16l; | |
493 break; | |
494 } | |
495 | |
496 song->buffer_size = audio->samples; | |
497 song->resample_buffer = safe_malloc(audio->samples * sizeof(sample_t)); | |
498 song->common_buffer = safe_malloc(audio->samples * 2 * sizeof(Sint32)); | |
499 | |
500 song->control_ratio = audio->freq / CONTROLS_PER_SECOND; | |
501 if (song->control_ratio < 1) | |
502 song->control_ratio = 1; | |
503 else if (song->control_ratio > MAX_CONTROL_RATIO) | |
504 song->control_ratio = MAX_CONTROL_RATIO; | |
505 | |
506 song->lost_notes = 0; | |
507 song->cut_notes = 0; | |
508 | |
509 song->events = read_midi_file(song, &events, &song->samples); | |
510 | |
511 /* The RWops can safely be closed at this point, but let's make that the | |
512 * responsibility of the caller. | |
513 */ | |
514 | |
515 /* Make sure everything is okay */ | |
516 if (!song->events) { | |
517 free(song); | |
518 return(NULL); | |
519 } | |
520 | |
521 song->default_instrument = 0; | |
522 song->default_program = DEFAULT_PROGRAM; | |
523 | |
524 if (*def_instr_name) | |
525 set_default_instrument(song, def_instr_name); | |
526 | |
527 load_missing_instruments(song); | |
528 | |
529 return(song); | |
530 } | |
531 | |
532 void Timidity_FreeSong(MidiSong *song) | |
533 { | |
534 int i; | |
535 | |
536 free_instruments(song); | |
537 | |
538 for (i = 0; i < 128; i++) | |
539 { | |
540 if (song->tonebank[i]) | |
541 free(song->tonebank[i]); | |
542 if (song->drumset[i]) | |
543 free(song->drumset[i]); | |
544 } | |
545 | |
546 free(song->common_buffer); | |
547 free(song->resample_buffer); | |
548 free(song->events); | |
549 free(song); | |
550 } | |
551 | |
552 void Timidity_Exit(void) | |
553 { | |
554 int i; | |
555 | |
556 for (i = 0; i < 128; i++) | |
557 { | |
558 if (master_tonebank[i]) | |
559 { | |
560 free(master_tonebank[i]->tone); | |
561 free(master_tonebank[i]); | |
562 } | |
563 if (master_drumset[i]) | |
564 { | |
565 free(master_drumset[i]->tone); | |
566 free(master_drumset[i]); | |
567 } | |
568 } | |
569 | |
570 free_pathlist(); | |
571 } |