src/audio/SDL_mixer.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 22 Feb 2015 23:21:32 +0100
changeset 9373 679eb3986e37
parent 8149 681eb46b8ac4
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Emscripten: Fixed out of range joystick device index after joystick disconnect.

After disconnecting a joystick the remaining kept their original device index.
This was not correct because the device index must be a number between 0 and
SDL_NumJoysticks(). It was fixed with ideas from SDL's joystick implementation
for Android. Some range checks were removed as the caller already checks them.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 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_internal.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 
    30 /* This table is used to add two sound values together and pin
    31  * the value to avoid overflow.  (used with permission from ARDI)
    32  * Changed to use 0xFE instead of 0xFF for better sound quality.
    33  */
    34 static const Uint8 mix8[] = {
    35     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    36     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    37     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    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, 0x01, 0x02, 0x03,
    47     0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
    48     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    49     0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
    50     0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
    51     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
    52     0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
    53     0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    54     0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
    55     0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    56     0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
    57     0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
    58     0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
    59     0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
    60     0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
    61     0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
    62     0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
    63     0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
    64     0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
    65     0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
    66     0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
    67     0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
    68     0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
    69     0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE,
    70     0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
    71     0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
    72     0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 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
    82 };
    83 
    84 /* The volume ranges from 0 - 128 */
    85 #define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME)
    86 #define ADJUST_VOLUME_U8(s, v)  (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
    87 
    88 
    89 void
    90 SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
    91                    Uint32 len, int volume)
    92 {
    93     if (volume == 0) {
    94         return;
    95     }
    96 
    97     switch (format) {
    98 
    99     case AUDIO_U8:
   100         {
   101 #if defined(__GNUC__) && defined(__M68000__) && !defined(__mcoldfire__) && defined(SDL_ASSEMBLY_ROUTINES)
   102             SDL_MixAudio_m68k_U8((char *) dst, (char *) src,
   103                                  (unsigned long) len, (long) volume,
   104                                  (char *) mix8);
   105 #else
   106             Uint8 src_sample;
   107 
   108             while (len--) {
   109                 src_sample = *src;
   110                 ADJUST_VOLUME_U8(src_sample, volume);
   111                 *dst = mix8[*dst + src_sample];
   112                 ++dst;
   113                 ++src;
   114             }
   115 #endif
   116         }
   117         break;
   118 
   119     case AUDIO_S8:
   120         {
   121             Sint8 *dst8, *src8;
   122             Sint8 src_sample;
   123             int dst_sample;
   124             const int max_audioval = ((1 << (8 - 1)) - 1);
   125             const int min_audioval = -(1 << (8 - 1));
   126 
   127             src8 = (Sint8 *) src;
   128             dst8 = (Sint8 *) dst;
   129             while (len--) {
   130                 src_sample = *src8;
   131                 ADJUST_VOLUME(src_sample, volume);
   132                 dst_sample = *dst8 + src_sample;
   133                 if (dst_sample > max_audioval) {
   134                     *dst8 = max_audioval;
   135                 } else if (dst_sample < min_audioval) {
   136                     *dst8 = min_audioval;
   137                 } else {
   138                     *dst8 = dst_sample;
   139                 }
   140                 ++dst8;
   141                 ++src8;
   142             }
   143         }
   144         break;
   145 
   146     case AUDIO_S16LSB:
   147         {
   148             Sint16 src1, src2;
   149             int dst_sample;
   150             const int max_audioval = ((1 << (16 - 1)) - 1);
   151             const int min_audioval = -(1 << (16 - 1));
   152 
   153             len /= 2;
   154             while (len--) {
   155                 src1 = ((src[1]) << 8 | src[0]);
   156                 ADJUST_VOLUME(src1, volume);
   157                 src2 = ((dst[1]) << 8 | dst[0]);
   158                 src += 2;
   159                 dst_sample = src1 + src2;
   160                 if (dst_sample > max_audioval) {
   161                     dst_sample = max_audioval;
   162                 } else if (dst_sample < min_audioval) {
   163                     dst_sample = min_audioval;
   164                 }
   165                 dst[0] = dst_sample & 0xFF;
   166                 dst_sample >>= 8;
   167                 dst[1] = dst_sample & 0xFF;
   168                 dst += 2;
   169             }
   170         }
   171         break;
   172 
   173     case AUDIO_S16MSB:
   174         {
   175 #if defined(__GNUC__) && defined(__M68000__) && !defined(__mcoldfire__) && defined(SDL_ASSEMBLY_ROUTINES)
   176             SDL_MixAudio_m68k_S16MSB((short *) dst, (short *) src,
   177                                      (unsigned long) len, (long) volume);
   178 #else
   179             Sint16 src1, src2;
   180             int dst_sample;
   181             const int max_audioval = ((1 << (16 - 1)) - 1);
   182             const int min_audioval = -(1 << (16 - 1));
   183 
   184             len /= 2;
   185             while (len--) {
   186                 src1 = ((src[0]) << 8 | src[1]);
   187                 ADJUST_VOLUME(src1, volume);
   188                 src2 = ((dst[0]) << 8 | dst[1]);
   189                 src += 2;
   190                 dst_sample = src1 + src2;
   191                 if (dst_sample > max_audioval) {
   192                     dst_sample = max_audioval;
   193                 } else if (dst_sample < min_audioval) {
   194                     dst_sample = min_audioval;
   195                 }
   196                 dst[1] = dst_sample & 0xFF;
   197                 dst_sample >>= 8;
   198                 dst[0] = dst_sample & 0xFF;
   199                 dst += 2;
   200             }
   201 #endif
   202         }
   203         break;
   204 
   205     case AUDIO_S32LSB:
   206         {
   207             const Uint32 *src32 = (Uint32 *) src;
   208             Uint32 *dst32 = (Uint32 *) dst;
   209             Sint64 src1, src2;
   210             Sint64 dst_sample;
   211             const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
   212             const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
   213 
   214             len /= 4;
   215             while (len--) {
   216                 src1 = (Sint64) ((Sint32) SDL_SwapLE32(*src32));
   217                 src32++;
   218                 ADJUST_VOLUME(src1, volume);
   219                 src2 = (Sint64) ((Sint32) SDL_SwapLE32(*dst32));
   220                 dst_sample = src1 + src2;
   221                 if (dst_sample > max_audioval) {
   222                     dst_sample = max_audioval;
   223                 } else if (dst_sample < min_audioval) {
   224                     dst_sample = min_audioval;
   225                 }
   226                 *(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample));
   227             }
   228         }
   229         break;
   230 
   231     case AUDIO_S32MSB:
   232         {
   233             const Uint32 *src32 = (Uint32 *) src;
   234             Uint32 *dst32 = (Uint32 *) dst;
   235             Sint64 src1, src2;
   236             Sint64 dst_sample;
   237             const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
   238             const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
   239 
   240             len /= 4;
   241             while (len--) {
   242                 src1 = (Sint64) ((Sint32) SDL_SwapBE32(*src32));
   243                 src32++;
   244                 ADJUST_VOLUME(src1, volume);
   245                 src2 = (Sint64) ((Sint32) SDL_SwapBE32(*dst32));
   246                 dst_sample = src1 + src2;
   247                 if (dst_sample > max_audioval) {
   248                     dst_sample = max_audioval;
   249                 } else if (dst_sample < min_audioval) {
   250                     dst_sample = min_audioval;
   251                 }
   252                 *(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample));
   253             }
   254         }
   255         break;
   256 
   257     case AUDIO_F32LSB:
   258         {
   259             const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
   260             const float fvolume = (float) volume;
   261             const float *src32 = (float *) src;
   262             float *dst32 = (float *) dst;
   263             float src1, src2;
   264             double dst_sample;
   265             /* !!! FIXME: are these right? */
   266             const double max_audioval = 3.402823466e+38F;
   267             const double min_audioval = -3.402823466e+38F;
   268 
   269             len /= 4;
   270             while (len--) {
   271                 src1 = ((SDL_SwapFloatLE(*src32) * fvolume) * fmaxvolume);
   272                 src2 = SDL_SwapFloatLE(*dst32);
   273                 src32++;
   274 
   275                 dst_sample = ((double) src1) + ((double) 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_SwapFloatLE((float) dst_sample);
   282             }
   283         }
   284         break;
   285 
   286     case AUDIO_F32MSB:
   287         {
   288             const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
   289             const float fvolume = (float) volume;
   290             const float *src32 = (float *) src;
   291             float *dst32 = (float *) dst;
   292             float src1, src2;
   293             double dst_sample;
   294             /* !!! FIXME: are these right? */
   295             const double max_audioval = 3.402823466e+38F;
   296             const double min_audioval = -3.402823466e+38F;
   297 
   298             len /= 4;
   299             while (len--) {
   300                 src1 = ((SDL_SwapFloatBE(*src32) * fvolume) * fmaxvolume);
   301                 src2 = SDL_SwapFloatBE(*dst32);
   302                 src32++;
   303 
   304                 dst_sample = ((double) src1) + ((double) src2);
   305                 if (dst_sample > max_audioval) {
   306                     dst_sample = max_audioval;
   307                 } else if (dst_sample < min_audioval) {
   308                     dst_sample = min_audioval;
   309                 }
   310                 *(dst32++) = SDL_SwapFloatBE((float) dst_sample);
   311             }
   312         }
   313         break;
   314 
   315     default:                   /* If this happens... FIXME! */
   316         SDL_SetError("SDL_MixAudio(): unknown audio format");
   317         return;
   318     }
   319 }
   320 
   321 /* vi: set ts=4 sw=4 expandtab: */