diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/snd_mem.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/snd_mem.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/snd_mem.c b/apps/plugins/sdl/progs/quake/snd_mem.c new file mode 100644 index 0000000000..71e32aa056 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/snd_mem.c | |||
@@ -0,0 +1,341 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License | ||
6 | as published by the Free Software Foundation; either version 2 | ||
7 | of the License, or (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | |||
19 | */ | ||
20 | // snd_mem.c: sound caching | ||
21 | |||
22 | #include "quakedef.h" | ||
23 | |||
24 | int cache_full_cycle; | ||
25 | |||
26 | byte *S_Alloc (int size); | ||
27 | |||
28 | /* | ||
29 | ================ | ||
30 | ResampleSfx | ||
31 | ================ | ||
32 | */ | ||
33 | void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) | ||
34 | { | ||
35 | int outcount; | ||
36 | int srcsample; | ||
37 | float stepscale; | ||
38 | int i; | ||
39 | int sample, samplefrac, fracstep; | ||
40 | sfxcache_t *sc; | ||
41 | |||
42 | sc = Cache_Check (&sfx->cache); | ||
43 | if (!sc) | ||
44 | return; | ||
45 | |||
46 | stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 | ||
47 | |||
48 | outcount = sc->length / stepscale; | ||
49 | sc->length = outcount; | ||
50 | if (sc->loopstart != -1) | ||
51 | sc->loopstart = sc->loopstart / stepscale; | ||
52 | |||
53 | sc->speed = shm->speed; | ||
54 | if (loadas8bit.value) | ||
55 | sc->width = 1; | ||
56 | else | ||
57 | sc->width = inwidth; | ||
58 | sc->stereo = 0; | ||
59 | |||
60 | // resample / decimate to the current source rate | ||
61 | |||
62 | if (stepscale == 1 && inwidth == 1 && sc->width == 1) | ||
63 | { | ||
64 | // fast special case | ||
65 | for (i=0 ; i<outcount ; i++) | ||
66 | ((signed char *)sc->data)[i] | ||
67 | = (int)( (unsigned char)(data[i]) - 128); | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | // general case | ||
72 | samplefrac = 0; | ||
73 | fracstep = stepscale*256; | ||
74 | for (i=0 ; i<outcount ; i++) | ||
75 | { | ||
76 | srcsample = samplefrac >> 8; | ||
77 | samplefrac += fracstep; | ||
78 | if (inwidth == 2) | ||
79 | sample = LittleShort ( ((short *)data)[srcsample] ); | ||
80 | else | ||
81 | sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; | ||
82 | if (sc->width == 2) | ||
83 | ((short *)sc->data)[i] = sample; | ||
84 | else | ||
85 | ((signed char *)sc->data)[i] = sample >> 8; | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | //============================================================================= | ||
91 | |||
92 | /* | ||
93 | ============== | ||
94 | S_LoadSound | ||
95 | ============== | ||
96 | */ | ||
97 | sfxcache_t *S_LoadSound (sfx_t *s) | ||
98 | { | ||
99 | char namebuffer[256]; | ||
100 | byte *data; | ||
101 | wavinfo_t info; | ||
102 | int len; | ||
103 | float stepscale; | ||
104 | sfxcache_t *sc; | ||
105 | byte stackbuf[1*1024]; // avoid dirtying the cache heap | ||
106 | |||
107 | // see if still in memory | ||
108 | sc = Cache_Check (&s->cache); | ||
109 | if (sc) | ||
110 | return sc; | ||
111 | |||
112 | //Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); | ||
113 | // load it in | ||
114 | Q_strcpy(namebuffer, "sound/"); | ||
115 | Q_strcat(namebuffer, s->name); | ||
116 | |||
117 | // Con_Printf ("loading %s\n",namebuffer); | ||
118 | |||
119 | data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); | ||
120 | |||
121 | if (!data) | ||
122 | { | ||
123 | Con_Printf ("Couldn't load %s\n", namebuffer); | ||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | info = GetWavinfo (s->name, data, com_filesize); | ||
128 | if (info.channels != 1) | ||
129 | { | ||
130 | Con_Printf ("%s is a stereo sample\n",s->name); | ||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | stepscale = (float)info.rate / shm->speed; | ||
135 | len = info.samples / stepscale; | ||
136 | |||
137 | len = len * info.width * info.channels; | ||
138 | |||
139 | sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); | ||
140 | if (!sc) | ||
141 | return NULL; | ||
142 | |||
143 | sc->length = info.samples; | ||
144 | sc->loopstart = info.loopstart; | ||
145 | sc->speed = info.rate; | ||
146 | sc->width = info.width; | ||
147 | sc->stereo = info.channels; | ||
148 | |||
149 | ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); | ||
150 | |||
151 | return sc; | ||
152 | } | ||
153 | |||
154 | |||
155 | |||
156 | /* | ||
157 | =============================================================================== | ||
158 | |||
159 | WAV loading | ||
160 | |||
161 | =============================================================================== | ||
162 | */ | ||
163 | |||
164 | |||
165 | byte *data_p; | ||
166 | byte *iff_end; | ||
167 | byte *last_chunk; | ||
168 | byte *iff_data; | ||
169 | int iff_chunk_len; | ||
170 | |||
171 | |||
172 | short GetLittleShort(void) | ||
173 | { | ||
174 | short val = 0; | ||
175 | val = *data_p; | ||
176 | val = val + (*(data_p+1)<<8); | ||
177 | data_p += 2; | ||
178 | return val; | ||
179 | } | ||
180 | |||
181 | int GetLittleLong(void) | ||
182 | { | ||
183 | int val = 0; | ||
184 | val = *data_p; | ||
185 | val = val + (*(data_p+1)<<8); | ||
186 | val = val + (*(data_p+2)<<16); | ||
187 | val = val + (*(data_p+3)<<24); | ||
188 | data_p += 4; | ||
189 | return val; | ||
190 | } | ||
191 | |||
192 | void FindNextChunk(char *name) | ||
193 | { | ||
194 | while (1) | ||
195 | { | ||
196 | data_p=last_chunk; | ||
197 | |||
198 | if (data_p >= iff_end) | ||
199 | { // didn't find the chunk | ||
200 | data_p = NULL; | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | data_p += 4; | ||
205 | iff_chunk_len = GetLittleLong(); | ||
206 | if (iff_chunk_len < 0) | ||
207 | { | ||
208 | data_p = NULL; | ||
209 | return; | ||
210 | } | ||
211 | // if (iff_chunk_len > 1024*1024) | ||
212 | // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); | ||
213 | data_p -= 8; | ||
214 | last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); | ||
215 | if (!Q_strncmp(data_p, name, 4)) | ||
216 | return; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | void FindChunk(char *name) | ||
221 | { | ||
222 | last_chunk = iff_data; | ||
223 | FindNextChunk (name); | ||
224 | } | ||
225 | |||
226 | |||
227 | void DumpChunks(void) | ||
228 | { | ||
229 | char str[5]; | ||
230 | |||
231 | str[4] = 0; | ||
232 | data_p=iff_data; | ||
233 | do | ||
234 | { | ||
235 | memcpy (str, data_p, 4); | ||
236 | data_p += 4; | ||
237 | iff_chunk_len = GetLittleLong(); | ||
238 | Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); | ||
239 | data_p += (iff_chunk_len + 1) & ~1; | ||
240 | } while (data_p < iff_end); | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | ============ | ||
245 | GetWavinfo | ||
246 | ============ | ||
247 | */ | ||
248 | wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) | ||
249 | { | ||
250 | wavinfo_t info; | ||
251 | int i; | ||
252 | int format; | ||
253 | int samples; | ||
254 | |||
255 | memset (&info, 0, sizeof(info)); | ||
256 | |||
257 | if (!wav) | ||
258 | return info; | ||
259 | |||
260 | iff_data = wav; | ||
261 | iff_end = wav + wavlength; | ||
262 | |||
263 | // find "RIFF" chunk | ||
264 | FindChunk("RIFF"); | ||
265 | if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) | ||
266 | { | ||
267 | Con_Printf("Missing RIFF/WAVE chunks\n"); | ||
268 | return info; | ||
269 | } | ||
270 | |||
271 | // get "fmt " chunk | ||
272 | iff_data = data_p + 12; | ||
273 | // DumpChunks (); | ||
274 | |||
275 | FindChunk("fmt "); | ||
276 | if (!data_p) | ||
277 | { | ||
278 | Con_Printf("Missing fmt chunk\n"); | ||
279 | return info; | ||
280 | } | ||
281 | data_p += 8; | ||
282 | format = GetLittleShort(); | ||
283 | if (format != 1) | ||
284 | { | ||
285 | Con_Printf("Microsoft PCM format only\n"); | ||
286 | return info; | ||
287 | } | ||
288 | |||
289 | info.channels = GetLittleShort(); | ||
290 | info.rate = GetLittleLong(); | ||
291 | data_p += 4+2; | ||
292 | info.width = GetLittleShort() / 8; | ||
293 | |||
294 | // get cue chunk | ||
295 | FindChunk("cue "); | ||
296 | if (data_p) | ||
297 | { | ||
298 | data_p += 32; | ||
299 | info.loopstart = GetLittleLong(); | ||
300 | // Con_Printf("loopstart=%d\n", sfx->loopstart); | ||
301 | |||
302 | // if the next chunk is a LIST chunk, look for a cue length marker | ||
303 | FindNextChunk ("LIST"); | ||
304 | if (data_p) | ||
305 | { | ||
306 | if (!strncmp (data_p + 28, "mark", 4)) | ||
307 | { // this is not a proper parse, but it works with cooledit... | ||
308 | data_p += 24; | ||
309 | i = GetLittleLong (); // samples in loop | ||
310 | info.samples = info.loopstart + i; | ||
311 | // Con_Printf("looped length: %i\n", i); | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | else | ||
316 | info.loopstart = -1; | ||
317 | |||
318 | // find data chunk | ||
319 | FindChunk("data"); | ||
320 | if (!data_p) | ||
321 | { | ||
322 | Con_Printf("Missing data chunk\n"); | ||
323 | return info; | ||
324 | } | ||
325 | |||
326 | data_p += 4; | ||
327 | samples = GetLittleLong () / info.width; | ||
328 | |||
329 | if (info.samples) | ||
330 | { | ||
331 | if (samples < info.samples) | ||
332 | Sys_Error ("Sound %s has a bad loop length", name); | ||
333 | } | ||
334 | else | ||
335 | info.samples = samples; | ||
336 | |||
337 | info.dataofs = data_p - wav; | ||
338 | |||
339 | return info; | ||
340 | } | ||
341 | |||