src/audio/SDL_mixer.c
author Ryan C. Gordon
Thu, 24 Aug 2006 12:10:46 +0000
changeset 1982 3b4ce57c6215
parent 1895 c121d94672cb
child 1985 8055185ae4ed
permissions -rw-r--r--
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.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* This provides the default mixing callback for the SDL audio routines */
slouken@0
    25
slouken@1358
    26
#include "SDL_cpuinfo.h"
slouken@0
    27
#include "SDL_timer.h"
slouken@1358
    28
#include "SDL_audio.h"
slouken@0
    29
#include "SDL_sysaudio.h"
slouken@539
    30
#include "SDL_mixer_MMX.h"
slouken@574
    31
#include "SDL_mixer_MMX_VC.h"
patmandin@633
    32
#include "SDL_mixer_m68k.h"
slouken@0
    33
slouken@0
    34
/* This table is used to add two sound values together and pin
slouken@0
    35
 * the value to avoid overflow.  (used with permission from ARDI)
slouken@0
    36
 * Changed to use 0xFE instead of 0xFF for better sound quality.
slouken@0
    37
 */
slouken@1895
    38
static const Uint8 mix8[] = {
slouken@1895
    39
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    40
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    41
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    42
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    43
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    44
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    45
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    46
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    47
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    48
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    49
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
slouken@1895
    50
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
slouken@1895
    51
    0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
slouken@1895
    52
    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
slouken@1895
    53
    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
slouken@1895
    54
    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
slouken@1895
    55
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
slouken@1895
    56
    0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
slouken@1895
    57
    0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
slouken@1895
    58
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
slouken@1895
    59
    0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
slouken@1895
    60
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
slouken@1895
    61
    0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
slouken@1895
    62
    0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
slouken@1895
    63
    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
slouken@1895
    64
    0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
slouken@1895
    65
    0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
slouken@1895
    66
    0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
slouken@1895
    67
    0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
slouken@1895
    68
    0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
slouken@1895
    69
    0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
slouken@1895
    70
    0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
slouken@1895
    71
    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
slouken@1895
    72
    0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
slouken@1895
    73
    0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE,
slouken@1895
    74
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    75
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    76
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    77
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    78
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    79
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    80
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    81
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    82
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    83
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    84
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
slouken@1895
    85
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE
slouken@0
    86
};
slouken@0
    87
slouken@0
    88
/* The volume ranges from 0 - 128 */
slouken@0
    89
#define ADJUST_VOLUME(s, v)	(s = (s*v)/SDL_MIX_MAXVOLUME)
slouken@0
    90
#define ADJUST_VOLUME_U8(s, v)	(s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
slouken@0
    91
slouken@1895
    92
void
slouken@1895
    93
SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
slouken@0
    94
{
slouken@1895
    95
    /* Mix the user-level audio format */
slouken@1895
    96
    if (current_audio) {
icculus@1982
    97
        SDL_AudioFormat format;
slouken@1895
    98
        if (current_audio->convert.needed) {
slouken@1895
    99
            format = current_audio->convert.src_format;
slouken@1895
   100
        } else {
slouken@1895
   101
            format = current_audio->spec.format;
slouken@1895
   102
        }
icculus@1982
   103
        SDL_MixAudioFormat(dst, src, format, len, volume);
slouken@1895
   104
    }
icculus@1982
   105
}
icculus@1982
   106
icculus@1982
   107
icculus@1982
   108
void
icculus@1982
   109
SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
icculus@1982
   110
                   Uint32 len, int volume)
