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 }