b49c73dabab80853ccabf8414db7b1ddb21f17e6
[platform/upstream/SDL.git] / src / audio / SDL_mixer.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 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: */