Atlas - SDL_mixer.c

Home / ext / SDL / src / audio Lines: 1 | Size: 10813 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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_sysaudio.h" 26 27/* This table is used to add two sound values together and pin 28 * the value to avoid overflow. (used with permission from ARDI) 29 */ 30static const Uint8 mix8[] = { 31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x02, 0x03, 43 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 44 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 45 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 46 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 47 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 48 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 49 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 50 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 51 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 52 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 53 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 54 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 55 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 56 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 57 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 58 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 59 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 60 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 61 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 62 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 63 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 64 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 65 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF, 66 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 67 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 68 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 69 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 70 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 71 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 72 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 73 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 74 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 75 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 76 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 77 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 78}; 79 80// The volume ranges from 0 - 128 81#define MIX_MAXVOLUME 128 82#define ADJUST_VOLUME(type, s, v) ((s) = (type)(((s) * (v)) / MIX_MAXVOLUME)) 83#define ADJUST_VOLUME_U8(s, v) ((s) = (Uint8)(((((s) - 128) * (v)) / MIX_MAXVOLUME) + 128)) 84 85// !!! FIXME: This needs some SIMD magic. 86// !!! FIXME: Add fast-path for volume = 1 87// !!! FIXME: Use larger scales for 16-bit/32-bit integers 88 89bool SDL_MixAudio(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, Uint32 len, float fvolume) 90{ 91 int volume = (int)SDL_roundf(fvolume * MIX_MAXVOLUME); 92 93 if (volume == 0) { 94 return true; 95 } 96 97 switch (format) { 98 99 case SDL_AUDIO_U8: 100 { 101 Uint8 src_sample; 102 103 while (len--) { 104 src_sample = *src; 105 ADJUST_VOLUME_U8(src_sample, volume); 106 *dst = mix8[*dst + src_sample]; 107 ++dst; 108 ++src; 109 } 110 } break; 111 112 case SDL_AUDIO_S8: 113 { 114 Sint8 *dst8, *src8; 115 Sint8 src_sample; 116 int dst_sample; 117 const int max_audioval = SDL_MAX_SINT8; 118 const int min_audioval = SDL_MIN_SINT8; 119 120 src8 = (Sint8 *)src; 121 dst8 = (Sint8 *)dst; 122 while (len--) { 123 src_sample = *src8; 124 ADJUST_VOLUME(Sint8, src_sample, volume); 125 dst_sample = *dst8 + src_sample; 126 if (dst_sample > max_audioval) { 127 dst_sample = max_audioval; 128 } else if (dst_sample < min_audioval) { 129 dst_sample = min_audioval; 130 } 131 *dst8 = (Sint8)dst_sample; 132 ++dst8; 133 ++src8; 134 } 135 } break; 136 137 case SDL_AUDIO_S16LE: 138 { 139 Sint16 src1, src2; 140 int dst_sample; 141 const int max_audioval = SDL_MAX_SINT16; 142 const int min_audioval = SDL_MIN_SINT16; 143 144 len /= 2; 145 while (len--) { 146 src1 = SDL_Swap16LE(*(Sint16 *)src); 147 ADJUST_VOLUME(Sint16, src1, volume); 148 src2 = SDL_Swap16LE(*(Sint16 *)dst); 149 src += 2; 150 dst_sample = src1 + src2; 151 if (dst_sample > max_audioval) { 152 dst_sample = max_audioval; 153 } else if (dst_sample < min_audioval) { 154 dst_sample = min_audioval; 155 } 156 *(Sint16 *)dst = SDL_Swap16LE((Sint16)dst_sample); 157 dst += 2; 158 } 159 } break; 160 161 case SDL_AUDIO_S16BE: 162 { 163 Sint16 src1, src2; 164 int dst_sample; 165 const int max_audioval = SDL_MAX_SINT16; 166 const int min_audioval = SDL_MIN_SINT16; 167 168 len /= 2; 169 while (len--) { 170 src1 = SDL_Swap16BE(*(Sint16 *)src); 171 ADJUST_VOLUME(Sint16, src1, volume); 172 src2 = SDL_Swap16BE(*(Sint16 *)dst); 173 src += 2; 174 dst_sample = src1 + src2; 175 if (dst_sample > max_audioval) { 176 dst_sample = max_audioval; 177 } else if (dst_sample < min_audioval) { 178 dst_sample = min_audioval; 179 } 180 *(Sint16 *)dst = SDL_Swap16BE((Sint16)dst_sample); 181 dst += 2; 182 } 183 } break; 184 185 case SDL_AUDIO_S32LE: 186 { 187 const Uint32 *src32 = (Uint32 *)src; 188 Uint32 *dst32 = (Uint32 *)dst; 189 Sint64 src1, src2; 190 Sint64 dst_sample; 191 const Sint64 max_audioval = SDL_MAX_SINT32; 192 const Sint64 min_audioval = SDL_MIN_SINT32; 193 194 len /= 4; 195 while (len--) { 196 src1 = (Sint64)((Sint32)SDL_Swap32LE(*src32)); 197 src32++; 198 ADJUST_VOLUME(Sint64, src1, volume); 199 src2 = (Sint64)((Sint32)SDL_Swap32LE(*dst32)); 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 *(dst32++) = SDL_Swap32LE((Uint32)((Sint32)dst_sample)); 207 } 208 } break; 209 210 case SDL_AUDIO_S32BE: 211 { 212 const Uint32 *src32 = (Uint32 *)src; 213 Uint32 *dst32 = (Uint32 *)dst; 214 Sint64 src1, src2; 215 Sint64 dst_sample; 216 const Sint64 max_audioval = SDL_MAX_SINT32; 217 const Sint64 min_audioval = SDL_MIN_SINT32; 218 219 len /= 4; 220 while (len--) { 221 src1 = (Sint64)((Sint32)SDL_Swap32BE(*src32)); 222 src32++; 223 ADJUST_VOLUME(Sint64, src1, volume); 224 src2 = (Sint64)((Sint32)SDL_Swap32BE(*dst32)); 225 dst_sample = src1 + src2; 226 if (dst_sample > max_audioval) { 227 dst_sample = max_audioval; 228 } else if (dst_sample < min_audioval) { 229 dst_sample = min_audioval; 230 } 231 *(dst32++) = SDL_Swap32BE((Uint32)((Sint32)dst_sample)); 232 } 233 } break; 234 235 case SDL_AUDIO_F32LE: 236 { 237 const float *src32 = (float *)src; 238 float *dst32 = (float *)dst; 239 float src1, src2; 240 float dst_sample; 241 const float max_audioval = 1.0f; 242 const float min_audioval = -1.0f; 243 244 len /= 4; 245 while (len--) { 246 src1 = SDL_SwapFloatLE(*src32) * fvolume; 247 src2 = SDL_SwapFloatLE(*dst32); 248 src32++; 249 250 dst_sample = src1 + src2; 251 if (dst_sample > max_audioval) { 252 dst_sample = max_audioval; 253 } else if (dst_sample < min_audioval) { 254 dst_sample = min_audioval; 255 } 256 *(dst32++) = SDL_SwapFloatLE(dst_sample); 257 } 258 } break; 259 260 case SDL_AUDIO_F32BE: 261 { 262 const float *src32 = (float *)src; 263 float *dst32 = (float *)dst; 264 float src1, src2; 265 float dst_sample; 266 const float max_audioval = 1.0f; 267 const float min_audioval = -1.0f; 268 269 len /= 4; 270 while (len--) { 271 src1 = SDL_SwapFloatBE(*src32) * fvolume; 272 src2 = SDL_SwapFloatBE(*dst32); 273 src32++; 274 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_SwapFloatBE(dst_sample); 282 } 283 } break; 284 285 default: // If this happens... FIXME! 286 return SDL_SetError("SDL_MixAudio(): unknown audio format"); 287 } 288 289 return true; 290} 291
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.