1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 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
SDL_MixAudioFormat(Uint8 * dst,const Uint8 * src,SDL_AudioFormat format,Uint32 len,int volume)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_U16LSB:
206 {
207 Uint16 src1, src2;
208 int dst_sample;
209 const int max_audioval = 0xFFFF;
210
211 len /= 2;
212 while (len--) {
213 src1 = ((src[1]) << 8 | src[0]);
214 ADJUST_VOLUME(src1, volume);
215 src2 = ((dst[1]) << 8 | dst[0]);
216 src += 2;
217 dst_sample = src1 + src2;
218 if (dst_sample > max_audioval) {
219 dst_sample = max_audioval;
220 }
221 dst[0] = dst_sample & 0xFF;
222 dst_sample >>= 8;
223 dst[1] = dst_sample & 0xFF;
224 dst += 2;
225 }
226 }
227 break;
228
229 case AUDIO_U16MSB:
230 {
231 Uint16 src1, src2;
232 int dst_sample;
233 const int max_audioval = 0xFFFF;
234
235 len /= 2;
236 while (len--) {
237 src1 = ((src[0]) << 8 | src[1]);
238 ADJUST_VOLUME(src1, volume);
239 src2 = ((dst[0]) << 8 | dst[1]);
240 src += 2;
241 dst_sample = src1 + src2;
242 if (dst_sample > max_audioval) {
243 dst_sample = max_audioval;
244 }
245 dst[1] = dst_sample & 0xFF;
246 dst_sample >>= 8;
247 dst[0] = dst_sample & 0xFF;
248 dst += 2;
249 }
250 }
251 break;
252
253 case AUDIO_S32LSB:
254 {
255 const Uint32 *src32 = (Uint32 *) src;
256 Uint32 *dst32 = (Uint32 *) dst;
257 Sint64 src1, src2;
258 Sint64 dst_sample;
259 const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
260 const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
261
262 len /= 4;
263 while (len--) {
264 src1 = (Sint64) ((Sint32) SDL_SwapLE32(*src32));
265 src32++;
266 ADJUST_VOLUME(src1, volume);
267 src2 = (Sint64) ((Sint32) SDL_SwapLE32(*dst32));
268 dst_sample = src1 + src2;
269 if (dst_sample > max_audioval) {
270 dst_sample = max_audioval;
271 } else if (dst_sample < min_audioval) {
272 dst_sample = min_audioval;
273 }
274 *(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample));
275 }
276 }
277 break;
278
279 case AUDIO_S32MSB:
280 {
281 const Uint32 *src32 = (Uint32 *) src;
282 Uint32 *dst32 = (Uint32 *) dst;
283 Sint64 src1, src2;
284 Sint64 dst_sample;
285 const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
286 const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
287
288 len /= 4;
289 while (len--) {
290 src1 = (Sint64) ((Sint32) SDL_SwapBE32(*src32));
291 src32++;
292 ADJUST_VOLUME(src1, volume);
293 src2 = (Sint64) ((Sint32) SDL_SwapBE32(*dst32));
294 dst_sample = src1 + src2;
295 if (dst_sample > max_audioval) {
296 dst_sample = max_audioval;
297 } else if (dst_sample < min_audioval) {
298 dst_sample = min_audioval;
299 }
300 *(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample));
301 }
302 }
303 break;
304
305 case AUDIO_F32LSB:
306 {
307 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
308 const float fvolume = (float) volume;
309 const float *src32 = (float *) src;
310 float *dst32 = (float *) dst;
311 float src1, src2;
312 double dst_sample;
313 /* !!! FIXME: are these right? */
314 const double max_audioval = 3.402823466e+38F;
315 const double min_audioval = -3.402823466e+38F;
316
317 len /= 4;
318 while (len--) {
319 src1 = ((SDL_SwapFloatLE(*src32) * fvolume) * fmaxvolume);
320 src2 = SDL_SwapFloatLE(*dst32);
321 src32++;
322
323 dst_sample = ((double) src1) + ((double) src2);
324 if (dst_sample > max_audioval) {
325 dst_sample = max_audioval;
326 } else if (dst_sample < min_audioval) {
327 dst_sample = min_audioval;
328 }
329 *(dst32++) = SDL_SwapFloatLE((float) dst_sample);
330 }
331 }
332 break;
333
334 case AUDIO_F32MSB:
335 {
336 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
337 const float fvolume = (float) volume;
338 const float *src32 = (float *) src;
339 float *dst32 = (float *) dst;
340 float src1, src2;
341 double dst_sample;
342 /* !!! FIXME: are these right? */
343 const double max_audioval = 3.402823466e+38F;
344 const double min_audioval = -3.402823466e+38F;
345
346 len /= 4;
347 while (len--) {
348 src1 = ((SDL_SwapFloatBE(*src32) * fvolume) * fmaxvolume);
349 src2 = SDL_SwapFloatBE(*dst32);
350 src32++;
351
352 dst_sample = ((double) src1) + ((double) src2);
353 if (dst_sample > max_audioval) {
354 dst_sample = max_audioval;
355 } else if (dst_sample < min_audioval) {
356 dst_sample = min_audioval;
357 }
358 *(dst32++) = SDL_SwapFloatBE((float) dst_sample);
359 }
360 }
361 break;
362
363 default: /* If this happens... FIXME! */
364 SDL_SetError("SDL_MixAudioFormat(): unknown audio format");
365 return;
366 }
367 }
368
369 /* vi: set ts=4 sw=4 expandtab: */
370