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