icculus@1982
   111
{
icculus@1982
   112
    if (volume == 0) {
icculus@1982
   113
        return;
icculus@1982
   114
    }
icculus@1982
   115
slouken@1895
   116
    switch (format) {
slouken@0
   117
slouken@1895
   118
    case AUDIO_U8:
slouken@1895
   119
        {
slouken@1402
   120
#if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   121
            SDL_MixAudio_m68k_U8((char *) dst, (char *) src,
slouken@1895
   122
                                 (unsigned long) len, (long) volume,
slouken@1895
   123
                                 (char *) mix8);
patmandin@633
   124
#else
slouken@1895
   125
            Uint8 src_sample;
slouken@0
   126
slouken@1895
   127
            while (len--) {
slouken@1895
   128
                src_sample = *src;
slouken@1895
   129
                ADJUST_VOLUME_U8(src_sample, volume);
slouken@1895
   130
                *dst = mix8[*dst + src_sample];
slouken@1895
   131
                ++dst;
slouken@1895
   132
                ++src;
slouken@1895
   133
            }
patmandin@633
   134
#endif
slouken@1895
   135
        }
slouken@1895
   136
        break;
slouken@0
   137
slouken@1895
   138
    case AUDIO_S8:
slouken@1895
   139
        {
slouken@1402
   140
#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   141
            if (SDL_HasMMX()) {
slouken@1895
   142
                SDL_MixAudio_MMX_S8((char *) dst, (char *) src,
slouken@1895
   143
                                    (unsigned int) len, (int) volume);
slouken@1895
   144
            } else
slouken@1442
   145
#elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   146
            if (SDL_HasMMX()) {
slouken@1895
   147
                SDL_MixAudio_MMX_S8_VC((char *) dst, (char *) src,
slouken@1895
   148
                                       (unsigned int) len, (int) volume);
slouken@1895
   149
            } else
slouken@574
   150
#endif
slouken@1402
   151
#if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   152
                SDL_MixAudio_m68k_S8((char *) dst, (char *) src,
slouken@1895
   153
                                     (unsigned long) len, (long) volume);
patmandin@633
   154
#else
slouken@1895
   155
            {
slouken@1895
   156
                Sint8 *dst8, *src8;
slouken@1895
   157
                Sint8 src_sample;
slouken@1895
   158
                int dst_sample;
slouken@1895
   159
                const int max_audioval = ((1 << (8 - 1)) - 1);
slouken@1895
   160
                const int min_audioval = -(1 << (8 - 1));
slouken@0
   161
slouken@1895
   162
                src8 = (Sint8 *) src;
slouken@1895
   163
                dst8 = (Sint8 *) dst;
slouken@1895
   164
                while (len--) {
slouken@1895
   165
                    src_sample = *src8;
slouken@1895
   166
                    ADJUST_VOLUME(src_sample, volume);
slouken@1895
   167
                    dst_sample = *dst8 + src_sample;
slouken@1895
   168
                    if (dst_sample > max_audioval) {
slouken@1895
   169
                        *dst8 = max_audioval;
slouken@1895
   170
                    } else if (dst_sample < min_audioval) {
slouken@1895
   171
                        *dst8 = min_audioval;
slouken@1895
   172
                    } else {
slouken@1895
   173
                        *dst8 = dst_sample;
slouken@1895
   174
                    }
slouken@1895
   175
                    ++dst8;
slouken@1895
   176
                    ++src8;
slouken@1895
   177
                }
slouken@1895
   178
            }
patmandin@633
   179
#endif
slouken@1895
   180
        }
slouken@1895
   181
        break;
slouken@0
   182
slouken@1895
   183
    case AUDIO_S16LSB:
slouken@1895
   184
        {
slouken@1402
   185
#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   186
            if (SDL_HasMMX()) {
slouken@1895
   187
                SDL_MixAudio_MMX_S16((char *) dst, (char *) src,
slouken@1895
   188
                                     (unsigned int) len, (int) volume);
slouken@1895
   189
            } else
slouken@1442
   190
#elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   191
            if (SDL_HasMMX()) {
slouken@1895
   192
                SDL_MixAudio_MMX_S16_VC((char *) dst, (char *) src,
slouken@1895
   193
                                        (unsigned int) len, (int) volume);
slouken@1895
   194
            } else
slouken@539
   195
#endif
slouken@1402
   196
#if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   197
                SDL_MixAudio_m68k_S16LSB((short *) dst, (short *) src,
slouken@1895
   198
                                         (unsigned long) len, (long) volume);
patmandin@633
   199
#else
slouken@1895
   200
            {
slouken@1895
   201
                Sint16 src1, src2;
slouken@1895
   202
                int dst_sample;
slouken@1895
   203
                const int max_audioval = ((1 << (16 - 1)) - 1);
slouken@1895
   204
                const int min_audioval = -(1 << (16 - 1));
slouken@0
   205
slouken@1895
   206
                len /= 2;
slouken@1895
   207
                while (len--) {
slouken@1895
   208
                    src1 = ((src[1]) << 8 | src[0]);
slouken@1895
   209
                    ADJUST_VOLUME(src1, volume);
slouken@1895
   210
                    src2 = ((dst[1]) << 8 | dst[0]);
slouken@1895
   211
                    src += 2;
slouken@1895
   212
                    dst_sample = src1 + src2;
slouken@1895
   213
                    if (dst_sample > max_audioval) {
slouken@1895
   214
                        dst_sample = max_audioval;
slouken@1895
   215
                    } else if (dst_sample < min_audioval) {
slouken@1895
   216
                        dst_sample = min_audioval;
slouken@1895
   217
                    }
slouken@1895
   218
                    dst[0] = dst_sample & 0xFF;
slouken@1895
   219
                    dst_sample >>= 8;
slouken@1895
   220
                    dst[1] = dst_sample & 0xFF;
slouken@1895
   221
                    dst += 2;
slouken@1895
   222
                }
slouken@1895
   223
            }
patmandin@633
   224
#endif
slouken@1895
   225
        }
slouken@1895
   226
        break;
slouken@0
   227
slouken@1895
   228
    case AUDIO_S16MSB:
slouken@1895
   229
        {
slouken@1402
   230
#if defined(__GNUC__) && defined(__M68000__) && defined(SDL_ASSEMBLY_ROUTINES)
slouken@1895
   231
            SDL_MixAudio_m68k_S16MSB((short *) dst, (short *) src,
slouken@1895
   232
                                     (unsigned long) len, (long) volume);
patmandin@633
   233
#else
slouken@1895
   234
            Sint16 src1, src2;
slouken@1895
   235
            int dst_sample;
slouken@1895
   236
            const int max_audioval = ((1 << (16 - 1)) - 1);
slouken@1895
   237
            const int min_audioval = -(1 << (16 - 1));
slouken@0
   238
slouken@1895
   239
            len /= 2;
slouken@1895
   240
            while (len--) {
slouken@1895
   241
                src1 = ((src[0]) << 8 | src[1]);
slouken@1895
   242
                ADJUST_VOLUME(src1, volume);
slouken@1895
   243
                src2 = ((dst[0]) << 8 | dst[1]);
slouken@1895
   244
                src += 2;
slouken@1895
   245
                dst_sample = src1 + src2;
slouken@1895
   246
                if (dst_sample > max_audioval) {
slouken@1895
   247
                    dst_sample = max_audioval;
slouken@1895
   248
                } else if (dst_sample < min_audioval) {
slouken@1895
   249
                    dst_sample = min_audioval;
slouken@1895
   250
                }
slouken@1895
   251
                dst[1] = dst_sample & 0xFF;
slouken@1895
   252
                dst_sample >>= 8;
slouken@1895
   253
                dst[0] = dst_sample & 0xFF;
slouken@1895
   254
                dst += 2;
slouken@1895
   255
            }
patmandin@633
   256
#endif
slouken@1895
   257
        }
slouken@1895
   258
        break;
slouken@0
   259
icculus@1982
   260
    case AUDIO_S32LSB:
icculus@1982
   261
        {
icculus@1982
   262
            const Uint32 *src32 = (Uint32 *) src;
icculus@1982
   263
            Uint32 *dst32 = (Uint32 *) dst;
icculus@1982
   264
            Sint32 src1, src2;
icculus@1982
   265
            Sint64 dst_sample;
icculus@1982
   266
            const Sint64 max_audioval = ((((Sint64)1) << (32 - 1)) - 1);
icculus@1982
   267
            const Sint64 min_audioval = -(((Sint64)1) << (32 - 1));
icculus@1982
   268
icculus@1982
   269
            len /= 4;
icculus@1982
   270
            while (len--) {
icculus@1982
   271
                src1 = (Sint32) SDL_SwapLE32(*src32);
icculus@1982
   272
                src32++;
icculus@1982
   273
                ADJUST_VOLUME(src1, volume);
icculus@1982
   274
                src2 = (Sint32) SDL_SwapLE32(*dst32);
icculus@1982
   275
                dst_sample = src1 + src2;
icculus@1982
   276
                if (dst_sample > max_audioval) {
icculus@1982
   277
                    dst_sample = max_audioval;
icculus@1982
   278
                } else if (dst_sample < min_audioval) {
icculus@1982
   279
                    dst_sample = min_audioval;
icculus@1982
   280
                }
icculus@1982
   281
                *(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample));
icculus@1982
   282
            }
icculus@1982
   283
        }
icculus@1982
   284
        break;
icculus@1982
   285
icculus@1982
   286
    case AUDIO_S32MSB:
icculus@1982
   287
        {
icculus@1982
   288
            const Uint32 *src32 = (Uint32 *) src;
icculus@1982
   289
            Uint32 *dst32 = (Uint32 *) dst;
icculus@1982
   290
            Sint32 src1, src2;
icculus@1982
   291
            Sint64 dst_sample;
icculus@1982
   292
            const Sint64 max_audioval = ((((Sint64)1) << (32 - 1)) - 1);
icculus@1982
   293
            const Sint64 min_audioval = -(((Sint64)1) << (32 - 1));
icculus@1982
   294
icculus@1982
   295
            len /= 4;
icculus@1982
   296
            while (len--) {
icculus@1982
   297
                src1 = (Sint32) SDL_SwapBE32(*src32);
icculus@1982
   298
                src32++;
icculus@1982
   299
                ADJUST_VOLUME(src1, volume);
icculus@1982
   300
                src2 = (Sint32) SDL_SwapBE32(*dst32);
icculus@1982
   301
                dst_sample = src1 + src2;
icculus@1982
   302
                if (dst_sample > max_audioval) {
icculus@1982
   303
                    dst_sample = max_audioval;
icculus@1982
   304
                } else if (dst_sample < min_audioval) {
icculus@1982
   305
                    dst_sample = min_audioval;
icculus@1982
   306
                }
icculus@1982
   307
                *(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample));
icculus@1982
   308
            }
icculus@1982
   309
        }
