Mercurial > SDL_sound_CoreAudio
annotate SDL_sound.c @ 20:d4ac6ce1360e
Added WAV entries.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 19 Sep 2001 08:30:14 +0000 |
parents | cc2c32349380 |
children | ddc3614c9042 |
rev | line source |
---|---|
4 | 1 /* |
2 * SDL_sound -- An abstract sound format decoding API. | |
3 * Copyright (C) 2001 Ryan C. Gordon. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2.1 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 | |
20 /** | |
21 * This file implements the core API, which is relatively simple. | |
22 * The real meat of SDL_sound is in the decoders directory. | |
23 * | |
24 * Documentation is in SDL_sound.h ... It's verbose, honest. :) | |
25 * | |
26 * Please see the file LICENSE in the source's root directory. | |
27 * | |
28 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org) | |
29 */ | |
30 | |
31 | |
32 #include <stdio.h> | |
33 #include <stdlib.h> | |
34 #include <string.h> | |
35 #include <assert.h> | |
36 #include <ctype.h> | |
37 | |
38 #include "SDL.h" | |
39 #include "SDL_sound.h" | |
40 | |
41 #define __SDL_SOUND_INTERNAL__ | |
42 #include "SDL_sound_internal.h" | |
43 | |
44 | |
45 /* The various decoder drivers... */ | |
46 | |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
47 #if (defined SOUND_SUPPORTS_MP3) |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
48 extern const Sound_DecoderFunctions __Sound_DecoderFunctions_MP3; |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
49 #endif |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
50 |
20 | 51 #if (defined SOUND_SUPPORTS_WAV) |
52 extern const Sound_DecoderFunctions __Sound_DecoderFunctions_WAV; | |
53 #endif | |
54 | |
4 | 55 #if (defined SOUND_SUPPORTS_VOC) |
56 extern const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC; | |
57 #endif | |
58 | |
59 #if (defined SOUND_SUPPORTS_RAW) | |
60 extern const Sound_DecoderFunctions __Sound_DecoderFunctions_RAW; | |
61 #endif | |
62 | |
63 static const Sound_DecoderFunctions *decoderFuncs[] = | |
64 { | |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
65 #if (defined SOUND_SUPPORTS_MP3) |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
66 &__Sound_DecoderFunctions_MP3, |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
67 #endif |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
68 |
20 | 69 #if (defined SOUND_SUPPORTS_WAV) |
70 &__Sound_DecoderFunctions_WAV, | |
71 #endif | |
72 | |
4 | 73 #if (defined SOUND_SUPPORTS_VOC) |
74 &__Sound_DecoderFunctions_VOC, | |
75 #endif | |
76 | |
77 #if (defined SOUND_SUPPORTS_RAW) | |
78 &__Sound_DecoderFunctions_RAW, | |
79 #endif | |
80 | |
81 NULL | |
82 }; | |
83 | |
84 | |
85 | |
86 /* General SDL_sound state ... */ | |
87 | |
88 static int initialized = 0; | |
89 static Sound_Sample *samplesList = NULL; /* this is a linked list. */ | |
90 static const Sound_DecoderInfo **available_decoders = NULL; | |
91 | |
92 | |
93 /* functions ... */ | |
94 | |
95 void Sound_GetLinkedVersion(Sound_Version *ver) | |
96 { | |
97 if (ver != NULL) | |
98 { | |
99 ver->major = SOUND_VER_MAJOR; | |
100 ver->minor = SOUND_VER_MINOR; | |
101 ver->patch = SOUND_VER_PATCH; | |
102 } /* if */ | |
103 } /* Sound_GetLinkedVersion */ | |
104 | |
105 | |
106 int Sound_Init(void) | |
107 { | |
108 size_t i; | |
109 BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0); | |
110 samplesList = NULL; | |
111 | |
112 SDL_Init(SDL_INIT_AUDIO); | |
113 | |
114 for (i = 0; decoderFuncs[i] != NULL; i++) | |
115 ; /* do nothing. */ | |
116 | |
117 i++; | |
118 available_decoders = (const Sound_DecoderInfo **) | |
119 malloc(i * sizeof (Sound_DecoderInfo *)); | |
120 BAIL_IF_MACRO(available_decoders == NULL, ERR_OUT_OF_MEMORY, 0); | |
121 | |
122 for (i = 0; decoderFuncs[i] != NULL; i++) | |
123 available_decoders[i] = &decoderFuncs[i]->info; | |
124 | |
125 initialized = 1; | |
126 return(1); | |
127 } /* Sound_Init */ | |
128 | |
129 | |
130 int Sound_Quit(void) | |
131 { | |
132 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); | |
133 | |
134 while (((volatile Sound_Sample *) samplesList) != NULL) | |
135 Sound_FreeSample(samplesList); | |
136 | |
137 if (available_decoders != NULL) | |
138 free(available_decoders); | |
139 available_decoders = NULL; | |
140 | |
141 initialized = 0; | |
142 | |
143 return(1); | |
144 } /* Sound_Quit */ | |
145 | |
146 | |
147 const Sound_DecoderInfo **Sound_AvailableDecoders(void) | |
148 { | |
149 return(available_decoders); /* READ. ONLY. */ | |
150 } /* Sound_AvailableDecoders */ | |
151 | |
152 | |
153 const char *Sound_GetError(void) | |
154 { | |
155 return(SDL_GetError()); | |
156 } /* Sound_GetError */ | |
157 | |
158 | |
159 void Sound_ClearError(void) | |
160 { | |
161 SDL_ClearError(); | |
162 } /* Sound_ClearError */ | |
163 | |
164 | |
165 /* | |
166 * This is declared in the internal header. | |
167 */ | |
168 void Sound_SetError(const char *err) | |
169 { | |
170 if (err != NULL) | |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
171 { |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
172 _D(("Sound_SetError(\"%s\");\n", err)); |
4 | 173 SDL_SetError(err); |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
174 } /* if */ |
4 | 175 } /* Sound_SetError */ |
176 | |
177 | |
178 /* | |
179 * -ansi and -pedantic flags prevent use of strcasecmp() on Linux, and | |
180 * I honestly don't want to mess around with figuring out if a given | |
181 * platform has "strcasecmp", "stricmp", or | |
182 * "compare_two_damned_strings_case_insensitive", which I hear is in the | |
183 * next release of Carbon. :) This is exported so decoders may use it if | |
184 * they like. | |
185 */ | |
186 int __Sound_strcasecmp(const char *x, const char *y) | |
187 { | |
188 int ux, uy; | |
189 | |
190 do | |
191 { | |
192 ux = toupper((int) *x); | |
193 uy = toupper((int) *y); | |
194 if (ux > uy) | |
195 return(1); | |
196 else if (ux < uy) | |
197 return(-1); | |
198 x++; | |
199 y++; | |
200 } while ((ux) && (uy)); | |
201 | |
202 return(0); | |
203 } /* __Sound_strcasecmp */ | |
204 | |
205 | |
206 /* | |
207 * Allocate a Sound_Sample, and fill in most of its fields. Those that need | |
208 * to be filled in later, by a decoder, will be initialized to zero. | |
209 */ | |
210 static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired, | |
211 Uint32 bufferSize) | |
212 { | |
213 Sound_Sample *retval = malloc(sizeof (Sound_Sample)); | |
214 Sound_SampleInternal *internal = malloc(sizeof (Sound_SampleInternal)); | |
215 if ((retval == NULL) || (internal == NULL)) | |
216 { | |
217 Sound_SetError(ERR_OUT_OF_MEMORY); | |
218 if (retval) | |
219 free(retval); | |
220 if (internal) | |
221 free(internal); | |
222 | |
223 return(NULL); | |
224 } /* if */ | |
225 | |
226 memset(retval, '\0', sizeof (Sound_Sample)); | |
227 memset(internal, '\0', sizeof (Sound_SampleInternal)); | |
228 | |
229 assert(bufferSize > 0); | |
230 retval->buffer = malloc(bufferSize); /* pure ugly. */ | |
231 if (!retval->buffer) | |
232 { | |
233 Sound_SetError(ERR_OUT_OF_MEMORY); | |
234 free(internal); | |
235 free(retval); | |
236 return(NULL); | |
237 } /* if */ | |
238 memset(retval->buffer, '\0', bufferSize); | |
239 retval->buffer_size = bufferSize; | |
240 | |
241 if (desired != NULL) | |
242 memcpy(&retval->desired, desired, sizeof (Sound_AudioInfo)); | |
243 | |
244 internal->rw = rw; | |
245 retval->opaque = internal; | |
246 return(retval); | |
247 } /* alloc_sample */ | |
248 | |
249 | |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
250 #if (defined DEBUG_CHATTER) |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
251 static __inline__ const char *fmt_to_str(Uint16 fmt) |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
252 { |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
253 switch(fmt) |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
254 { |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
255 case AUDIO_U8: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
256 return("U8"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
257 case AUDIO_S8: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
258 return("S8"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
259 case AUDIO_U16LSB: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
260 return("U16LSB"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
261 case AUDIO_S16LSB: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
262 return("S16LSB"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
263 case AUDIO_U16MSB: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
264 return("U16MSB"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
265 case AUDIO_S16MSB: |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
266 return("S16MSB"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
267 } /* switch */ |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
268 |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
269 return("Unknown"); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
270 } /* fmt_to_str */ |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
271 #endif |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
272 |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
273 |
4 | 274 /* |
275 * The bulk of the Sound_NewSample() work is done here... | |
276 * Ask the specified decoder to handle the data in (rw), and if | |
277 * so, construct the Sound_Sample. Otherwise, try to wind (rw)'s stream | |
278 * back to where it was, and return false. | |
279 * | |
280 * !!! FIXME: This is big, ugly, nasty, and smelly. | |
281 */ | |
282 static int init_sample(const Sound_DecoderFunctions *funcs, | |
283 Sound_Sample *sample, const char *ext, | |
284 Sound_AudioInfo *_desired) | |
285 { | |
286 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
287 int pos = SDL_RWtell(internal->rw); /* !!! FIXME: Int? Really? */ | |
288 Sound_AudioInfo desired; | |
289 | |
290 /* fill in the funcs for this decoder... */ | |
291 sample->decoder = &funcs->info; | |
292 internal->funcs = funcs; | |
293 if (!funcs->open(sample, ext)) | |
294 { | |
295 SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */ | |
296 return(0); | |
297 } /* if */ | |
298 | |
299 /* success; we've got a decoder! */ | |
300 | |
301 /* Now we need to set up the conversion buffer... */ | |
302 | |
303 memcpy(&desired, (_desired != NULL) ? _desired : &sample->actual, | |
304 sizeof (Sound_AudioInfo)); | |
305 | |
306 if (SDL_BuildAudioCVT(&internal->sdlcvt, | |
307 sample->actual.format, | |
308 sample->actual.channels, | |
309 (int) sample->actual.rate, /* !!! FIXME: Int? Really? */ | |
310 desired.format, | |
311 desired.channels, | |
312 (int) desired.rate) == -1) /* !!! FIXME: Int? Really? */ | |
313 { | |
314 Sound_SetError(SDL_GetError()); | |
315 funcs->close(sample); | |
316 SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */ | |
317 return(0); | |
318 } /* if */ | |
319 | |
320 if (internal->sdlcvt.len_mult > 1) | |
321 { | |
322 void *rc = realloc(sample->buffer, | |
323 sample->buffer_size * internal->sdlcvt.len_mult); | |
324 if (rc == NULL) | |
325 { | |
326 funcs->close(sample); | |
327 SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */ | |
328 return(0); | |
329 } /* if */ | |
330 | |
331 sample->buffer = rc; | |
332 } /* if */ | |
333 | |
334 /* these pointers are all one and the same. */ | |
335 memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo)); | |
336 internal->sdlcvt.buf = internal->buffer = sample->buffer; | |
337 internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult; | |
338 internal->sdlcvt.len = internal->buffer_size; | |
339 | |
340 /* Prepend our new Sound_Sample to the samplesList... */ | |
341 if (samplesList != NULL) | |
342 { | |
343 internal->next = samplesList; | |
344 if (samplesList != NULL) | |
345 internal->prev = sample; | |
346 } /* if */ | |
347 samplesList = sample; | |
348 | |
10
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
349 _D(("New sample DESIRED format: %s format, %d rate, %d channels.\n", |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
350 fmt_to_str(sample->desired.format), |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
351 sample->desired.rate, |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
352 sample->desired.channels)); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
353 |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
354 _D(("New sample ACTUAL format: %s format, %d rate, %d channels.\n", |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
355 fmt_to_str(sample->actual.format), |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
356 sample->actual.rate, |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
357 sample->actual.channels)); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
358 |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
359 _D(("On-the-fly conversion: %s.\n", |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
360 internal->sdlcvt.needed ? "ENABLED" : "DISABLED")); |
cc2c32349380
Some debugging output, and MP3 and VOC entries, added.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
361 |
4 | 362 return(1); |
363 } /* init_sample */ | |
364 | |
365 | |
366 Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, | |
367 Sound_AudioInfo *desired, Uint32 bSize) | |
368 { | |
369 size_t i; | |
370 Sound_Sample *retval; | |
371 | |
372 /* sanity checks. */ | |
373 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL); | |
374 BAIL_IF_MACRO(rw == NULL, ERR_INVALID_ARGUMENT, NULL); | |
375 | |
376 retval = alloc_sample(rw, desired, bSize); | |
377 if (!retval) | |
378 return(NULL); /* alloc_sample() sets error message... */ | |
379 | |
380 if (ext != NULL) | |
381 { | |
382 for (i = 0; decoderFuncs[i] != NULL; i++) | |
383 { | |
384 const char *decoderExt = decoderFuncs[i]->info.extension; | |
385 if (__Sound_strcasecmp(decoderExt, ext) == 0) | |
386 { | |
387 if (init_sample(decoderFuncs[i], retval, ext, desired)) | |
388 return(retval); | |
389 } /* if */ | |
390 } /* for */ | |
391 } /* if */ | |
392 | |
393 /* no direct extension match? Try everything we've got... */ | |
394 for (i = 0; decoderFuncs[i] != NULL; i++) | |
395 { | |
396 if (init_sample(decoderFuncs[i], retval, ext, desired)) | |
397 return(retval); | |
398 } /* for */ | |
399 | |
400 /* nothing could handle the sound data... */ | |
401 free(retval->opaque); | |
402 if (retval->buffer != NULL) | |
403 free(retval->buffer); | |
404 free(retval); | |
405 SDL_RWclose(rw); | |
406 Sound_SetError(ERR_UNSUPPORTED_FORMAT); | |
407 return(NULL); | |
408 } /* Sound_NewSample */ | |
409 | |
410 | |
411 Sound_Sample *Sound_NewSampleFromFile(const char *filename, | |
412 Sound_AudioInfo *desired, | |
413 Uint32 bufferSize) | |
414 { | |
415 const char *ext; | |
416 SDL_RWops *rw; | |
417 | |
418 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL); | |
419 BAIL_IF_MACRO(filename == NULL, ERR_INVALID_ARGUMENT, NULL); | |
420 | |
421 ext = strrchr(filename, '.'); | |
422 rw = SDL_RWFromFile(filename, "rb"); | |
423 BAIL_IF_MACRO(rw == NULL, SDL_GetError(), NULL); | |
424 | |
425 if (ext != NULL) | |
426 ext++; | |
427 | |
428 return(Sound_NewSample(rw, ext, desired, bufferSize)); | |
429 } /* Sound_NewSampleFromFile */ | |
430 | |
431 | |
432 void Sound_FreeSample(Sound_Sample *sample) | |
433 { | |
434 Sound_SampleInternal *internal; | |
435 | |
436 if (!initialized) | |
437 { | |
438 Sound_SetError(ERR_NOT_INITIALIZED); | |
439 return; | |
440 } /* if */ | |
441 | |
442 if (sample == NULL) | |
443 { | |
444 Sound_SetError(ERR_INVALID_ARGUMENT); | |
445 return; | |
446 } /* if */ | |
447 | |
448 internal = (Sound_SampleInternal *) sample->opaque; | |
449 | |
450 internal->funcs->close(sample); | |
451 | |
452 /* update the samplesList... */ | |
453 if (internal->prev != NULL) | |
454 { | |
455 Sound_SampleInternal *prevInternal; | |
456 prevInternal = (Sound_SampleInternal *) internal->prev->opaque; | |
457 prevInternal->next = internal->next; | |
458 } /* if */ | |
459 else | |
460 { | |
461 assert(samplesList == sample); | |
462 samplesList = internal->next; | |
463 } /* else */ | |
464 | |
465 if (internal->next != NULL) | |
466 { | |
467 Sound_SampleInternal *nextInternal; | |
468 nextInternal = (Sound_SampleInternal *) internal->next->opaque; | |
469 nextInternal->prev = internal->prev; | |
470 } /* if */ | |
471 | |
472 /* nuke it... */ | |
473 if (internal->rw != NULL) /* this condition is a "just in case" thing. */ | |
474 SDL_RWclose(internal->rw); | |
475 assert(internal->buffer != NULL); | |
476 if (internal->buffer != sample->buffer) | |
477 free(internal->buffer); | |
478 free(internal); | |
479 if (sample->buffer != NULL) | |
480 free(sample->buffer); | |
481 free(sample); | |
482 } /* Sound_FreeSample */ | |
483 | |
484 | |
485 int Sound_SetBufferSize(Sound_Sample *sample, Uint32 newSize) | |
486 { | |
487 void *newBuf = NULL; | |
488 Sound_SampleInternal *internal = NULL; | |
489 | |
490 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); | |
491 BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0); | |
492 internal = ((Sound_SampleInternal *) sample->opaque); | |
493 newBuf = realloc(sample->buffer, newSize * internal->sdlcvt.len_mult); | |
494 BAIL_IF_MACRO(newBuf == NULL, ERR_OUT_OF_MEMORY, 0); | |
495 | |
496 internal->sdlcvt.buf = internal->buffer = sample->buffer = newBuf; | |
497 sample->buffer_size = newSize; | |
498 internal->buffer_size = newSize / internal->sdlcvt.len_mult; | |
499 internal->sdlcvt.len = internal->buffer_size; | |
500 | |
501 return(1); | |
502 } /* Sound_SetBufferSize */ | |
503 | |
504 | |
505 Uint32 Sound_Decode(Sound_Sample *sample) | |
506 { | |
507 Sound_SampleInternal *internal = NULL; | |
508 Uint32 retval = 0; | |
509 | |
510 /* a boatload of sanity checks... */ | |
511 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); | |
512 BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0); | |
513 BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0); | |
514 BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0); | |
515 | |
516 internal = (Sound_SampleInternal *) sample->opaque; | |
517 | |
518 assert(sample->buffer != NULL); | |
519 assert(sample->buffer_size > 0); | |
520 assert(internal->buffer != NULL); | |
521 assert(internal->buffer_size > 0); | |
522 | |
523 /* reset EAGAIN. Decoder can flip it back on if it needs to. */ | |
524 sample->flags &= !SOUND_SAMPLEFLAG_EAGAIN; | |
525 | |
526 retval = internal->funcs->read(sample); | |
527 if (internal->sdlcvt.needed) | |
528 { | |
529 internal->sdlcvt.len = retval; | |
530 SDL_ConvertAudio(&internal->sdlcvt); | |
531 retval *= internal->sdlcvt.len_mult; | |
532 } /* if */ | |
533 | |
534 return(retval); | |
535 } /* Sound_Decode */ | |
536 | |
537 | |
538 Uint32 Sound_DecodeAll(Sound_Sample *sample) | |
539 { | |
540 Sound_SampleInternal *internal = NULL; | |
541 void *buf = NULL; | |
542 Uint32 newBufSize = 0; | |
543 | |
544 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); | |
545 | |
546 internal = (Sound_SampleInternal *) sample->opaque; | |
547 | |
548 while ( ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) && | |
549 ((sample->flags & SOUND_SAMPLEFLAG_ERROR) == 0) ) | |
550 { | |
551 void *ptr = realloc(buf, newBufSize + sample->buffer_size); | |
552 if (ptr == NULL) | |
553 { | |
554 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
555 Sound_SetError(ERR_OUT_OF_MEMORY); | |
556 } /* if */ | |
557 else | |
558 { | |
559 Uint32 br = Sound_Decode(sample); | |
560 memcpy( ((char *) buf) + newBufSize, sample->buffer, br ); | |
561 newBufSize += br; | |
562 } /* else */ | |
563 } /* while */ | |
564 | |
565 free(sample->buffer); | |
566 sample->buffer = internal->buffer = internal->sdlcvt.buf = buf; | |
567 sample->buffer_size = newBufSize; | |
568 internal->buffer_size = newBufSize / internal->sdlcvt.len_mult; | |
569 internal->sdlcvt.len_mult = internal->buffer_size; | |
570 | |
571 return(newBufSize); | |
572 } /* Sound_DecodeAll */ | |
573 | |
574 | |
575 /* end of SDL_sound.c ... */ | |
576 |