1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 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 */
34static 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
89void
90SDL_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 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 }
111 break;
112
113 case AUDIO_S8:
114 {
115 Sint8 *dst8, *src8;
116 Sint8 src_sample;
117 int dst_sample;
118 const int max_audioval = ((1 << (8 - 1)) - 1);
119 const int min_audioval = -(1 << (8 - 1));
120
121 src8 = (Sint8 *) src;
122 dst8 = (Sint8 *) dst;
123 while (len--) {
124 src_sample = *src8;
125 ADJUST_VOLUME(src_sample, volume);
126 dst_sample = *dst8 + src_sample;
127 if (dst_sample > max_audioval) {
128 *dst8 = max_audioval;
129 } else if (dst_sample < min_audioval) {
130 *dst8 = min_audioval;
131 } else {
132 *dst8 = dst_sample;
133 }
134 ++dst8;
135 ++src8;
136 }
137 }
138 break;
139
140 case AUDIO_S16LSB:
141 {
142 Sint16 src1, src2;
143 int dst_sample;
144 const int max_audioval = ((1 << (16 - 1)) - 1);
145 const int min_audioval = -(1 << (16 - 1));
146
147 len /= 2;
148 while (len--) {
149 src1 = ((src[1]) << 8 | src[0]);
150 ADJUST_VOLUME(src1, volume);
151 src2 = ((dst[1]) << 8 | dst[0]);
152 src += 2;
153 dst_sample = src1 + src2;
154 if (dst_sample > max_audioval) {
155 dst_sample = max_audioval;
156 } else if (dst_sample < min_audioval) {
157 dst_sample = min_audioval;
158 }
159 dst[0] = dst_sample & 0xFF;
160 dst_sample >>= 8;
161 dst[1] = dst_sample & 0xFF;
162 dst += 2;
163 }
164 }
165 break;
166
167 case AUDIO_S16MSB:
168 {
169 Sint16 src1, src2;
170 int dst_sample;
171 const int max_audioval = ((1 << (16 - 1)) - 1);
172 const int min_audioval = -(1 << (16 - 1));
173
174 len /= 2;
175 while (len--) {
176 src1 = ((src[0]) << 8 | src[1]);
177 ADJUST_VOLUME(src1, volume);
178 src2 = ((dst[0]) << 8 | dst[1]);
179 src += 2;
180 dst_sample = src1 + src2;
181 if (dst_sample > max_audioval) {
182 dst_sample = max_audioval;
183 } else if (dst_sample < min_audioval) {
184 dst_sample = min_audioval;
185 }
186 dst[1] = dst_sample & 0xFF;
187 dst_sample >>= 8;
188 dst[0] = dst_sample & 0xFF;
189 dst += 2;
190 }
191 }
192 break;
193
194 case AUDIO_U16LSB:
195 {
196 Uint16 src1, src2;
197 int dst_sample;
198 const int max_audioval = 0xFFFF;
199
200 len /= 2;
201 while (len--) {
202 src1 = ((src[1]) << 8 | src[0]);
203 ADJUST_VOLUME(src1, volume);
204 src2 = ((dst[1]) << 8 | dst[0]);
205 src += 2;
206 dst_sample = src1 + src2;
207 if (dst_sample > max_audioval) {
208 dst_sample = max_audioval;
209 }
210 dst[0] = dst_sample & 0xFF;
211 dst_sample >>= 8;
212 dst[1] = dst_sample & 0xFF;
213 dst += 2;
214 }
215 }
216 break;
217
218 case AUDIO_U16MSB:
219 {
220 Uint16 src1, src2;
221 int dst_sample;
222 const int max_audioval = 0xFFFF;
223
224 len /= 2;
225 while (len--) {
226 src1 = ((src[0]) << 8 | src[1]);
227 ADJUST_VOLUME(src1, volume);
228 src2 = ((dst[0]) << 8 | dst[1]);
229 src += 2;
230 dst_sample = src1 + src2;
231 if (dst_sample > max_audioval) {
232 dst_sample = max_audioval;
233 }
234 dst[1] = dst_sample & 0xFF;
235 dst_sample >>= 8;
236 dst[0] = dst_sample & 0xFF;
237 dst += 2;
238 }
239 }
240 break;
241
242 case AUDIO_S32LSB:
243 {
244 const Uint32 *src32 = (Uint32 *) src;
245 Uint32 *dst32 = (Uint32 *) dst;
246 Sint64 src1, src2;
247 Sint64 dst_sample;
248 const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
249 const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
250
251 len /= 4;
252 while (len--) {
253 src1 = (Sint64) ((Sint32) SDL_SwapLE32(*src32));
254 src32++;
255 ADJUST_VOLUME(src1, volume);
256 src2 = (Sint64) ((Sint32) SDL_SwapLE32(*dst32));
257 dst_sample = src1 + src2;
258 if (dst_sample > max_audioval) {
259 dst_sample = max_audioval;
260 } else if (dst_sample < min_audioval) {
261 dst_sample = min_audioval;
262 }
263 *(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample));
264 }
265 }
266 break;
267
268 case AUDIO_S32MSB:
269 {
270 const Uint32 *src32 = (Uint32 *) src;
271 Uint32 *dst32 = (Uint32 *) dst;
272 Sint64 src1, src2;
273 Sint64 dst_sample;
274 const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
275 const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
276
277 len /= 4;
278 while (len--) {
279 src1 = (Sint64) ((Sint32) SDL_SwapBE32(*src32));
280 src32++;
281 ADJUST_VOLUME(src1, volume);
282 src2 = (Sint64) ((Sint32) SDL_SwapBE32(*dst32));
283 dst_sample = src1 + src2;
284 if (dst_sample > max_audioval) {
285 dst_sample = max_audioval;
286 } else if (dst_sample < min_audioval) {
287 dst_sample = min_audioval;
288 }
289 *(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample));
290 }
291 }
292 break;
293
294 case AUDIO_F32LSB:
295 {
296 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
297 const float fvolume = (float) volume;
298 const float *src32 = (float *) src;
299 float *dst32 = (float *) dst;
300 float src1, src2;
301 double dst_sample;
302 /* !!! FIXME: are these right? */
303 const double max_audioval = 3.402823466e+38F;
304 const double min_audioval = -3.402823466e+38F;
305
306 len /= 4;
307 while (len--) {
308 src1 = ((SDL_SwapFloatLE(*src32) * fvolume) * fmaxvolume);
309 src2 = SDL_SwapFloatLE(*dst32);
310 src32++;
311
312 dst_sample = ((double) src1) + ((double) src2);
313 if (dst_sample > max_audioval) {
314 dst_sample = max_audioval;
315 } else if (dst_sample < min_audioval) {
316 dst_sample = min_audioval;
317 }
318 *(dst32++) = SDL_SwapFloatLE((float) dst_sample);
319 }
320 }
321 break;
322
323 case AUDIO_F32MSB:
324 {
325 const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
326 const float fvolume = (float) volume;
327 const float *src32 = (float *) src;
328 float *dst32 = (float *) dst;
329 float src1, src2;
330 double dst_sample;
331 /* !!! FIXME: are these right? */
332 const double max_audioval = 3.402823466e+38F;
333 const double min_audioval = -3.402823466e+38F;
334
335 len /= 4;
336 while (len--) {
337 src1 = ((SDL_SwapFloatBE(*src32) * fvolume) * fmaxvolume);
338 src2 = SDL_SwapFloatBE(*dst32);
339 src32++;
340
341 dst_sample = ((double) src1) + ((double) src2);
342 if (dst_sample > max_audioval) {
343 dst_sample = max_audioval;
344 } else if (dst_sample < min_audioval) {
345 dst_sample = min_audioval;
346 }
347 *(dst32++) = SDL_SwapFloatBE((float) dst_sample);
348 }
349 }
350 break;
351
352 default: /* If this happens... FIXME! */
353 SDL_SetError("SDL_MixAudioFormat(): unknown audio format");
354 return;
355 }
356}
357
358/* vi: set ts=4 sw=4 expandtab: */
359