icculus@1982
   310
        break;
icculus@1982
   311
icculus@1982
   312
    case AUDIO_F32LSB:
icculus@1982
   313
        {
icculus@1982
   314
            const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
icculus@1982
   315
            const float fvolume = (float) volume;
icculus@1982
   316
            const float *src32 = (float *) src;
icculus@1982
   317
            float *dst32 = (float *) dst;
icculus@1982
   318
            float src1, src2;
icculus@1982
   319
            double dst_sample;
icculus@1982
   320
            /* !!! FIXME: are these right? */
icculus@1982
   321
            const double max_audioval = 3.40282347e+38F;
icculus@1982
   322
            const double min_audioval = -3.40282347e+38F;
icculus@1982
   323
icculus@1982
   324
            /* !!! FIXME: this is a little nasty. */
icculus@1982
   325
            union { float f; Uint32 ui32; } cvt;
icculus@1982
   326
icculus@1982
   327
            len /= 4;
icculus@1982
   328
            while (len--) {
icculus@1982
   329
                cvt.f = *(src32++);
icculus@1982
   330
                cvt.ui32 = SDL_SwapLE32(cvt.ui32);
icculus@1982
   331
                src1 = ((cvt.f * fvolume) * fmaxvolume);
icculus@1982
   332
icculus@1982
   333
                cvt.f = *dst32;
icculus@1982
   334
                cvt.ui32 = SDL_SwapLE32(cvt.ui32);
icculus@1982
   335
                src2 = cvt.f;
icculus@1982
   336
icculus@1982
   337
                dst_sample = src1 + src2;
icculus@1982
   338
                if (dst_sample > max_audioval) {
icculus@1982
   339
                    dst_sample = max_audioval;
icculus@1982
   340
                } else if (dst_sample < min_audioval) {
icculus@1982
   341
                    dst_sample = min_audioval;
icculus@1982
   342
                }
icculus@1982
   343
                cvt.f = ((float) dst_sample);
icculus@1982
   344
                cvt.ui32 = SDL_SwapLE32(cvt.ui32);
icculus@1982
   345
                *(dst32++) = cvt.f;
icculus@1982
   346
            }
icculus@1982
   347
        }
