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