Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
1079 lines (952 loc) · 34.2 KB

SDL_audiocvt.c

File metadata and controls

1079 lines (952 loc) · 34.2 KB
 
Apr 26, 2001
Apr 26, 2001
1
/*
Apr 8, 2011
Apr 8, 2011
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Apr 26, 2001
Apr 26, 2001
20
*/
Feb 21, 2006
Feb 21, 2006
21
#include "SDL_config.h"
Aug 26, 2008
Aug 26, 2008
22
Apr 26, 2001
Apr 26, 2001
23
24
25
/* Functions for audio drivers to perform runtime conversion of audio format */
#include "SDL_audio.h"
Aug 24, 2006
Aug 24, 2006
26
#include "SDL_audio_c.h"
Apr 26, 2001
Apr 26, 2001
27
Jan 11, 2009
Jan 11, 2009
28
/* #define DEBUG_CONVERT */
Aug 25, 2008
Aug 25, 2008
29
Jan 11, 2009
Jan 11, 2009
30
31
32
/* !!! FIXME */
#ifndef assert
#define assert(x)
Aug 25, 2008
Aug 25, 2008
33
34
#endif
Apr 26, 2001
Apr 26, 2001
35
/* Effectively mix right and left channels into a single channel */
Aug 24, 2006
Aug 24, 2006
36
37
static void SDLCALL
SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Apr 26, 2001
Apr 26, 2001
38
{
Jul 10, 2006
Jul 10, 2006
39
40
int i;
Sint32 sample;
Apr 26, 2001
Apr 26, 2001
41
42
#ifdef DEBUG_CONVERT
Jul 10, 2006
Jul 10, 2006
43
fprintf(stderr, "Converting to mono\n");
Apr 26, 2001
Apr 26, 2001
44
#endif
Aug 28, 2006
Aug 28, 2006
45
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
Jul 10, 2006
Jul 10, 2006
46
47
48
49
50
51
52
53
case AUDIO_U8:
{
Uint8 *src, *dst;
src = cvt->buf;
dst = cvt->buf;
for (i = cvt->len_cvt / 2; i; --i) {
sample = src[0] + src[1];
Sep 24, 2006
Sep 24, 2006
54
*dst = (Uint8) (sample / 2);
Jul 10, 2006
Jul 10, 2006
55
56
57
58
59
60
61
62
63
64
65
66
67
68
src += 2;
dst += 1;
}
}
break;
case AUDIO_S8:
{
Sint8 *src, *dst;
src = (Sint8 *) cvt->buf;
dst = (Sint8 *) cvt->buf;
for (i = cvt->len_cvt / 2; i; --i) {
sample = src[0] + src[1];
Sep 24, 2006
Sep 24, 2006
69
*dst = (Sint8) (sample / 2);
Jul 10, 2006
Jul 10, 2006
70
71
72
73
74
75
76
77
78
79
80
81
src += 2;
dst += 1;
}
}
break;
case AUDIO_U16:
{
Uint8 *src, *dst;
src = cvt->buf;
dst = cvt->buf;
Aug 24, 2006
Aug 24, 2006
82
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
83
84
85
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Uint16) ((src[0] << 8) | src[1]) +
(Uint16) ((src[2] << 8) | src[3]);
Sep 24, 2006
Sep 24, 2006
86
87
88
89
sample /= 2;
dst[1] = (sample & 0xFF);
sample >>= 8;
dst[0] = (sample & 0xFF);
Jul 10, 2006
Jul 10, 2006
90
91
92
93
94
95
96
src += 4;
dst += 2;
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Uint16) ((src[1] << 8) | src[0]) +
(Uint16) ((src[3] << 8) | src[2]);
Sep 24, 2006
Sep 24, 2006
97
98
99
100
sample /= 2;
dst[0] = (sample & 0xFF);
sample >>= 8;
dst[1] = (sample & 0xFF);
Jul 10, 2006
Jul 10, 2006
101
102
103
104
105
106
107
108
109
110
111
112
113
src += 4;
dst += 2;
}
}
}
break;
case AUDIO_S16:
{
Uint8 *src, *dst;
src = cvt->buf;
dst = cvt->buf;
Aug 24, 2006
Aug 24, 2006
114
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
115
116
117
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Sint16) ((src[0] << 8) | src[1]) +
(Sint16) ((src[2] << 8) | src[3]);
Sep 24, 2006
Sep 24, 2006
118
119
120
121
sample /= 2;
dst[1] = (sample & 0xFF);
sample >>= 8;
dst[0] = (sample & 0xFF);
Jul 10, 2006
Jul 10, 2006
122
123
124
125
126
127
128
src += 4;
dst += 2;
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Sint16) ((src[1] << 8) | src[0]) +
(Sint16) ((src[3] << 8) | src[2]);
Sep 24, 2006
Sep 24, 2006
129
130
131
132
sample /= 2;
dst[0] = (sample & 0xFF);
sample >>= 8;
dst[1] = (sample & 0xFF);
Jul 10, 2006
Jul 10, 2006
133
134
135
136
137
138
139
src += 4;
dst += 2;
}
}
}
break;
Aug 24, 2006
Aug 24, 2006
140
case AUDIO_S32:
Jul 10, 2006
Jul 10, 2006
141
{
Aug 24, 2006
Aug 24, 2006
142
143
144
145
146
const Uint32 *src = (const Uint32 *) cvt->buf;
Uint32 *dst = (Uint32 *) cvt->buf;
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
const Sint64 added =
Aug 28, 2006
Aug 28, 2006
147
148
(((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
((Sint64) (Sint32) SDL_SwapBE32(src[1])));
Nov 29, 2006
Nov 29, 2006
149
*(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
Jul 10, 2006
Jul 10, 2006
150
151
}
} else {
Aug 24, 2006
Aug 24, 2006
152
153
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
const Sint64 added =
Aug 28, 2006
Aug 28, 2006
154
155
(((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
((Sint64) (Sint32) SDL_SwapLE32(src[1])));
Nov 29, 2006
Nov 29, 2006
156
*(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
Jul 10, 2006
Jul 10, 2006
157
158
159
160
161
}
}
}
break;
Aug 24, 2006
Aug 24, 2006
162
case AUDIO_F32:
Jul 10, 2006
Jul 10, 2006
163
{
Sep 1, 2006
Sep 1, 2006
164
165
const float *src = (const float *) cvt->buf;
float *dst = (float *) cvt->buf;
Aug 24, 2006
Aug 24, 2006
166
167
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
Oct 17, 2006
Oct 17, 2006
168
169
const float src1 = SDL_SwapFloatBE(src[0]);
const float src2 = SDL_SwapFloatBE(src[1]);
Aug 24, 2006
Aug 24, 2006
170
const double added = ((double) src1) + ((double) src2);
Oct 17, 2006
Oct 17, 2006
171
172
const float halved = (float) (added * 0.5);
*(dst++) = SDL_SwapFloatBE(halved);
Jul 10, 2006
Jul 10, 2006
173
174
}
} else {
Aug 24, 2006
Aug 24, 2006
175
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
Oct 17, 2006
Oct 17, 2006
176
177
const float src1 = SDL_SwapFloatLE(src[0]);
const float src2 = SDL_SwapFloatLE(src[1]);
Aug 24, 2006
Aug 24, 2006
178
const double added = ((double) src1) + ((double) src2);
Oct 17, 2006
Oct 17, 2006
179
180
const float halved = (float) (added * 0.5);
*(dst++) = SDL_SwapFloatLE(halved);
Jul 10, 2006
Jul 10, 2006
181
182
183
184
185
}
}
}
break;
}
Aug 24, 2006
Aug 24, 2006
186
187
cvt->len_cvt /= 2;
Jul 10, 2006
Jul 10, 2006
188
189
190
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
Aug 21, 2004
Aug 21, 2004
191
192
193
}
Aug 24, 2006
Aug 24, 2006
194
195
196
/* Discard top 4 channels */
static void SDLCALL
SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Aug 21, 2004
Aug 21, 2004
197
{
Jul 10, 2006
Jul 10, 2006
198
int i;
Aug 21, 2004
Aug 21, 2004
199
200
#ifdef DEBUG_CONVERT
Aug 24, 2006
Aug 24, 2006
201
fprintf(stderr, "Converting down from 6 channels to stereo\n");
Aug 21, 2004
Aug 21, 2004
202
#endif
Jul 10, 2006
Jul 10, 2006
203
Aug 28, 2006
Aug 28, 2006
204
#define strip_chans_6_to_2(type) \
Aug 24, 2006
Aug 24, 2006
205
206
207
208
209
210
211
212
213
214
{ \
const type *src = (const type *) cvt->buf; \
type *dst = (type *) cvt->buf; \
for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
dst[0] = src[0]; \
dst[1] = src[1]; \
src += 6; \
dst += 2; \
} \
}
Jul 10, 2006
Jul 10, 2006
215
Aug 24, 2006
Aug 24, 2006
216
217
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
Aug 28, 2006
Aug 28, 2006
218
219
220
221
222
223
224
225
226
case 8:
strip_chans_6_to_2(Uint8);
break;
case 16:
strip_chans_6_to_2(Uint16);
break;
case 32:
strip_chans_6_to_2(Uint32);
break;
Aug 24, 2006
Aug 24, 2006
227
}
Jul 10, 2006
Jul 10, 2006
228
Aug 28, 2006
Aug 28, 2006
229
#undef strip_chans_6_to_2
Jul 10, 2006
Jul 10, 2006
230
Aug 24, 2006
Aug 24, 2006
231
232
233
234
235
cvt->len_cvt /= 3;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
}
Jul 10, 2006
Jul 10, 2006
236
237
Aug 24, 2006
Aug 24, 2006
238
239
240
241
242
/* Discard top 2 channels of 6 */
static void SDLCALL
SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
{
int i;
Jul 10, 2006
Jul 10, 2006
243
Aug 24, 2006
Aug 24, 2006
244
245
246
#ifdef DEBUG_CONVERT
fprintf(stderr, "Converting 6 down to quad\n");
#endif
Jul 10, 2006
Jul 10, 2006
247
Aug 28, 2006
Aug 28, 2006
248
#define strip_chans_6_to_4(type) \
Aug 24, 2006
Aug 24, 2006
249
250
251
252
253
254
255
256
257
258
259
{ \
const type *src = (const type *) cvt->buf; \
type *dst = (type *) cvt->buf; \
for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
dst[0] = src[0]; \
dst[1] = src[1]; \
dst[2] = src[2]; \
dst[3] = src[3]; \
src += 6; \
dst += 4; \
} \
Jul 10, 2006
Jul 10, 2006
260
}
Aug 24, 2006
Aug 24, 2006
261
262
263
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
Aug 28, 2006
Aug 28, 2006
264
265
266
267
268
269
270
271
272
case 8:
strip_chans_6_to_4(Uint8);
break;
case 16:
strip_chans_6_to_4(Uint16);
break;
case 32:
strip_chans_6_to_4(Uint32);
break;
Aug 24, 2006
Aug 24, 2006
273
274
}
Aug 28, 2006
Aug 28, 2006
275
#undef strip_chans_6_to_4
Aug 24, 2006
Aug 24, 2006
276
277
278
cvt->len_cvt /= 6;
cvt->len_cvt *= 4;
Jul 10, 2006
Jul 10, 2006
279
280
281
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
Aug 21, 2004
Aug 21, 2004
282
}
Apr 26, 2001
Apr 26, 2001
283
284
/* Duplicate a mono channel to both stereo channels */
Aug 24, 2006
Aug 24, 2006
285
286
static void SDLCALL
SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Apr 26, 2001
Apr 26, 2001
287
{
Jul 10, 2006
Jul 10, 2006
288
int i;
Apr 26, 2001
Apr 26, 2001
289
290
#ifdef DEBUG_CONVERT
Jul 10, 2006
Jul 10, 2006
291
fprintf(stderr, "Converting to stereo\n");
Apr 26, 2001
Apr 26, 2001
292
#endif
Aug 24, 2006
Aug 24, 2006
293
Aug 28, 2006
Aug 28, 2006
294
#define dup_chans_1_to_2(type) \
Aug 24, 2006
Aug 24, 2006
295
296
297
298
299
300
301
302
{ \
const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
for (i = cvt->len_cvt / 2; i; --i, --src) { \
const type val = *src; \
dst -= 2; \
dst[0] = dst[1] = val; \
} \
Jul 10, 2006
Jul 10, 2006
303
}
Aug 24, 2006
Aug 24, 2006
304
305
306
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
Aug 28, 2006
Aug 28, 2006
307
308
309
310
311
312
313
314
315
case 8:
dup_chans_1_to_2(Uint8);
break;
case 16:
dup_chans_1_to_2(Uint16);
break;
case 32:
dup_chans_1_to_2(Uint32);
break;
Aug 24, 2006
Aug 24, 2006
316
317
}
Aug 28, 2006
Aug 28, 2006
318
#undef dup_chans_1_to_2
Aug 24, 2006
Aug 24, 2006
319
Jul 10, 2006
Jul 10, 2006
320
321
322
323
cvt->len_cvt *= 2;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
Apr 26, 2001
Apr 26, 2001
324
325
}
Aug 21, 2004
Aug 21, 2004
326
327
/* Duplicate a stereo channel to a pseudo-5.1 stream */
Aug 24, 2006
Aug 24, 2006
328
329
static void SDLCALL
SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Aug 21, 2004
Aug 21, 2004
330
{
Jul 10, 2006
Jul 10, 2006
331
int i;
Aug 21, 2004
Aug 21, 2004
332
333
#ifdef DEBUG_CONVERT
Jul 10, 2006
Jul 10, 2006
334
fprintf(stderr, "Converting stereo to surround\n");
Aug 21, 2004
Aug 21, 2004
335
#endif
Jul 10, 2006
Jul 10, 2006
336
Aug 28, 2006
Aug 28, 2006
337
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
Jul 10, 2006
Jul 10, 2006
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
case AUDIO_U8:
{
Uint8 *src, *dst, lf, rf, ce;
src = (Uint8 *) (cvt->buf + cvt->len_cvt);
dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
for (i = cvt->len_cvt; i; --i) {
dst -= 6;
src -= 2;
lf = src[0];
rf = src[1];
ce = (lf / 2) + (rf / 2);
dst[0] = lf;
dst[1] = rf;
dst[2] = lf - ce;
dst[3] = rf - ce;
dst[4] = ce;
dst[5] = ce;
}
}
break;
case AUDIO_S8:
{
Sint8 *src, *dst, lf, rf, ce;
src = (Sint8 *) cvt->buf + cvt->len_cvt;
dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
for (i = cvt->len_cvt; i; --i) {
dst -= 6;
src -= 2;
lf = src[0];
rf = src[1];
ce = (lf / 2) + (rf / 2);
dst[0] = lf;
dst[1] = rf;
dst[2] = lf - ce;
dst[3] = rf - ce;
dst[4] = ce;
dst[5] = ce;
}
}
break;
case AUDIO_U16:
{
Uint8 *src, *dst;
Uint16 lf, rf, ce, lr, rr;
src = cvt->buf + cvt->len_cvt;
dst = cvt->buf + cvt->len_cvt * 3;
Aug 24, 2006
Aug 24, 2006
390
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 12;
src -= 4;
lf = (Uint16) ((src[0] << 8) | src[1]);
rf = (Uint16) ((src[2] << 8) | src[3]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[1] = (lf & 0xFF);
dst[0] = ((lf >> 8) & 0xFF);
dst[3] = (rf & 0xFF);
dst[2] = ((rf >> 8) & 0xFF);
dst[1 + 4] = (lr & 0xFF);
dst[0 + 4] = ((lr >> 8) & 0xFF);
dst[3 + 4] = (rr & 0xFF);
dst[2 + 4] = ((rr >> 8) & 0xFF);
dst[1 + 8] = (ce & 0xFF);
dst[0 + 8] = ((ce >> 8) & 0xFF);
dst[3 + 8] = (ce & 0xFF);
dst[2 + 8] = ((ce >> 8) & 0xFF);
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 12;
src -= 4;
lf = (Uint16) ((src[1] << 8) | src[0]);
rf = (Uint16) ((src[3] << 8) | src[2]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[0] = (lf & 0xFF);
dst[1] = ((lf >> 8) & 0xFF);
dst[2] = (rf & 0xFF);
dst[3] = ((rf >> 8) & 0xFF);
dst[0 + 4] = (lr & 0xFF);
dst[1 + 4] = ((lr >> 8) & 0xFF);
dst[2 + 4] = (rr & 0xFF);
dst[3 + 4] = ((rr >> 8) & 0xFF);
dst[0 + 8] = (ce & 0xFF);
dst[1 + 8] = ((ce >> 8) & 0xFF);
dst[2 + 8] = (ce & 0xFF);
dst[3 + 8] = ((ce >> 8) & 0xFF);
}
}
}
break;
case AUDIO_S16:
{
Uint8 *src, *dst;
Sint16 lf, rf, ce, lr, rr;
src = cvt->buf + cvt->len_cvt;
dst = cvt->buf + cvt->len_cvt * 3;
Aug 24, 2006
Aug 24, 2006
450
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 12;
src -= 4;
lf = (Sint16) ((src[0] << 8) | src[1]);
rf = (Sint16) ((src[2] << 8) | src[3]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[1] = (lf & 0xFF);
dst[0] = ((lf >> 8) & 0xFF);
dst[3] = (rf & 0xFF);
dst[2] = ((rf >> 8) & 0xFF);
dst[1 + 4] = (lr & 0xFF);
dst[0 + 4] = ((lr >> 8) & 0xFF);
dst[3 + 4] = (rr & 0xFF);
dst[2 + 4] = ((rr >> 8) & 0xFF);
dst[1 + 8] = (ce & 0xFF);
dst[0 + 8] = ((ce >> 8) & 0xFF);
dst[3 + 8] = (ce & 0xFF);
dst[2 + 8] = ((ce >> 8) & 0xFF);
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 12;
src -= 4;
lf = (Sint16) ((src[1] << 8) | src[0]);
rf = (Sint16) ((src[3] << 8) | src[2]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[0] = (lf & 0xFF);
dst[1] = ((lf >> 8) & 0xFF);
dst[2] = (rf & 0xFF);
dst[3] = ((rf >> 8) & 0xFF);
dst[0 + 4] = (lr & 0xFF);
dst[1 + 4] = ((lr >> 8) & 0xFF);
dst[2 + 4] = (rr & 0xFF);
dst[3 + 4] = ((rr >> 8) & 0xFF);
dst[0 + 8] = (ce & 0xFF);
dst[1 + 8] = ((ce >> 8) & 0xFF);
dst[2 + 8] = (ce & 0xFF);
dst[3 + 8] = ((ce >> 8) & 0xFF);
}
}
}
break;
Aug 24, 2006
Aug 24, 2006
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
case AUDIO_S32:
{
Sint32 lf, rf, ce;
const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt;
Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3;
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
lf = (Sint32) SDL_SwapBE32(src[0]);
rf = (Sint32) SDL_SwapBE32(src[1]);
ce = (lf / 2) + (rf / 2);
dst[0] = SDL_SwapBE32((Uint32) lf);
dst[1] = SDL_SwapBE32((Uint32) rf);
dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
dst[4] = SDL_SwapBE32((Uint32) ce);
dst[5] = SDL_SwapBE32((Uint32) ce);
}
} else {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
lf = (Sint32) SDL_SwapLE32(src[0]);
rf = (Sint32) SDL_SwapLE32(src[1]);
ce = (lf / 2) + (rf / 2);
dst[0] = src[0];
dst[1] = src[1];
dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
dst[4] = SDL_SwapLE32((Uint32) ce);
dst[5] = SDL_SwapLE32((Uint32) ce);
}
}
}
break;
case AUDIO_F32:
{
float lf, rf, ce;
Sep 1, 2006
Sep 1, 2006
543
544
const float *src = (const float *) cvt->buf + cvt->len_cvt;
float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
Aug 24, 2006
Aug 24, 2006
545
546
547
548
549
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
Sep 1, 2006
Sep 1, 2006
550
551
lf = SDL_SwapFloatBE(src[0]);
rf = SDL_SwapFloatBE(src[1]);
Aug 24, 2006
Aug 24, 2006
552
553
554
ce = (lf * 0.5f) + (rf * 0.5f);
dst[0] = src[0];
dst[1] = src[1];
Sep 1, 2006
Sep 1, 2006
555
556
557
dst[2] = SDL_SwapFloatBE(lf - ce);
dst[3] = SDL_SwapFloatBE(rf - ce);
dst[4] = dst[5] = SDL_SwapFloatBE(ce);
Aug 24, 2006
Aug 24, 2006
558
559
560
561
562
}
} else {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
Sep 1, 2006
Sep 1, 2006
563
564
lf = SDL_SwapFloatLE(src[0]);
rf = SDL_SwapFloatLE(src[1]);
Aug 24, 2006
Aug 24, 2006
565
566
567
ce = (lf * 0.5f) + (rf * 0.5f);
dst[0] = src[0];
dst[1] = src[1];
Sep 1, 2006
Sep 1, 2006
568
569
570
dst[2] = SDL_SwapFloatLE(lf - ce);
dst[3] = SDL_SwapFloatLE(rf - ce);
dst[4] = dst[5] = SDL_SwapFloatLE(ce);
Aug 24, 2006
Aug 24, 2006
571
572
573
574
575
}
}
}
break;
Jul 10, 2006
Jul 10, 2006
576
577
578
579
580
}
cvt->len_cvt *= 3;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
Aug 21, 2004
Aug 21, 2004
581
582
583
584
}
/* Duplicate a stereo channel to a pseudo-4.0 stream */
Aug 24, 2006
Aug 24, 2006
585
586
static void SDLCALL
SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Aug 21, 2004
Aug 21, 2004
587
{
Jul 10, 2006
Jul 10, 2006
588
int i;
Aug 21, 2004
Aug 21, 2004
589
590
#ifdef DEBUG_CONVERT
Jul 10, 2006
Jul 10, 2006
591
fprintf(stderr, "Converting stereo to quad\n");
Aug 21, 2004
Aug 21, 2004
592
#endif
Jul 10, 2006
Jul 10, 2006
593
Aug 28, 2006
Aug 28, 2006
594
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
Jul 10, 2006
Jul 10, 2006
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
case AUDIO_U8:
{
Uint8 *src, *dst, lf, rf, ce;
src = (Uint8 *) (cvt->buf + cvt->len_cvt);
dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
for (i = cvt->len_cvt; i; --i) {
dst -= 4;
src -= 2;
lf = src[0];
rf = src[1];
ce = (lf / 2) + (rf / 2);
dst[0] = lf;
dst[1] = rf;
dst[2] = lf - ce;
dst[3] = rf - ce;
}
}
break;
case AUDIO_S8:
{
Sint8 *src, *dst, lf, rf, ce;
src = (Sint8 *) cvt->buf + cvt->len_cvt;
dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
for (i = cvt->len_cvt; i; --i) {
dst -= 4;
src -= 2;
lf = src[0];
rf = src[1];
ce = (lf / 2) + (rf / 2);
dst[0] = lf;
dst[1] = rf;
dst[2] = lf - ce;
dst[3] = rf - ce;
}
}
break;
case AUDIO_U16:
{
Uint8 *src, *dst;
Uint16 lf, rf, ce, lr, rr;
src = cvt->buf + cvt->len_cvt;
dst = cvt->buf + cvt->len_cvt * 2;
Aug 24, 2006
Aug 24, 2006
643
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 8;
src -= 4;
lf = (Uint16) ((src[0] << 8) | src[1]);
rf = (Uint16) ((src[2] << 8) | src[3]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[1] = (lf & 0xFF);
dst[0] = ((lf >> 8) & 0xFF);
dst[3] = (rf & 0xFF);
dst[2] = ((rf >> 8) & 0xFF);
dst[1 + 4] = (lr & 0xFF);
dst[0 + 4] = ((lr >> 8) & 0xFF);
dst[3 + 4] = (rr & 0xFF);
dst[2 + 4] = ((rr >> 8) & 0xFF);
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 8;
src -= 4;
lf = (Uint16) ((src[1] << 8) | src[0]);
rf = (Uint16) ((src[3] << 8) | src[2]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[0] = (lf & 0xFF);
dst[1] = ((lf >> 8) & 0xFF);
dst[2] = (rf & 0xFF);
dst[3] = ((rf >> 8) & 0xFF);
dst[0 + 4] = (lr & 0xFF);
dst[1 + 4] = ((lr >> 8) & 0xFF);
dst[2 + 4] = (rr & 0xFF);
dst[3 + 4] = ((rr >> 8) & 0xFF);
}
}
}
break;
case AUDIO_S16:
{
Uint8 *src, *dst;
Sint16 lf, rf, ce, lr, rr;
src = cvt->buf + cvt->len_cvt;
dst = cvt->buf + cvt->len_cvt * 2;
Aug 24, 2006
Aug 24, 2006
693
if (SDL_AUDIO_ISBIGENDIAN(format)) {
Jul 10, 2006
Jul 10, 2006
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 8;
src -= 4;
lf = (Sint16) ((src[0] << 8) | src[1]);
rf = (Sint16) ((src[2] << 8) | src[3]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[1] = (lf & 0xFF);
dst[0] = ((lf >> 8) & 0xFF);
dst[3] = (rf & 0xFF);
dst[2] = ((rf >> 8) & 0xFF);
dst[1 + 4] = (lr & 0xFF);
dst[0 + 4] = ((lr >> 8) & 0xFF);
dst[3 + 4] = (rr & 0xFF);
dst[2 + 4] = ((rr >> 8) & 0xFF);
}
} else {
for (i = cvt->len_cvt / 4; i; --i) {
dst -= 8;
src -= 4;
lf = (Sint16) ((src[1] << 8) | src[0]);
rf = (Sint16) ((src[3] << 8) | src[2]);
ce = (lf / 2) + (rf / 2);
rr = lf - ce;
lr = rf - ce;
dst[0] = (lf & 0xFF);
dst[1] = ((lf >> 8) & 0xFF);
dst[2] = (rf & 0xFF);
dst[3] = ((rf >> 8) & 0xFF);
dst[0 + 4] = (lr & 0xFF);
dst[1 + 4] = ((lr >> 8) & 0xFF);
dst[2 + 4] = (rr & 0xFF);
dst[3 + 4] = ((rr >> 8) & 0xFF);
}
}
}
break;
Aug 24, 2006
Aug 24, 2006
735
736
737
738
739
case AUDIO_S32:
{
const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
Sint32 lf, rf, ce;
Apr 26, 2001
Apr 26, 2001
740
Aug 24, 2006
Aug 24, 2006
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 4;
src -= 2;
lf = (Sint32) SDL_SwapBE32(src[0]);
rf = (Sint32) SDL_SwapBE32(src[1]);
ce = (lf / 2) + (rf / 2);
dst[0] = src[0];
dst[1] = src[1];
dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
}
} else {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 4;
src -= 2;
lf = (Sint32) SDL_SwapLE32(src[0]);
rf = (Sint32) SDL_SwapLE32(src[1]);
ce = (lf / 2) + (rf / 2);
dst[0] = src[0];
dst[1] = src[1];
dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
}
}
}
break;
Jul 10, 2006
Jul 10, 2006
768
769
770
771
772
}
cvt->len_cvt *= 2;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
Apr 26, 2001
Apr 26, 2001
773
774
775
}
Jul 10, 2006
Jul 10, 2006
776
777
int
SDL_ConvertAudio(SDL_AudioCVT * cvt)
Apr 26, 2001
Apr 26, 2001
778
{
Jan 11, 2009
Jan 11, 2009
779
780
781
/* !!! FIXME: (cvt) should be const; stack-copy it here. */
/* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
Jul 10, 2006
Jul 10, 2006
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
/* Make sure there's data to convert */
if (cvt->buf == NULL) {
SDL_SetError("No buffer allocated for conversion");
return (-1);
}
/* Return okay if no conversion is necessary */
cvt->len_cvt = cvt->len;
if (cvt->filters[0] == NULL) {
return (0);
}
/* Set up the conversion and go! */
cvt->filter_index = 0;
cvt->filters[0] (cvt, cvt->src_format);
return (0);
Apr 26, 2001
Apr 26, 2001
797
798
}
Aug 24, 2006
Aug 24, 2006
799
800
801
802
803
804
805
806
807
static SDL_AudioFilter
SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
{
/*
* Fill in any future conversions that are specialized to a
* processor, platform, compiler, or library here.
*/
Aug 28, 2006
Aug 28, 2006
808
return NULL; /* no specialized converter code available. */
Aug 24, 2006
Aug 24, 2006
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
}
/*
* Find a converter between two data types. We try to select a hand-tuned
* asm/vectorized/optimized function first, and then fallback to an
* autogenerated function that is customized to convert between two
* specific data types.
*/
static int
SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
{
if (src_fmt != dst_fmt) {
const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
/* No hand-tuned converter? Try the autogenerated ones. */
if (filter == NULL) {
int i;
for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
filter = filt->filter;
break;
}
}
if (filter == NULL) {
Nov 25, 2009
Nov 25, 2009
839
840
SDL_SetError("No conversion available for these formats");
return -1;
Aug 24, 2006
Aug 24, 2006
841
842
843
844
845
846
847
848
849
850
851
852
853
}
}
/* Update (cvt) with filter details... */
cvt->filters[cvt->filter_index++] = filter;
if (src_bitsize < dst_bitsize) {
const int mult = (dst_bitsize / src_bitsize);
cvt->len_mult *= mult;
cvt->len_ratio *= mult;
} else if (src_bitsize > dst_bitsize) {
cvt->len_ratio /= (src_bitsize / dst_bitsize);
}
Aug 28, 2006
Aug 28, 2006
854
return 1; /* added a converter. */
Aug 24, 2006
Aug 24, 2006
855
856
}
Aug 28, 2006
Aug 28, 2006
857
return 0; /* no conversion necessary. */
Aug 24, 2006
Aug 24, 2006
858
859
}
Aug 25, 2008
Aug 25, 2008
860
Jan 11, 2009
Jan 11, 2009
861
862
863
static SDL_AudioFilter
SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
int src_rate, int dst_rate)
Aug 25, 2008
Aug 25, 2008
864
{
Jan 11, 2009
Jan 11, 2009
865
866
867
/*
* Fill in any future conversions that are specialized to a
* processor, platform, compiler, or library here.
Aug 25, 2008
Aug 25, 2008
868
869
*/
Jan 11, 2009
Jan 11, 2009
870
return NULL; /* no specialized converter code available. */
Aug 25, 2008
Aug 25, 2008
871
872
}
Jan 11, 2009
Jan 11, 2009
873
874
static int
SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
Aug 25, 2008
Aug 25, 2008
875
{
Jan 11, 2009
Jan 11, 2009
876
int retval = 0;
Aug 25, 2008
Aug 25, 2008
877
Jan 11, 2009
Jan 11, 2009
878
879
880
881
/* If we only built with the arbitrary resamplers, ignore multiples. */
#if !LESS_RESAMPLERS
int lo, hi;
int div;
Aug 25, 2008
Aug 25, 2008
882
Jan 11, 2009
Jan 11, 2009
883
884
885
assert(src_rate != 0);
assert(dst_rate != 0);
assert(src_rate != dst_rate);
Aug 25, 2008
Aug 25, 2008
886
Jan 11, 2009
Jan 11, 2009
887
888
889
if (src_rate < dst_rate) {
lo = src_rate;
hi = dst_rate;
Aug 25, 2008
Aug 25, 2008
890
} else {
Jan 11, 2009
Jan 11, 2009
891
892
lo = dst_rate;
hi = src_rate;
Aug 25, 2008
Aug 25, 2008
893
894
}
Jan 11, 2009
Jan 11, 2009
895
896
/* zero means "not a supported multiple" ... we only do 2x and 4x. */
if ((hi % lo) != 0)
Jan 14, 2009
Jan 14, 2009
897
return 0; /* not a multiple. */
Sep 1, 2008
Sep 1, 2008
898
Jan 11, 2009
Jan 11, 2009
899
900
901
div = hi / lo;
retval = ((div == 2) || (div == 4)) ? div : 0;
#endif
Aug 25, 2008
Aug 25, 2008
902
Jan 11, 2009
Jan 11, 2009
903
return retval;
Aug 25, 2008
Aug 25, 2008
904
905
}
Jan 11, 2009
Jan 11, 2009
906
907
908
static int
SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
int src_rate, int dst_rate)
Aug 25, 2008
Aug 25, 2008
909
{
Jan 11, 2009
Jan 11, 2009
910
911
912
if (src_rate != dst_rate) {
SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
src_rate, dst_rate);
Aug 25, 2008
Aug 25, 2008
913
Jan 11, 2009
Jan 11, 2009
914
915
916
917
/* No hand-tuned converter? Try the autogenerated ones. */
if (filter == NULL) {
int i;
const int upsample = (src_rate < dst_rate) ? 1 : 0;
Jan 14, 2009
Jan 14, 2009
918
919
const int multiple =
SDL_FindFrequencyMultiple(src_rate, dst_rate);
Jan 11, 2009
Jan 11, 2009
920
921
922
923
924
925
926
927
928
929
930
for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
if ((filt->fmt == cvt->dst_format) &&
(filt->channels == dst_channels) &&
(filt->upsample == upsample) &&
(filt->multiple == multiple)) {
filter = filt->filter;
break;
}
}
Aug 25, 2008
Aug 25, 2008
931
Jan 11, 2009
Jan 11, 2009
932
if (filter == NULL) {
Nov 25, 2009
Nov 25, 2009
933
934
SDL_SetError("No conversion available for these rates");
return -1;
Jan 11, 2009
Jan 11, 2009
935
936
}
}
Aug 25, 2008
Aug 25, 2008
937
Jan 11, 2009
Jan 11, 2009
938
939
940
941
/* Update (cvt) with filter details... */
cvt->filters[cvt->filter_index++] = filter;
if (src_rate < dst_rate) {
const double mult = ((double) dst_rate) / ((double) src_rate);
Jan 12, 2009
Jan 12, 2009
942
cvt->len_mult *= (int) SDL_ceil(mult);
Jan 11, 2009
Jan 11, 2009
943
944
945
946
cvt->len_ratio *= mult;
} else {
cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
}
Aug 25, 2008
Aug 25, 2008
947
Jan 11, 2009
Jan 11, 2009
948
return 1; /* added a converter. */
Aug 25, 2008
Aug 25, 2008
949
950
}
Jan 11, 2009
Jan 11, 2009
951
return 0; /* no conversion necessary. */
Aug 25, 2008
Aug 25, 2008
952
}
Aug 24, 2006
Aug 24, 2006
953
954
955
956
957
/* Creates a set of audio filters to convert from one format to another.
Returns -1 if the format conversion is not supported, 0 if there's
no conversion needed, or 1 if the audio filter is set up.
Apr 26, 2001
Apr 26, 2001
958
*/
Jul 10, 2006
Jul 10, 2006
959
960
961
int
SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
Aug 24, 2006
Aug 24, 2006
962
963
SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
Apr 26, 2001
Apr 26, 2001
964
{
Jan 11, 2009
Jan 11, 2009
965
966
967
968
969
970
971
972
/*
* !!! FIXME: reorder filters based on which grow/shrink the buffer.
* !!! FIXME: ideally, we should do everything that shrinks the buffer
* !!! FIXME: first, so we don't have to process as many bytes in a given
* !!! FIXME: filter and abuse the CPU cache less. This might not be as
* !!! FIXME: good in practice as it sounds in theory, though.
*/
Nov 25, 2009
Nov 25, 2009
973
/* there are no unsigned types over 16 bits, so catch this up front. */
Aug 24, 2006
Aug 24, 2006
974
if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
Nov 25, 2009
Nov 25, 2009
975
SDL_SetError("Invalid source format");
Aug 24, 2006
Aug 24, 2006
976
977
978
return -1;
}
if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
Nov 25, 2009
Nov 25, 2009
979
SDL_SetError("Invalid destination format");
Aug 24, 2006
Aug 24, 2006
980
981
return -1;
}
Jan 11, 2009
Jan 11, 2009
982
983
984
/* prevent possible divisions by zero, etc. */
if ((src_rate == 0) || (dst_rate == 0)) {
Nov 25, 2009
Nov 25, 2009
985
SDL_SetError("Source or destination rate is zero");
Jan 11, 2009
Jan 11, 2009
986
987
return -1;
}
Aug 28, 2006
Aug 28, 2006
988
#ifdef DEBUG_CONVERT
Aug 24, 2006
Aug 24, 2006
989
printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
Aug 28, 2006
Aug 28, 2006
990
991
src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
#endif
Aug 24, 2006
Aug 24, 2006
992
Jul 10, 2006
Jul 10, 2006
993
/* Start off with no conversion necessary */
Dec 19, 2008
Dec 19, 2008
994
SDL_zerop(cvt);
Aug 24, 2006
Aug 24, 2006
995
996
cvt->src_format = src_fmt;
cvt->dst_format = dst_fmt;
Jul 10, 2006
Jul 10, 2006
997
998
999
1000
cvt->needed = 0;
cvt->filter_index = 0;
cvt->filters[0] = NULL;
cvt->len_mult = 1;