icculus@1982
   348
        break;
icculus@1982
   349
icculus@1982
   350
    case AUDIO_F32MSB:
icculus@1982
   351
        {
icculus@1982
   352
            const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
icculus@1982
   353
            const float fvolume = (float) volume;
icculus@1982
   354
            const float *src32 = (float *) src;
icculus@1982
   355
            float *dst32 = (float *) dst;
icculus@1982
   356
            float src1, src2;
icculus@1982
   357
            double dst_sample;
icculus@1982
   358
            /* !!! FIXME: are these right? */
icculus@1982
   359
            const double max_audioval = 3.40282347e+38F;
icculus@1982
   360
            const double min_audioval = -3.40282347e+38F;
icculus@1982
   361
icculus@1982
   362
            /* !!! FIXME: this is a little nasty. */
icculus@1982
   363
            union { float f; Uint32 ui32; } cvt;
icculus@1982
   364
icculus@1982
   365
            len /= 4;
icculus@1982
   366
            while (len--) {
icculus@1982
   367
                cvt.f = *(src32++);
icculus@1982
   368
                cvt.ui32 = SDL_SwapBE32(cvt.ui32);
icculus@1982
   369
                src1 = ((cvt.f * fvolume) * fmaxvolume);
icculus@1982
   370
icculus@1982
   371
                cvt.f = *dst32;
icculus@1982
   372
                cvt.ui32 = SDL_SwapBE32(cvt.ui32);
icculus@1982
   373
                src2 = cvt.f;
icculus@1982
   374
icculus@1982
   375
                dst_sample = src1 + src2;
icculus@1982
   376
                if (dst_sample > max_audioval) {
icculus@1982
   377
                    dst_sample = max_audioval;
icculus@1982
   378
                } else if (dst_sample < min_audioval) {
icculus@1982
   379
                    dst_sample = min_audioval;
icculus@1982
   380
                }
icculus@1982
   381
                cvt.f = ((float) dst_sample);
icculus@1982
   382
                cvt.ui32 = SDL_SwapBE32(cvt.ui32);
icculus@1982
   383
                *(dst32++) = cvt.f;
icculus@1982
   384
            }
icculus@1982
   385
        }
icculus@1982
   386
        break;
icculus@1982
   387
slouken@1895
   388
    default:                   /* If this happens... FIXME! */
slouken@1895
   389
        SDL_SetError("SDL_MixAudio(): unknown audio format");
slouken@1895
   390
        return;
slouken@1895
   391
    }
slouken@0
   392
}
slouken@574
   393
slouken@1895
   394
/* vi: set ts=4 sw=4 expandtab: */