1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* This provides the default mixing callback for the SDL audio routines */ 25 26 #include "SDL_cpuinfo.h" 27 #include "SDL_timer.h" 28 #include "SDL_audio.h" 29 #include "SDL_sysaudio.h" 30 #include "SDL_mixer_MMX.h" 31 #include "SDL_mixer_MMX_VC.h" 32 #include "SDL_mixer_m68k.h" 33 34 /* This table is used to add two sound values together and pin 35 * the value to avoid overflow. (used with permission from ARDI) 36 * Changed to use 0xFE instead of 0xFF for better sound quality. 37 */ 38 static const Uint8 mix8[] = 39 { 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, 0x00, 0x00, 0x00, 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 52 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 53 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 54 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 55 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 56 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 57 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 58 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 59 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 60 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 61 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 62 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 63 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 64 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 65 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 66 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 67 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 68 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 69 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 70 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 71 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 72 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 73 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 74 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 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, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 85 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 86 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE 87 }; 88 89 /* The volume ranges from 0 - 128 */ 90 #define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME) 91 #define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) 92 93 void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) 94 { 95 Uint16 format; 96 97 if ( volume == 0 ) { 98 return; 99 } 100 /* Mix the user-level audio format */ 101 if ( current_audio ) { 102 if ( current_audio->convert.needed ) { 103 format = current_audio->convert.src_format; 104 } else { 105 format = current_audio->spec.format; 106 } 107 } else { 108 /* HACK HACK HACK */ 109 format = AUDIO_S16; 110 } 111 switch (format) { 112 113 case AUDIO_U8: { 114 #if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) 115 SDL_MixAudio_m68k_U8((char*)dst,(char*)src,(unsigned long)len,(long)volume,(char *)mix8); 116 #else 117 Uint8 src_sample; 118 119 while ( len-- ) { 120 src_sample = *src; 121 ADJUST_VOLUME_U8(src_sample, volume); 122 *dst = mix8[*dst+src_sample]; 123 ++dst; 124 ++src; 125 } 126 #endif 127 } 128 break; 129 130 case AUDIO_S8: { 131 #if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ 132 #if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) 133 if (SDL_HasMMX()) 134 { 135 SDL_MixAudio_MMX_S8((char*)dst,(char*)src,(unsigned int)len,(int)volume); 136 } 137 else 138 #elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) 139 if (SDL_HasMMX()) 140 { 141 SDL_MixAudio_MMX_S8_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume); 142 } 143 else 144 #endif 145 #endif 146 147 #if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) 148 SDL_MixAudio_m68k_S8((char*)dst,(char*)src,(unsigned long)len,(long)volume); 149 #else 150 { 151 Sint8 *dst8, *src8; 152 Sint8 src_sample; 153 int dst_sample; 154 const int max_audioval = ((1<<(8-1))-1); 155 const int min_audioval = -(1<<(8-1)); 156 157 src8 = (Sint8 *)src; 158 dst8 = (Sint8 *)dst; 159 while ( len-- ) { 160 src_sample = *src8; 161 ADJUST_VOLUME(src_sample, volume); 162 dst_sample = *dst8 + src_sample; 163 if ( dst_sample > max_audioval ) { 164 *dst8 = max_audioval; 165 } else 166 if ( dst_sample < min_audioval ) { 167 *dst8 = min_audioval; 168 } else { 169 *dst8 = dst_sample; 170 } 171 ++dst8; 172 ++src8; 173 } 174 } 175 #endif 176 } 177 break; 178 179 case AUDIO_S16LSB: { 180 #if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ 181 #if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) 182 if (SDL_HasMMX()) 183 { 184 SDL_MixAudio_MMX_S16((char*)dst,(char*)src,(unsigned int)len,(int)volume); 185 } 186 else 187 #elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) 188 if (SDL_HasMMX()) 189 { 190 SDL_MixAudio_MMX_S16_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume); 191 } 192 else 193 #endif 194 #endif 195 196 #if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) 197 SDL_MixAudio_m68k_S16LSB((short*)dst,(short*)src,(unsigned long)len,(long)volume); 198 #else 199 { 200 Sint16 src1, src2; 201 int dst_sample; 202 const int max_audioval = ((1<<(16-1))-1); 203 const int min_audioval = -(1<<(16-1)); 204 205 len /= 2; 206 while ( len-- ) { 207 src1 = ((src[1])<<8|src[0]); 208 ADJUST_VOLUME(src1, volume); 209 src2 = ((dst[1])<<8|dst[0]); 210 src += 2; 211 dst_sample = src1+src2; 212 if ( dst_sample > max_audioval ) { 213 dst_sample = max_audioval; 214 } else 215 if ( dst_sample < min_audioval ) { 216 dst_sample = min_audioval; 217 } 218 dst[0] = dst_sample&0xFF; 219 dst_sample >>= 8; 220 dst[1] = dst_sample&0xFF; 221 dst += 2; 222 } 223 } 224 #endif 225 } 226 break; 227 228 case AUDIO_S16MSB: { 229 #if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) 230 SDL_MixAudio_m68k_S16MSB((short*)dst,(short*)src,(unsigned long)len,(long)volume); 231 #else 232 Sint16 src1, src2; 233 int dst_sample; 234 const int max_audioval = ((1<<(16-1))-1); 235 const int min_audioval = -(1<<(16-1)); 236 237 len /= 2; 238 while ( len-- ) { 239 src1 = ((src[0])<<8|src[1]); 240 ADJUST_VOLUME(src1, volume); 241 src2 = ((dst[0])<<8|dst[1]); 242 src += 2; 243 dst_sample = src1+src2; 244 if ( dst_sample > max_audioval ) { 245 dst_sample = max_audioval; 246 } else 247 if ( dst_sample < min_audioval ) { 248 dst_sample = min_audioval; 249 } 250 dst[1] = dst_sample&0xFF; 251 dst_sample >>= 8; 252 dst[0] = dst_sample&0xFF; 253 dst += 2; 254 } 255 #endif 256 } 257 break; 258 259 default: /* If this happens... FIXME! */ 260 SDL_SetError("SDL_MixAudio(): unknown audio format"); 261 return; 262 } 263 } 264 265