Mercurial > SDL_sound_CoreAudio
annotate decoders/timidity/timidity.c @ 474:c66080364dff
Most decoders now report total sample play time, now. Technically, this
breaks binary compatibility with the 1.0 branch, since it extends the
Sound_Sample struct, but most (all?) programs are just passing pointers
allocated by SDL_sound around, and might be okay.
Source-level compatibility is not broken...yet! :)
--ryan.
-------- Original Message --------
Subject: SDL_sound patch: Finding total length of time of sound file.
Date: Sun, 26 Jan 2003 09:31:17 -0800 (PST)
Hi Ryan,
I am working with Eric Wing and helping him modify
SDL_sound. AS part of our efforts in improving and
enhancing SDL_sound, we like to submit this patch. We
modified the codecs to find the total time of a sound
file. Below is the explanation of the patch. The
patch is appended as an attachment to this email.
* MOTIVATION:
We needed the ability to get the total play time of a
sample (And we noticed that we're not the only ones).
Since SDL_sound blocks direct access to the specific
decoders, there is no way for a user to know this
information short of decoding the whole thing.
Because of this, we believe this will be a useful
addition, even though the accuracy may not be perfect
(subject to each decoder) or the information may not
always be available.
* CONTRIBUTORS:
Wesley Leong (modified the majority of the codecs and
verified the results)
Eric Wing (showed everyone how to do modify codec,
modified mikmod)
Wang Lam (modified a handful of codecs, researched
into specs and int overflow)
Ahilan Anantha (modified a few codecs and helped with
integer math)
* GENERAL ISSUES:
We chose the value to be milliseconds as an Sint32.
Milliseconds because that's what Sound_Seek takes as a
parameter and -1 to allow for instances/codecs where
the value could not be determined. We are
not sure if this is the final convention you want, so
we are willing to work with you on this.
We also expect the total_time field to be set on open
and never again modified by SDL_sound. Users may
access it directly much like the sample buffer and
buffer_size. We thought about recomputing the time
on DecodeAll, but since users may seek or decode small
chunks first, not all the data may be there. So this
is better done by the user. This may be good
information to document.
Currently, all the main codecs are implemented except
for QuickTime.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 08 May 2004 08:19:50 +0000 |
parents | cbc2a4ffeeec |
children |
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 | |
455
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
401 int Timidity_Init_NoConfig() |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
402 { |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
403 /* Allocate memory for the standard tonebank and drumset */ |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
404 master_tonebank[0] = safe_malloc(sizeof(ToneBank)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
405 memset(master_tonebank[0], 0, sizeof(ToneBank)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
406 master_tonebank[0]->tone = safe_malloc(128 * sizeof(ToneBankElement)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
407 memset(master_tonebank[0]->tone, 0, 128 * sizeof(ToneBankElement)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
408 |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
409 master_drumset[0] = safe_malloc(sizeof(ToneBank)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
410 memset(master_drumset[0], 0, sizeof(ToneBank)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
411 master_drumset[0]->tone = safe_malloc(128 * sizeof(ToneBankElement)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
412 memset(master_drumset[0]->tone, 0, 128 * sizeof(ToneBankElement)); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
413 |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
414 return 0; |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
415 } |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
416 |
199 | 417 int Timidity_Init() |
418 { | |
419 /* !!! FIXME: This may be ugly, but slightly less so than requiring the | |
420 * default search path to have only one element. I think. | |
421 * | |
422 * We only need to include the likely locations for the config | |
423 * file itself since that file should contain any other directory | |
424 * that needs to be added to the search path. | |
425 */ | |
426 #ifdef WIN32 | |
427 add_to_pathlist("\\TIMIDITY"); | |
428 #else | |
429 add_to_pathlist("/usr/local/lib/timidity"); | |
430 add_to_pathlist("/etc"); | |
431 #endif | |
432 | |
455
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
433 Timidity_Init_NoConfig(); |
199 | 434 |
435 return read_config_file(CONFIG_FILE); | |
436 } | |
437 | |
455
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
438 MidiSong *Timidity_LoadDLSSong(SDL_RWops *rw, DLS_Patches *patches, SDL_AudioSpec *audio) |
199 | 439 { |
440 MidiSong *song; | |
441 int i; | |
442 | |
443 if (rw == NULL) | |
444 return NULL; | |
445 | |
446 /* Allocate memory for the song */ | |
447 song = (MidiSong *)safe_malloc(sizeof(*song)); | |
448 memset(song, 0, sizeof(*song)); | |
455
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
449 song->patches = patches; |
199 | 450 |
451 for (i = 0; i < 128; i++) | |
452 { | |
453 if (master_tonebank[i]) | |
454 { | |
455 song->tonebank[i] = safe_malloc(sizeof(ToneBank)); | |
254 | 456 memset(song->tonebank[i], 0, sizeof(ToneBank)); |
199 | 457 song->tonebank[i]->tone = master_tonebank[i]->tone; |
458 } | |
459 if (master_drumset[i]) | |
460 { | |
461 song->drumset[i] = safe_malloc(sizeof(ToneBank)); | |
254 | 462 memset(song->drumset[i], 0, sizeof(ToneBank)); |
199 | 463 song->drumset[i]->tone = master_drumset[i]->tone; |
464 } | |
465 } | |
466 | |
467 song->amplification = DEFAULT_AMPLIFICATION; | |
468 song->voices = DEFAULT_VOICES; | |
469 song->drumchannels = DEFAULT_DRUMCHANNELS; | |
470 | |
471 song->rw = rw; | |
472 | |
473 song->rate = audio->freq; | |
474 song->encoding = 0; | |
475 if ((audio->format & 0xFF) == 16) | |
476 song->encoding |= PE_16BIT; | |
477 if (audio->format & 0x8000) | |
478 song->encoding |= PE_SIGNED; | |
479 if (audio->channels == 1) | |
480 song->encoding |= PE_MONO; | |
481 switch (audio->format) { | |
482 case AUDIO_S8: | |
483 song->write = s32tos8; | |
484 break; | |
485 case AUDIO_U8: | |
486 song->write = s32tou8; | |
487 break; | |
488 case AUDIO_S16LSB: | |
489 song->write = s32tos16l; | |
490 break; | |
491 case AUDIO_S16MSB: | |
492 song->write = s32tos16b; | |
493 break; | |
494 case AUDIO_U16LSB: | |
495 song->write = s32tou16l; | |
496 break; | |
497 default: | |
498 SNDDBG(("Unsupported audio format")); | |
499 song->write = s32tou16l; | |
500 break; | |
501 } | |
502 | |
503 song->buffer_size = audio->samples; | |
504 song->resample_buffer = safe_malloc(audio->samples * sizeof(sample_t)); | |
505 song->common_buffer = safe_malloc(audio->samples * 2 * sizeof(Sint32)); | |
506 | |
507 song->control_ratio = audio->freq / CONTROLS_PER_SECOND; | |
508 if (song->control_ratio < 1) | |
509 song->control_ratio = 1; | |
510 else if (song->control_ratio > MAX_CONTROL_RATIO) | |
511 song->control_ratio = MAX_CONTROL_RATIO; | |
512 | |
513 song->lost_notes = 0; | |
514 song->cut_notes = 0; | |
515 | |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
455
diff
changeset
|
516 song->events = read_midi_file(song, &(song->groomed_event_count), |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
455
diff
changeset
|
517 &song->samples); |
199 | 518 |
519 /* The RWops can safely be closed at this point, but let's make that the | |
520 * responsibility of the caller. | |
521 */ | |
522 | |
523 /* Make sure everything is okay */ | |
524 if (!song->events) { | |
525 free(song); | |
526 return(NULL); | |
527 } | |
528 | |
529 song->default_instrument = 0; | |
530 song->default_program = DEFAULT_PROGRAM; | |
531 | |
532 if (*def_instr_name) | |
533 set_default_instrument(song, def_instr_name); | |
534 | |
535 load_missing_instruments(song); | |
536 | |
537 return(song); | |
538 } | |
539 | |
455
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
540 MidiSong *Timidity_LoadSong(SDL_RWops *rw, SDL_AudioSpec *audio) |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
541 { |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
542 return Timidity_LoadDLSSong(rw, NULL, audio); |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
543 } |
cbc2a4ffeeec
* Added support for loading DLS format instruments:
hercules
parents:
411
diff
changeset
|
544 |
199 | 545 void Timidity_FreeSong(MidiSong *song) |
546 { | |
547 int i; | |
548 | |
549 free_instruments(song); | |
550 | |
551 for (i = 0; i < 128; i++) | |
552 { | |
553 if (song->tonebank[i]) | |
554 free(song->tonebank[i]); | |
555 if (song->drumset[i]) | |
556 free(song->drumset[i]); | |
557 } | |
558 | |
559 free(song->common_buffer); | |
560 free(song->resample_buffer); | |
561 free(song->events); | |
562 free(song); | |
563 } | |
564 | |
565 void Timidity_Exit(void) | |
566 { | |
408 | 567 int i, j; |
199 | 568 |
569 for (i = 0; i < 128; i++) | |
570 { | |
571 if (master_tonebank[i]) | |
572 { | |
408 | 573 ToneBankElement *e = master_tonebank[i]->tone; |
574 if (e != NULL) | |
575 { | |
576 for (j = 0; j < 128; j++) | |
577 { | |
578 if (e[j].name != NULL) | |
579 free(e[j].name); | |
580 } | |
581 free(e); | |
582 } | |
199 | 583 free(master_tonebank[i]); |
584 } | |
585 if (master_drumset[i]) | |
586 { | |
411
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
587 ToneBankElement *e = master_drumset[i]->tone; |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
588 if (e != NULL) |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
589 { |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
590 for (j = 0; j < 128; j++) |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
591 { |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
592 if (e[j].name != NULL) |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
593 free(e[j].name); |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
594 } |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
595 free(e); |
1ba14a084531
Memory leak patched by Torbj�rn Andersson.
Ryan C. Gordon <icculus@icculus.org>
parents:
408
diff
changeset
|
596 } |
199 | 597 free(master_drumset[i]); |
598 } | |
599 } | |
600 | |
601 free_pathlist(); | |
602 } |