Mercurial > sdl-ios-xcode
comparison src/audio/SDL_mixer.c @ 1982:3b4ce57c6215
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 24 Aug 2006 12:10:46 +0000 |
parents | c121d94672cb |
children | 8055185ae4ed |
comparison
equal
deleted
inserted
replaced
1981:3f21778e7433 | 1982:3b4ce57c6215 |
---|---|
90 #define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) | 90 #define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) |
91 | 91 |
92 void | 92 void |
93 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) | 93 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) |
94 { | 94 { |
95 Uint16 format; | |
96 | |
97 if (volume == 0) { | |
98 return; | |
99 } | |
100 /* Mix the user-level audio format */ | 95 /* Mix the user-level audio format */ |
101 if (current_audio) { | 96 if (current_audio) { |
97 SDL_AudioFormat format; | |
102 if (current_audio->convert.needed) { | 98 if (current_audio->convert.needed) { |
103 format = current_audio->convert.src_format; | 99 format = current_audio->convert.src_format; |
104 } else { | 100 } else { |
105 format = current_audio->spec.format; | 101 format = current_audio->spec.format; |
106 } | 102 } |
107 } else { | 103 SDL_MixAudioFormat(dst, src, format, len, volume); |
108 /* HACK HACK HACK */ | |
109 format = AUDIO_S16; | |
110 } | 104 } |
105 } | |
106 | |
107 | |
108 void | |
109 SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format, | |
110 Uint32 len, int volume) | |
111 { | |
112 if (volume == 0) { | |
113 return; | |
114 } | |
115 | |
111 switch (format) { | 116 switch (format) { |
112 | 117 |
113 case AUDIO_U8: | 118 case AUDIO_U8: |
114 { | 119 { |
115 #if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES) | 120 #if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES) |
250 } | 255 } |
251 #endif | 256 #endif |
252 } | 257 } |
253 break; | 258 break; |
254 | 259 |
260 case AUDIO_S32LSB: | |
261 { | |
262 const Uint32 *src32 = (Uint32 *) src; | |
263 Uint32 *dst32 = (Uint32 *) dst; | |
264 Sint32 src1, src2; | |
265 Sint64 dst_sample; | |
266 const Sint64 max_audioval = ((((Sint64)1) << (32 - 1)) - 1); | |
267 const Sint64 min_audioval = -(((Sint64)1) << (32 - 1)); | |
268 | |
269 len /= 4; | |
270 while (len--) { | |
271 src1 = (Sint32) SDL_SwapLE32(*src32); | |
272 src32++; | |
273 ADJUST_VOLUME(src1, volume); | |
274 src2 = (Sint32) SDL_SwapLE32(*dst32); | |
275 dst_sample = src1 + src2; | |
276 if (dst_sample > max_audioval) { | |
277 dst_sample = max_audioval; | |
278 } else if (dst_sample < min_audioval) { | |
279 dst_sample = min_audioval; | |
280 } | |
281 *(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample)); | |
282 } | |
283 } | |
284 break; | |
285 | |
286 case AUDIO_S32MSB: | |
287 { | |
288 const Uint32 *src32 = (Uint32 *) src; | |
289 Uint32 *dst32 = (Uint32 *) dst; | |
290 Sint32 src1, src2; | |
291 Sint64 dst_sample; | |
292 const Sint64 max_audioval = ((((Sint64)1) << (32 - 1)) - 1); | |
293 const Sint64 min_audioval = -(((Sint64)1) << (32 - 1)); | |
294 | |
295 len /= 4; | |
296 while (len--) { | |
297 src1 = (Sint32) SDL_SwapBE32(*src32); | |
298 src32++; | |
299 ADJUST_VOLUME(src1, volume); | |
300 src2 = (Sint32) SDL_SwapBE32(*dst32); | |
301 dst_sample = src1 + src2; | |
302 if (dst_sample > max_audioval) { | |
303 dst_sample = max_audioval; | |
304 } else if (dst_sample < min_audioval) { | |
305 dst_sample = min_audioval; | |
306 } | |
307 *(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample)); | |
308 } | |
309 } | |
310 break; | |
311 | |
312 case AUDIO_F32LSB: | |
313 { | |
314 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME); | |
315 const float fvolume = (float) volume; | |
316 const float *src32 = (float *) src; | |
317 float *dst32 = (float *) dst; | |
318 float src1, src2; | |
319 double dst_sample; | |
320 /* !!! FIXME: are these right? */ | |
321 const double max_audioval = 3.40282347e+38F; | |
322 const double min_audioval = -3.40282347e+38F; | |
323 | |
324 /* !!! FIXME: this is a little nasty. */ | |
325 union { float f; Uint32 ui32; } cvt; | |
326 | |
327 len /= 4; | |
328 while (len--) { | |
329 cvt.f = *(src32++); | |
330 cvt.ui32 = SDL_SwapLE32(cvt.ui32); | |
331 src1 = ((cvt.f * fvolume) * fmaxvolume); | |
332 | |
333 cvt.f = *dst32; | |
334 cvt.ui32 = SDL_SwapLE32(cvt.ui32); | |
335 src2 = cvt.f; | |
336 | |
337 dst_sample = src1 + src2; | |
338 if (dst_sample > max_audioval) { | |
339 dst_sample = max_audioval; | |
340 } else if (dst_sample < min_audioval) { | |
341 dst_sample = min_audioval; | |
342 } | |
343 cvt.f = ((float) dst_sample); | |
344 cvt.ui32 = SDL_SwapLE32(cvt.ui32); | |
345 *(dst32++) = cvt.f; | |
346 } | |
347 } | |
348 break; | |
349 | |
350 case AUDIO_F32MSB: | |
351 { | |
352 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME); | |
353 const float fvolume = (float) volume; | |
354 const float *src32 = (float *) src; | |
355 float *dst32 = (float *) dst; | |
356 float src1, src2; | |
357 double dst_sample; | |
358 /* !!! FIXME: are these right? */ | |
359 const double max_audioval = 3.40282347e+38F; | |
360 const double min_audioval = -3.40282347e+38F; | |
361 | |
362 /* !!! FIXME: this is a little nasty. */ | |
363 union { float f; Uint32 ui32; } cvt; | |
364 | |
365 len /= 4; | |
366 while (len--) { | |
367 cvt.f = *(src32++); | |
368 cvt.ui32 = SDL_SwapBE32(cvt.ui32); | |
369 src1 = ((cvt.f * fvolume) * fmaxvolume); | |
370 | |
371 cvt.f = *dst32; | |
372 cvt.ui32 = SDL_SwapBE32(cvt.ui32); | |
373 src2 = cvt.f; | |
374 | |
375 dst_sample = src1 + src2; | |
376 if (dst_sample > max_audioval) { | |
377 dst_sample = max_audioval; | |
378 } else if (dst_sample < min_audioval) { | |
379 dst_sample = min_audioval; | |
380 } | |
381 cvt.f = ((float) dst_sample); | |
382 cvt.ui32 = SDL_SwapBE32(cvt.ui32); | |
383 *(dst32++) = cvt.f; | |
384 } | |
385 } | |
386 break; | |
387 | |
255 default: /* If this happens... FIXME! */ | 388 default: /* If this happens... FIXME! */ |
256 SDL_SetError("SDL_MixAudio(): unknown audio format"); | 389 SDL_SetError("SDL_MixAudio(): unknown audio format"); |
257 return; | 390 return; |
258 } | 391 } |
259 } | 392 } |