This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_audiocvt.c
1079 lines (952 loc) · 34.2 KB
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.
20
*/
21
#include "SDL_config.h"
23
24
25
/* Functions for audio drivers to perform runtime conversion of audio format */
#include "SDL_audio.h"
26
#include "SDL_audio_c.h"
28
/* #define DEBUG_CONVERT */
30
31
32
/* !!! FIXME */
#ifndef assert
#define assert(x)
35
/* Effectively mix right and left channels into a single channel */
36
37
static void SDLCALL
SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
39
40
int i;
Sint32 sample;
41
42
#ifdef DEBUG_CONVERT
43
fprintf(stderr, "Converting to mono\n");
44
#endif
45
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
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];
54
*dst = (Uint8) (sample / 2);
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];
69
*dst = (Sint8) (sample / 2);
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;
82
if (SDL_AUDIO_ISBIGENDIAN(format)) {
83
84
85
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Uint16) ((src[0] << 8) | src[1]) +
(Uint16) ((src[2] << 8) | src[3]);
86
87
88
89
sample /= 2;
dst[1] = (sample & 0xFF);
sample >>= 8;
dst[0] = (sample & 0xFF);
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]);
97
98
99
100
sample /= 2;
dst[0] = (sample & 0xFF);
sample >>= 8;
dst[1] = (sample & 0xFF);
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;
114
if (SDL_AUDIO_ISBIGENDIAN(format)) {
115
116
117
for (i = cvt->len_cvt / 4; i; --i) {
sample = (Sint16) ((src[0] << 8) | src[1]) +
(Sint16) ((src[2] << 8) | src[3]);
118
119
120
121
sample /= 2;
dst[1] = (sample & 0xFF);
sample >>= 8;
dst[0] = (sample & 0xFF);
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]);
129
130
131
132
sample /= 2;
dst[0] = (sample & 0xFF);
sample >>= 8;
dst[1] = (sample & 0xFF);
133
134
135
136
137
138
139
src += 4;
dst += 2;
}
}
}
break;
140
case AUDIO_S32:
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 =
147
148
(((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
((Sint64) (Sint32) SDL_SwapBE32(src[1])));
149
*(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
150
151
}
} else {
152
153
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
const Sint64 added =
154
155
(((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
((Sint64) (Sint32) SDL_SwapLE32(src[1])));
156
*(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
157
158
159
160
161
}
}
}
break;
162
case AUDIO_F32:
164
165
const float *src = (const float *) cvt->buf;
float *dst = (float *) cvt->buf;
166
167
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
168
169
const float src1 = SDL_SwapFloatBE(src[0]);
const float src2 = SDL_SwapFloatBE(src[1]);
170
const double added = ((double) src1) + ((double) src2);
171
172
const float halved = (float) (added * 0.5);
*(dst++) = SDL_SwapFloatBE(halved);
173
174
}
} else {
175
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
176
177
const float src1 = SDL_SwapFloatLE(src[0]);
const float src2 = SDL_SwapFloatLE(src[1]);
178
const double added = ((double) src1) + ((double) src2);
179
180
const float halved = (float) (added * 0.5);
*(dst++) = SDL_SwapFloatLE(halved);
181
182
183
184
185
}
}
}
break;
}
186
187
cvt->len_cvt /= 2;
188
189
190
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
194
195
196
/* Discard top 4 channels */
static void SDLCALL
SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
199
200
#ifdef DEBUG_CONVERT
201
fprintf(stderr, "Converting down from 6 channels to stereo\n");
204
#define strip_chans_6_to_2(type) \
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; \
} \
}
216
217
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
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;
229
#undef strip_chans_6_to_2
231
232
233
234
235
cvt->len_cvt /= 3;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
}
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;
244
245
246
#ifdef DEBUG_CONVERT
fprintf(stderr, "Converting 6 down to quad\n");
#endif
248
#define strip_chans_6_to_4(type) \
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; \
} \
261
262
263
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
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;
275
#undef strip_chans_6_to_4
276
277
278
cvt->len_cvt /= 6;
cvt->len_cvt *= 4;
279
280
281
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
283
284
/* Duplicate a mono channel to both stereo channels */
285
286
static void SDLCALL
SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
287
{
289
290
#ifdef DEBUG_CONVERT
291
fprintf(stderr, "Converting to stereo\n");
292
#endif
294
#define dup_chans_1_to_2(type) \
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; \
} \
304
305
306
/* this function only cares about typesize, and data as a block of bits. */
switch (SDL_AUDIO_BITSIZE(format)) {
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;
318
#undef dup_chans_1_to_2
320
321
322
323
cvt->len_cvt *= 2;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
324
325
}
326
327
/* Duplicate a stereo channel to a pseudo-5.1 stream */
328
329
static void SDLCALL
SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
332
333
#ifdef DEBUG_CONVERT
334
fprintf(stderr, "Converting stereo to surround\n");
337
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
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;
390
if (SDL_AUDIO_ISBIGENDIAN(format)) {
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;
450
if (SDL_AUDIO_ISBIGENDIAN(format)) {
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;
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;
543
544
const float *src = (const float *) cvt->buf + cvt->len_cvt;
float *dst = (float *) cvt->buf + cvt->len_cvt * 3;
545
546
547
548
549
if (SDL_AUDIO_ISBIGENDIAN(format)) {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
550
551
lf = SDL_SwapFloatBE(src[0]);
rf = SDL_SwapFloatBE(src[1]);
552
553
554
ce = (lf * 0.5f) + (rf * 0.5f);
dst[0] = src[0];
dst[1] = src[1];
555
556
557
dst[2] = SDL_SwapFloatBE(lf - ce);
dst[3] = SDL_SwapFloatBE(rf - ce);
dst[4] = dst[5] = SDL_SwapFloatBE(ce);
558
559
560
561
562
}
} else {
for (i = cvt->len_cvt / 8; i; --i) {
dst -= 6;
src -= 2;
563
564
lf = SDL_SwapFloatLE(src[0]);
rf = SDL_SwapFloatLE(src[1]);
565
566
567
ce = (lf * 0.5f) + (rf * 0.5f);
dst[0] = src[0];
dst[1] = src[1];
568
569
570
dst[2] = SDL_SwapFloatLE(lf - ce);
dst[3] = SDL_SwapFloatLE(rf - ce);
dst[4] = dst[5] = SDL_SwapFloatLE(ce);
571
572
573
574
575
}
}
}
break;
576
577
578
579
580
}
cvt->len_cvt *= 3;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
581
582
583
584
}
/* Duplicate a stereo channel to a pseudo-4.0 stream */
585
586
static void SDLCALL
SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
589
590
#ifdef DEBUG_CONVERT
591
fprintf(stderr, "Converting stereo to quad\n");
594
switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) {
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;
643
if (SDL_AUDIO_ISBIGENDIAN(format)) {
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;
693
if (SDL_AUDIO_ISBIGENDIAN(format)) {
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;
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;
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;
768
769
770
771
772
}
cvt->len_cvt *= 2;
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
}
773
774
775
}
776
777
int
SDL_ConvertAudio(SDL_AudioCVT * cvt)
778
{
779
780
781
/* !!! FIXME: (cvt) should be const; stack-copy it here. */
/* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
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);
797
798
}
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.
*/
808
return NULL; /* no specialized converter code available. */
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) {
839
840
SDL_SetError("No conversion available for these formats");
return -1;
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);
}
854
return 1; /* added a converter. */
857
return 0; /* no conversion necessary. */
861
862
863
static SDL_AudioFilter
SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
int src_rate, int dst_rate)
865
866
867
/*
* Fill in any future conversions that are specialized to a
* processor, platform, compiler, or library here.
870
return NULL; /* no specialized converter code available. */
873
874
static int
SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
876
int retval = 0;
878
879
880
881
/* If we only built with the arbitrary resamplers, ignore multiples. */
#if !LESS_RESAMPLERS
int lo, hi;
int div;
883
884
885
assert(src_rate != 0);
assert(dst_rate != 0);
assert(src_rate != dst_rate);
887
888
889
if (src_rate < dst_rate) {
lo = src_rate;
hi = dst_rate;
891
892
lo = dst_rate;
hi = src_rate;
895
896
/* zero means "not a supported multiple" ... we only do 2x and 4x. */
if ((hi % lo) != 0)
897
return 0; /* not a multiple. */
899
900
901
div = hi / lo;
retval = ((div == 2) || (div == 4)) ? div : 0;
#endif
903
return retval;
906
907
908
static int
SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
int src_rate, int dst_rate)
910
911
912
if (src_rate != dst_rate) {
SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
src_rate, dst_rate);
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;
918
919
const int multiple =
SDL_FindFrequencyMultiple(src_rate, dst_rate);
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;
}
}
932
if (filter == NULL) {
933
934
SDL_SetError("No conversion available for these rates");
return -1;
935
936
}
}
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);
942
cvt->len_mult *= (int) SDL_ceil(mult);
943
944
945
946
cvt->len_ratio *= mult;
} else {
cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
}
948
return 1; /* added a converter. */
951
return 0; /* no conversion necessary. */
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.
958
*/
959
960
961
int
SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
962
963
SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
964
{
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.
*/
973
/* there are no unsigned types over 16 bits, so catch this up front. */
974
if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
975
SDL_SetError("Invalid source format");
976
977
978
return -1;
}
if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
979
SDL_SetError("Invalid destination format");
980
981
return -1;
}
982
983
984
/* prevent possible divisions by zero, etc. */
if ((src_rate == 0) || (dst_rate == 0)) {
985
SDL_SetError("Source or destination rate is zero");
986
987
return -1;
}
988
#ifdef DEBUG_CONVERT
989
printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
990
991
src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
#endif
993
/* Start off with no conversion necessary */
994
SDL_zerop(cvt);
995
996
cvt->src_format = src_fmt;
cvt->dst_format = dst_fmt;
997
998
999
1000
cvt->needed = 0;
cvt->filter_index = 0;
cvt->filters[0] = NULL;
cvt->len_mult = 1;