SDL-1.2.14
[sdl_omap.git] / src / audio / SDL_audiocvt.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/* Functions for audio drivers to perform runtime conversion of audio format */
25
26#include "SDL_audio.h"
27
28
29/* Effectively mix right and left channels into a single channel */
30void SDLCALL SDL_ConvertMono(SDL_AudioCVT *cvt, Uint16 format)
31{
32 int i;
33 Sint32 sample;
34
35#ifdef DEBUG_CONVERT
36 fprintf(stderr, "Converting to mono\n");
37#endif
38 switch (format&0x8018) {
39
40 case AUDIO_U8: {
41 Uint8 *src, *dst;
42
43 src = cvt->buf;
44 dst = cvt->buf;
45 for ( i=cvt->len_cvt/2; i; --i ) {
46 sample = src[0] + src[1];
47 *dst = (Uint8)(sample / 2);
48 src += 2;
49 dst += 1;
50 }
51 }
52 break;
53
54 case AUDIO_S8: {
55 Sint8 *src, *dst;
56
57 src = (Sint8 *)cvt->buf;
58 dst = (Sint8 *)cvt->buf;
59 for ( i=cvt->len_cvt/2; i; --i ) {
60 sample = src[0] + src[1];
61 *dst = (Sint8)(sample / 2);
62 src += 2;
63 dst += 1;
64 }
65 }
66 break;
67
68 case AUDIO_U16: {
69 Uint8 *src, *dst;
70
71 src = cvt->buf;
72 dst = cvt->buf;
73 if ( (format & 0x1000) == 0x1000 ) {
74 for ( i=cvt->len_cvt/4; i; --i ) {
75 sample = (Uint16)((src[0]<<8)|src[1])+
76 (Uint16)((src[2]<<8)|src[3]);
77 sample /= 2;
78 dst[1] = (sample&0xFF);
79 sample >>= 8;
80 dst[0] = (sample&0xFF);
81 src += 4;
82 dst += 2;
83 }
84 } else {
85 for ( i=cvt->len_cvt/4; i; --i ) {
86 sample = (Uint16)((src[1]<<8)|src[0])+
87 (Uint16)((src[3]<<8)|src[2]);
88 sample /= 2;
89 dst[0] = (sample&0xFF);
90 sample >>= 8;
91 dst[1] = (sample&0xFF);
92 src += 4;
93 dst += 2;
94 }
95 }
96 }
97 break;
98
99 case AUDIO_S16: {
100 Uint8 *src, *dst;
101
102 src = cvt->buf;
103 dst = cvt->buf;
104 if ( (format & 0x1000) == 0x1000 ) {
105 for ( i=cvt->len_cvt/4; i; --i ) {
106 sample = (Sint16)((src[0]<<8)|src[1])+
107 (Sint16)((src[2]<<8)|src[3]);
108 sample /= 2;
109 dst[1] = (sample&0xFF);
110 sample >>= 8;
111 dst[0] = (sample&0xFF);
112 src += 4;
113 dst += 2;
114 }
115 } else {
116 for ( i=cvt->len_cvt/4; i; --i ) {
117 sample = (Sint16)((src[1]<<8)|src[0])+
118 (Sint16)((src[3]<<8)|src[2]);
119 sample /= 2;
120 dst[0] = (sample&0xFF);
121 sample >>= 8;
122 dst[1] = (sample&0xFF);
123 src += 4;
124 dst += 2;
125 }
126 }
127 }
128 break;
129 }
130 cvt->len_cvt /= 2;
131 if ( cvt->filters[++cvt->filter_index] ) {
132 cvt->filters[cvt->filter_index](cvt, format);
133 }
134}
135
136/* Discard top 4 channels */
137void SDLCALL SDL_ConvertStrip(SDL_AudioCVT *cvt, Uint16 format)
138{
139 int i;
140 Sint32 lsample, rsample;
141
142#ifdef DEBUG_CONVERT
143 fprintf(stderr, "Converting down to stereo\n");
144#endif
145 switch (format&0x8018) {
146
147 case AUDIO_U8: {
148 Uint8 *src, *dst;
149
150 src = cvt->buf;
151 dst = cvt->buf;
152 for ( i=cvt->len_cvt/6; i; --i ) {
153 dst[0] = src[0];
154 dst[1] = src[1];
155 src += 6;
156 dst += 2;
157 }
158 }
159 break;
160
161 case AUDIO_S8: {
162 Sint8 *src, *dst;
163
164 src = (Sint8 *)cvt->buf;
165 dst = (Sint8 *)cvt->buf;
166 for ( i=cvt->len_cvt/6; i; --i ) {
167 dst[0] = src[0];
168 dst[1] = src[1];
169 src += 6;
170 dst += 2;
171 }
172 }
173 break;
174
175 case AUDIO_U16: {
176 Uint8 *src, *dst;
177
178 src = cvt->buf;
179 dst = cvt->buf;
180 if ( (format & 0x1000) == 0x1000 ) {
181 for ( i=cvt->len_cvt/12; i; --i ) {
182 lsample = (Uint16)((src[0]<<8)|src[1]);
183 rsample = (Uint16)((src[2]<<8)|src[3]);
184 dst[1] = (lsample&0xFF);
185 lsample >>= 8;
186 dst[0] = (lsample&0xFF);
187 dst[3] = (rsample&0xFF);
188 rsample >>= 8;
189 dst[2] = (rsample&0xFF);
190 src += 12;
191 dst += 4;
192 }
193 } else {
194 for ( i=cvt->len_cvt/12; i; --i ) {
195 lsample = (Uint16)((src[1]<<8)|src[0]);
196 rsample = (Uint16)((src[3]<<8)|src[2]);
197 dst[0] = (lsample&0xFF);
198 lsample >>= 8;
199 dst[1] = (lsample&0xFF);
200 dst[2] = (rsample&0xFF);
201 rsample >>= 8;
202 dst[3] = (rsample&0xFF);
203 src += 12;
204 dst += 4;
205 }
206 }
207 }
208 break;
209
210 case AUDIO_S16: {
211 Uint8 *src, *dst;
212
213 src = cvt->buf;
214 dst = cvt->buf;
215 if ( (format & 0x1000) == 0x1000 ) {
216 for ( i=cvt->len_cvt/12; i; --i ) {
217 lsample = (Sint16)((src[0]<<8)|src[1]);
218 rsample = (Sint16)((src[2]<<8)|src[3]);
219 dst[1] = (lsample&0xFF);
220 lsample >>= 8;
221 dst[0] = (lsample&0xFF);
222 dst[3] = (rsample&0xFF);
223 rsample >>= 8;
224 dst[2] = (rsample&0xFF);
225 src += 12;
226 dst += 4;
227 }
228 } else {
229 for ( i=cvt->len_cvt/12; i; --i ) {
230 lsample = (Sint16)((src[1]<<8)|src[0]);
231 rsample = (Sint16)((src[3]<<8)|src[2]);
232 dst[0] = (lsample&0xFF);
233 lsample >>= 8;
234 dst[1] = (lsample&0xFF);
235 dst[2] = (rsample&0xFF);
236 rsample >>= 8;
237 dst[3] = (rsample&0xFF);
238 src += 12;
239 dst += 4;
240 }
241 }
242 }
243 break;
244 }
245 cvt->len_cvt /= 3;
246 if ( cvt->filters[++cvt->filter_index] ) {
247 cvt->filters[cvt->filter_index](cvt, format);
248 }
249}
250
251
252/* Discard top 2 channels of 6 */
253void SDLCALL SDL_ConvertStrip_2(SDL_AudioCVT *cvt, Uint16 format)
254{
255 int i;
256 Sint32 lsample, rsample;
257
258#ifdef DEBUG_CONVERT
259 fprintf(stderr, "Converting 6 down to quad\n");
260#endif
261 switch (format&0x8018) {
262
263 case AUDIO_U8: {
264 Uint8 *src, *dst;
265
266 src = cvt->buf;
267 dst = cvt->buf;
268 for ( i=cvt->len_cvt/4; i; --i ) {
269 dst[0] = src[0];
270 dst[1] = src[1];
271 src += 4;
272 dst += 2;
273 }
274 }
275 break;
276
277 case AUDIO_S8: {
278 Sint8 *src, *dst;
279
280 src = (Sint8 *)cvt->buf;
281 dst = (Sint8 *)cvt->buf;
282 for ( i=cvt->len_cvt/4; i; --i ) {
283 dst[0] = src[0];
284 dst[1] = src[1];
285 src += 4;
286 dst += 2;
287 }
288 }
289 break;
290
291 case AUDIO_U16: {
292 Uint8 *src, *dst;
293
294 src = cvt->buf;
295 dst = cvt->buf;
296 if ( (format & 0x1000) == 0x1000 ) {
297 for ( i=cvt->len_cvt/8; i; --i ) {
298 lsample = (Uint16)((src[0]<<8)|src[1]);
299 rsample = (Uint16)((src[2]<<8)|src[3]);
300 dst[1] = (lsample&0xFF);
301 lsample >>= 8;
302 dst[0] = (lsample&0xFF);
303 dst[3] = (rsample&0xFF);
304 rsample >>= 8;
305 dst[2] = (rsample&0xFF);
306 src += 8;
307 dst += 4;
308 }
309 } else {
310 for ( i=cvt->len_cvt/8; i; --i ) {
311 lsample = (Uint16)((src[1]<<8)|src[0]);
312 rsample = (Uint16)((src[3]<<8)|src[2]);
313 dst[0] = (lsample&0xFF);
314 lsample >>= 8;
315 dst[1] = (lsample&0xFF);
316 dst[2] = (rsample&0xFF);
317 rsample >>= 8;
318 dst[3] = (rsample&0xFF);
319 src += 8;
320 dst += 4;
321 }
322 }
323 }
324 break;
325
326 case AUDIO_S16: {
327 Uint8 *src, *dst;
328
329 src = cvt->buf;
330 dst = cvt->buf;
331 if ( (format & 0x1000) == 0x1000 ) {
332 for ( i=cvt->len_cvt/8; i; --i ) {
333 lsample = (Sint16)((src[0]<<8)|src[1]);
334 rsample = (Sint16)((src[2]<<8)|src[3]);
335 dst[1] = (lsample&0xFF);
336 lsample >>= 8;
337 dst[0] = (lsample&0xFF);
338 dst[3] = (rsample&0xFF);
339 rsample >>= 8;
340 dst[2] = (rsample&0xFF);
341 src += 8;
342 dst += 4;
343 }
344 } else {
345 for ( i=cvt->len_cvt/8; i; --i ) {
346 lsample = (Sint16)((src[1]<<8)|src[0]);
347 rsample = (Sint16)((src[3]<<8)|src[2]);
348 dst[0] = (lsample&0xFF);
349 lsample >>= 8;
350 dst[1] = (lsample&0xFF);
351 dst[2] = (rsample&0xFF);
352 rsample >>= 8;
353 dst[3] = (rsample&0xFF);
354 src += 8;
355 dst += 4;
356 }
357 }
358 }
359 break;
360 }
361 cvt->len_cvt /= 2;
362 if ( cvt->filters[++cvt->filter_index] ) {
363 cvt->filters[cvt->filter_index](cvt, format);
364 }
365}
366
367/* Duplicate a mono channel to both stereo channels */
368void SDLCALL SDL_ConvertStereo(SDL_AudioCVT *cvt, Uint16 format)
369{
370 int i;
371
372#ifdef DEBUG_CONVERT
373 fprintf(stderr, "Converting to stereo\n");
374#endif
375 if ( (format & 0xFF) == 16 ) {
376 Uint16 *src, *dst;
377
378 src = (Uint16 *)(cvt->buf+cvt->len_cvt);
379 dst = (Uint16 *)(cvt->buf+cvt->len_cvt*2);
380 for ( i=cvt->len_cvt/2; i; --i ) {
381 dst -= 2;
382 src -= 1;
383 dst[0] = src[0];
384 dst[1] = src[0];
385 }
386 } else {
387 Uint8 *src, *dst;
388
389 src = cvt->buf+cvt->len_cvt;
390 dst = cvt->buf+cvt->len_cvt*2;
391 for ( i=cvt->len_cvt; i; --i ) {
392 dst -= 2;
393 src -= 1;
394 dst[0] = src[0];
395 dst[1] = src[0];
396 }
397 }
398 cvt->len_cvt *= 2;
399 if ( cvt->filters[++cvt->filter_index] ) {
400 cvt->filters[cvt->filter_index](cvt, format);
401 }
402}
403
404
405/* Duplicate a stereo channel to a pseudo-5.1 stream */
406void SDLCALL SDL_ConvertSurround(SDL_AudioCVT *cvt, Uint16 format)
407{
408 int i;
409
410#ifdef DEBUG_CONVERT
411 fprintf(stderr, "Converting stereo to surround\n");
412#endif
413 switch (format&0x8018) {
414
415 case AUDIO_U8: {
416 Uint8 *src, *dst, lf, rf, ce;
417
418 src = (Uint8 *)(cvt->buf+cvt->len_cvt);
419 dst = (Uint8 *)(cvt->buf+cvt->len_cvt*3);
420 for ( i=cvt->len_cvt; i; --i ) {
421 dst -= 6;
422 src -= 2;
423 lf = src[0];
424 rf = src[1];
425 ce = (lf/2) + (rf/2);
426 dst[0] = lf;
427 dst[1] = rf;
428 dst[2] = lf - ce;
429 dst[3] = rf - ce;
430 dst[4] = ce;
431 dst[5] = ce;
432 }
433 }
434 break;
435
436 case AUDIO_S8: {
437 Sint8 *src, *dst, lf, rf, ce;
438
439 src = (Sint8 *)cvt->buf+cvt->len_cvt;
440 dst = (Sint8 *)cvt->buf+cvt->len_cvt*3;
441 for ( i=cvt->len_cvt; i; --i ) {
442 dst -= 6;
443 src -= 2;
444 lf = src[0];
445 rf = src[1];
446 ce = (lf/2) + (rf/2);
447 dst[0] = lf;
448 dst[1] = rf;
449 dst[2] = lf - ce;
450 dst[3] = rf - ce;
451 dst[4] = ce;
452 dst[5] = ce;
453 }
454 }
455 break;
456
457 case AUDIO_U16: {
458 Uint8 *src, *dst;
459 Uint16 lf, rf, ce, lr, rr;
460
461 src = cvt->buf+cvt->len_cvt;
462 dst = cvt->buf+cvt->len_cvt*3;
463
464 if ( (format & 0x1000) == 0x1000 ) {
465 for ( i=cvt->len_cvt/4; i; --i ) {
466 dst -= 12;
467 src -= 4;
468 lf = (Uint16)((src[0]<<8)|src[1]);
469 rf = (Uint16)((src[2]<<8)|src[3]);
470 ce = (lf/2) + (rf/2);
471 rr = lf - ce;
472 lr = rf - ce;
473 dst[1] = (lf&0xFF);
474 dst[0] = ((lf>>8)&0xFF);
475 dst[3] = (rf&0xFF);
476 dst[2] = ((rf>>8)&0xFF);
477
478 dst[1+4] = (lr&0xFF);
479 dst[0+4] = ((lr>>8)&0xFF);
480 dst[3+4] = (rr&0xFF);
481 dst[2+4] = ((rr>>8)&0xFF);
482
483 dst[1+8] = (ce&0xFF);
484 dst[0+8] = ((ce>>8)&0xFF);
485 dst[3+8] = (ce&0xFF);
486 dst[2+8] = ((ce>>8)&0xFF);
487 }
488 } else {
489 for ( i=cvt->len_cvt/4; i; --i ) {
490 dst -= 12;
491 src -= 4;
492 lf = (Uint16)((src[1]<<8)|src[0]);
493 rf = (Uint16)((src[3]<<8)|src[2]);
494 ce = (lf/2) + (rf/2);
495 rr = lf - ce;
496 lr = rf - ce;
497 dst[0] = (lf&0xFF);
498 dst[1] = ((lf>>8)&0xFF);
499 dst[2] = (rf&0xFF);
500 dst[3] = ((rf>>8)&0xFF);
501
502 dst[0+4] = (lr&0xFF);
503 dst[1+4] = ((lr>>8)&0xFF);
504 dst[2+4] = (rr&0xFF);
505 dst[3+4] = ((rr>>8)&0xFF);
506
507 dst[0+8] = (ce&0xFF);
508 dst[1+8] = ((ce>>8)&0xFF);
509 dst[2+8] = (ce&0xFF);
510 dst[3+8] = ((ce>>8)&0xFF);
511 }
512 }
513 }
514 break;
515
516 case AUDIO_S16: {
517 Uint8 *src, *dst;
518 Sint16 lf, rf, ce, lr, rr;
519
520 src = cvt->buf+cvt->len_cvt;
521 dst = cvt->buf+cvt->len_cvt*3;
522
523 if ( (format & 0x1000) == 0x1000 ) {
524 for ( i=cvt->len_cvt/4; i; --i ) {
525 dst -= 12;
526 src -= 4;
527 lf = (Sint16)((src[0]<<8)|src[1]);
528 rf = (Sint16)((src[2]<<8)|src[3]);
529 ce = (lf/2) + (rf/2);
530 rr = lf - ce;
531 lr = rf - ce;
532 dst[1] = (lf&0xFF);
533 dst[0] = ((lf>>8)&0xFF);
534 dst[3] = (rf&0xFF);
535 dst[2] = ((rf>>8)&0xFF);
536
537 dst[1+4] = (lr&0xFF);
538 dst[0+4] = ((lr>>8)&0xFF);
539 dst[3+4] = (rr&0xFF);
540 dst[2+4] = ((rr>>8)&0xFF);
541
542 dst[1+8] = (ce&0xFF);
543 dst[0+8] = ((ce>>8)&0xFF);
544 dst[3+8] = (ce&0xFF);
545 dst[2+8] = ((ce>>8)&0xFF);
546 }
547 } else {
548 for ( i=cvt->len_cvt/4; i; --i ) {
549 dst -= 12;
550 src -= 4;
551 lf = (Sint16)((src[1]<<8)|src[0]);
552 rf = (Sint16)((src[3]<<8)|src[2]);
553 ce = (lf/2) + (rf/2);
554 rr = lf - ce;
555 lr = rf - ce;
556 dst[0] = (lf&0xFF);
557 dst[1] = ((lf>>8)&0xFF);
558 dst[2] = (rf&0xFF);
559 dst[3] = ((rf>>8)&0xFF);
560
561 dst[0+4] = (lr&0xFF);
562 dst[1+4] = ((lr>>8)&0xFF);
563 dst[2+4] = (rr&0xFF);
564 dst[3+4] = ((rr>>8)&0xFF);
565
566 dst[0+8] = (ce&0xFF);
567 dst[1+8] = ((ce>>8)&0xFF);
568 dst[2+8] = (ce&0xFF);
569 dst[3+8] = ((ce>>8)&0xFF);
570 }
571 }
572 }
573 break;
574 }
575 cvt->len_cvt *= 3;
576 if ( cvt->filters[++cvt->filter_index] ) {
577 cvt->filters[cvt->filter_index](cvt, format);
578 }
579}
580
581
582/* Duplicate a stereo channel to a pseudo-4.0 stream */
583void SDLCALL SDL_ConvertSurround_4(SDL_AudioCVT *cvt, Uint16 format)
584{
585 int i;
586
587#ifdef DEBUG_CONVERT
588 fprintf(stderr, "Converting stereo to quad\n");
589#endif
590 switch (format&0x8018) {
591
592 case AUDIO_U8: {
593 Uint8 *src, *dst, lf, rf, ce;
594
595 src = (Uint8 *)(cvt->buf+cvt->len_cvt);
596 dst = (Uint8 *)(cvt->buf+cvt->len_cvt*2);
597 for ( i=cvt->len_cvt; i; --i ) {
598 dst -= 4;
599 src -= 2;
600 lf = src[0];
601 rf = src[1];
602 ce = (lf/2) + (rf/2);
603 dst[0] = lf;
604 dst[1] = rf;
605 dst[2] = lf - ce;
606 dst[3] = rf - ce;
607 }
608 }
609 break;
610
611 case AUDIO_S8: {
612 Sint8 *src, *dst, lf, rf, ce;
613
614 src = (Sint8 *)cvt->buf+cvt->len_cvt;
615 dst = (Sint8 *)cvt->buf+cvt->len_cvt*2;
616 for ( i=cvt->len_cvt; i; --i ) {
617 dst -= 4;
618 src -= 2;
619 lf = src[0];
620 rf = src[1];
621 ce = (lf/2) + (rf/2);
622 dst[0] = lf;
623 dst[1] = rf;
624 dst[2] = lf - ce;
625 dst[3] = rf - ce;
626 }
627 }
628 break;
629
630 case AUDIO_U16: {
631 Uint8 *src, *dst;
632 Uint16 lf, rf, ce, lr, rr;
633
634 src = cvt->buf+cvt->len_cvt;
635 dst = cvt->buf+cvt->len_cvt*2;
636
637 if ( (format & 0x1000) == 0x1000 ) {
638 for ( i=cvt->len_cvt/4; i; --i ) {
639 dst -= 8;
640 src -= 4;
641 lf = (Uint16)((src[0]<<8)|src[1]);
642 rf = (Uint16)((src[2]<<8)|src[3]);
643 ce = (lf/2) + (rf/2);
644 rr = lf - ce;
645 lr = rf - ce;
646 dst[1] = (lf&0xFF);
647 dst[0] = ((lf>>8)&0xFF);
648 dst[3] = (rf&0xFF);
649 dst[2] = ((rf>>8)&0xFF);
650
651 dst[1+4] = (lr&0xFF);
652 dst[0+4] = ((lr>>8)&0xFF);
653 dst[3+4] = (rr&0xFF);
654 dst[2+4] = ((rr>>8)&0xFF);
655 }
656 } else {
657 for ( i=cvt->len_cvt/4; i; --i ) {
658 dst -= 8;
659 src -= 4;
660 lf = (Uint16)((src[1]<<8)|src[0]);
661 rf = (Uint16)((src[3]<<8)|src[2]);
662 ce = (lf/2) + (rf/2);
663 rr = lf - ce;
664 lr = rf - ce;
665 dst[0] = (lf&0xFF);
666 dst[1] = ((lf>>8)&0xFF);
667 dst[2] = (rf&0xFF);
668 dst[3] = ((rf>>8)&0xFF);
669
670 dst[0+4] = (lr&0xFF);
671 dst[1+4] = ((lr>>8)&0xFF);
672 dst[2+4] = (rr&0xFF);
673 dst[3+4] = ((rr>>8)&0xFF);
674 }
675 }
676 }
677 break;
678
679 case AUDIO_S16: {
680 Uint8 *src, *dst;
681 Sint16 lf, rf, ce, lr, rr;
682
683 src = cvt->buf+cvt->len_cvt;
684 dst = cvt->buf+cvt->len_cvt*2;
685
686 if ( (format & 0x1000) == 0x1000 ) {
687 for ( i=cvt->len_cvt/4; i; --i ) {
688 dst -= 8;
689 src -= 4;
690 lf = (Sint16)((src[0]<<8)|src[1]);
691 rf = (Sint16)((src[2]<<8)|src[3]);
692 ce = (lf/2) + (rf/2);
693 rr = lf - ce;
694 lr = rf - ce;
695 dst[1] = (lf&0xFF);
696 dst[0] = ((lf>>8)&0xFF);
697 dst[3] = (rf&0xFF);
698 dst[2] = ((rf>>8)&0xFF);
699
700 dst[1+4] = (lr&0xFF);
701 dst[0+4] = ((lr>>8)&0xFF);
702 dst[3+4] = (rr&0xFF);
703 dst[2+4] = ((rr>>8)&0xFF);
704 }
705 } else {
706 for ( i=cvt->len_cvt/4; i; --i ) {
707 dst -= 8;
708 src -= 4;
709 lf = (Sint16)((src[1]<<8)|src[0]);
710 rf = (Sint16)((src[3]<<8)|src[2]);
711 ce = (lf/2) + (rf/2);
712 rr = lf - ce;
713 lr = rf - ce;
714 dst[0] = (lf&0xFF);
715 dst[1] = ((lf>>8)&0xFF);
716 dst[2] = (rf&0xFF);
717 dst[3] = ((rf>>8)&0xFF);
718
719 dst[0+4] = (lr&0xFF);
720 dst[1+4] = ((lr>>8)&0xFF);
721 dst[2+4] = (rr&0xFF);
722 dst[3+4] = ((rr>>8)&0xFF);
723 }
724 }
725 }
726 break;
727 }
728 cvt->len_cvt *= 2;
729 if ( cvt->filters[++cvt->filter_index] ) {
730 cvt->filters[cvt->filter_index](cvt, format);
731 }
732}
733
734
735/* Convert 8-bit to 16-bit - LSB */
736void SDLCALL SDL_Convert16LSB(SDL_AudioCVT *cvt, Uint16 format)
737{
738 int i;
739 Uint8 *src, *dst;
740
741#ifdef DEBUG_CONVERT
742 fprintf(stderr, "Converting to 16-bit LSB\n");
743#endif
744 src = cvt->buf+cvt->len_cvt;
745 dst = cvt->buf+cvt->len_cvt*2;
746 for ( i=cvt->len_cvt; i; --i ) {
747 src -= 1;
748 dst -= 2;
749 dst[1] = *src;
750 dst[0] = 0;
751 }
752 format = ((format & ~0x0008) | AUDIO_U16LSB);
753 cvt->len_cvt *= 2;
754 if ( cvt->filters[++cvt->filter_index] ) {
755 cvt->filters[cvt->filter_index](cvt, format);
756 }
757}
758/* Convert 8-bit to 16-bit - MSB */
759void SDLCALL SDL_Convert16MSB(SDL_AudioCVT *cvt, Uint16 format)
760{
761 int i;
762 Uint8 *src, *dst;
763
764#ifdef DEBUG_CONVERT
765 fprintf(stderr, "Converting to 16-bit MSB\n");
766#endif
767 src = cvt->buf+cvt->len_cvt;
768 dst = cvt->buf+cvt->len_cvt*2;
769 for ( i=cvt->len_cvt; i; --i ) {
770 src -= 1;
771 dst -= 2;
772 dst[0] = *src;
773 dst[1] = 0;
774 }
775 format = ((format & ~0x0008) | AUDIO_U16MSB);
776 cvt->len_cvt *= 2;
777 if ( cvt->filters[++cvt->filter_index] ) {
778 cvt->filters[cvt->filter_index](cvt, format);
779 }
780}
781
782/* Convert 16-bit to 8-bit */
783void SDLCALL SDL_Convert8(SDL_AudioCVT *cvt, Uint16 format)
784{
785 int i;
786 Uint8 *src, *dst;
787
788#ifdef DEBUG_CONVERT
789 fprintf(stderr, "Converting to 8-bit\n");
790#endif
791 src = cvt->buf;
792 dst = cvt->buf;
793 if ( (format & 0x1000) != 0x1000 ) { /* Little endian */
794 ++src;
795 }
796 for ( i=cvt->len_cvt/2; i; --i ) {
797 *dst = *src;
798 src += 2;
799 dst += 1;
800 }
801 format = ((format & ~0x9010) | AUDIO_U8);
802 cvt->len_cvt /= 2;
803 if ( cvt->filters[++cvt->filter_index] ) {
804 cvt->filters[cvt->filter_index](cvt, format);
805 }
806}
807
808/* Toggle signed/unsigned */
809void SDLCALL SDL_ConvertSign(SDL_AudioCVT *cvt, Uint16 format)
810{
811 int i;
812 Uint8 *data;
813
814#ifdef DEBUG_CONVERT
815 fprintf(stderr, "Converting audio signedness\n");
816#endif
817 data = cvt->buf;
818 if ( (format & 0xFF) == 16 ) {
819 if ( (format & 0x1000) != 0x1000 ) { /* Little endian */
820 ++data;
821 }
822 for ( i=cvt->len_cvt/2; i; --i ) {
823 *data ^= 0x80;
824 data += 2;
825 }
826 } else {
827 for ( i=cvt->len_cvt; i; --i ) {
828 *data++ ^= 0x80;
829 }
830 }
831 format = (format ^ 0x8000);
832 if ( cvt->filters[++cvt->filter_index] ) {
833 cvt->filters[cvt->filter_index](cvt, format);
834 }
835}
836
837/* Toggle endianness */
838void SDLCALL SDL_ConvertEndian(SDL_AudioCVT *cvt, Uint16 format)
839{
840 int i;
841 Uint8 *data, tmp;
842
843#ifdef DEBUG_CONVERT
844 fprintf(stderr, "Converting audio endianness\n");
845#endif
846 data = cvt->buf;
847 for ( i=cvt->len_cvt/2; i; --i ) {
848 tmp = data[0];
849 data[0] = data[1];
850 data[1] = tmp;
851 data += 2;
852 }
853 format = (format ^ 0x1000);
854 if ( cvt->filters[++cvt->filter_index] ) {
855 cvt->filters[cvt->filter_index](cvt, format);
856 }
857}
858
859/* Convert rate up by multiple of 2 */
860void SDLCALL SDL_RateMUL2(SDL_AudioCVT *cvt, Uint16 format)
861{
862 int i;
863 Uint8 *src, *dst;
864
865#ifdef DEBUG_CONVERT
866 fprintf(stderr, "Converting audio rate * 2\n");
867#endif
868 src = cvt->buf+cvt->len_cvt;
869 dst = cvt->buf+cvt->len_cvt*2;
870 switch (format & 0xFF) {
871 case 8:
872 for ( i=cvt->len_cvt; i; --i ) {
873 src -= 1;
874 dst -= 2;
875 dst[0] = src[0];
876 dst[1] = src[0];
877 }
878 break;
879 case 16:
880 for ( i=cvt->len_cvt/2; i; --i ) {
881 src -= 2;
882 dst -= 4;
883 dst[0] = src[0];
884 dst[1] = src[1];
885 dst[2] = src[0];
886 dst[3] = src[1];
887 }
888 break;
889 }
890 cvt->len_cvt *= 2;
891 if ( cvt->filters[++cvt->filter_index] ) {
892 cvt->filters[cvt->filter_index](cvt, format);
893 }
894}
895
896
897/* Convert rate up by multiple of 2, for stereo */
898void SDLCALL SDL_RateMUL2_c2(SDL_AudioCVT *cvt, Uint16 format)
899{
900 int i;
901 Uint8 *src, *dst;
902
903#ifdef DEBUG_CONVERT
904 fprintf(stderr, "Converting audio rate * 2\n");
905#endif
906 src = cvt->buf+cvt->len_cvt;
907 dst = cvt->buf+cvt->len_cvt*2;
908 switch (format & 0xFF) {
909 case 8:
910 for ( i=cvt->len_cvt/2; i; --i ) {
911 src -= 2;
912 dst -= 4;
913 dst[0] = src[0];
914 dst[1] = src[1];
915 dst[2] = src[0];
916 dst[3] = src[1];
917 }
918 break;
919 case 16:
920 for ( i=cvt->len_cvt/4; i; --i ) {
921 src -= 4;
922 dst -= 8;
923 dst[0] = src[0];
924 dst[1] = src[1];
925 dst[2] = src[2];
926 dst[3] = src[3];
927 dst[4] = src[0];
928 dst[5] = src[1];
929 dst[6] = src[2];
930 dst[7] = src[3];
931 }
932 break;
933 }
934 cvt->len_cvt *= 2;
935 if ( cvt->filters[++cvt->filter_index] ) {
936 cvt->filters[cvt->filter_index](cvt, format);
937 }
938}
939
940/* Convert rate up by multiple of 2, for quad */
941void SDLCALL SDL_RateMUL2_c4(SDL_AudioCVT *cvt, Uint16 format)
942{
943 int i;
944 Uint8 *src, *dst;
945
946#ifdef DEBUG_CONVERT
947 fprintf(stderr, "Converting audio rate * 2\n");
948#endif
949 src = cvt->buf+cvt->len_cvt;
950 dst = cvt->buf+cvt->len_cvt*2;
951 switch (format & 0xFF) {
952 case 8:
953 for ( i=cvt->len_cvt/4; i; --i ) {
954 src -= 4;
955 dst -= 8;
956 dst[0] = src[0];
957 dst[1] = src[1];
958 dst[2] = src[2];
959 dst[3] = src[3];
960 dst[4] = src[0];
961 dst[5] = src[1];
962 dst[6] = src[2];
963 dst[7] = src[3];
964 }
965 break;
966 case 16:
967 for ( i=cvt->len_cvt/8; i; --i ) {
968 src -= 8;
969 dst -= 16;
970 dst[0] = src[0];
971 dst[1] = src[1];
972 dst[2] = src[2];
973 dst[3] = src[3];
974 dst[4] = src[4];
975 dst[5] = src[5];
976 dst[6] = src[6];
977 dst[7] = src[7];
978 dst[8] = src[0];
979 dst[9] = src[1];
980 dst[10] = src[2];
981 dst[11] = src[3];
982 dst[12] = src[4];
983 dst[13] = src[5];
984 dst[14] = src[6];
985 dst[15] = src[7];
986 }
987 break;
988 }
989 cvt->len_cvt *= 2;
990 if ( cvt->filters[++cvt->filter_index] ) {
991 cvt->filters[cvt->filter_index](cvt, format);
992 }
993}
994
995
996/* Convert rate up by multiple of 2, for 5.1 */
997void SDLCALL SDL_RateMUL2_c6(SDL_AudioCVT *cvt, Uint16 format)
998{
999 int i;
1000 Uint8 *src, *dst;
1001
1002#ifdef DEBUG_CONVERT
1003 fprintf(stderr, "Converting audio rate * 2\n");
1004#endif
1005 src = cvt->buf+cvt->len_cvt;
1006 dst = cvt->buf+cvt->len_cvt*2;
1007 switch (format & 0xFF) {
1008 case 8:
1009 for ( i=cvt->len_cvt/6; i; --i ) {
1010 src -= 6;
1011 dst -= 12;
1012 dst[0] = src[0];
1013 dst[1] = src[1];
1014 dst[2] = src[2];
1015 dst[3] = src[3];
1016 dst[4] = src[4];
1017 dst[5] = src[5];
1018 dst[6] = src[0];
1019 dst[7] = src[1];
1020 dst[8] = src[2];
1021 dst[9] = src[3];
1022 dst[10] = src[4];
1023 dst[11] = src[5];
1024 }
1025 break;
1026 case 16:
1027 for ( i=cvt->len_cvt/12; i; --i ) {
1028 src -= 12;
1029 dst -= 24;
1030 dst[0] = src[0];
1031 dst[1] = src[1];
1032 dst[2] = src[2];
1033 dst[3] = src[3];
1034 dst[4] = src[4];
1035 dst[5] = src[5];
1036 dst[6] = src[6];
1037 dst[7] = src[7];
1038 dst[8] = src[8];
1039 dst[9] = src[9];
1040 dst[10] = src[10];
1041 dst[11] = src[11];
1042 dst[12] = src[0];
1043 dst[13] = src[1];
1044 dst[14] = src[2];
1045 dst[15] = src[3];
1046 dst[16] = src[4];
1047 dst[17] = src[5];
1048 dst[18] = src[6];
1049 dst[19] = src[7];
1050 dst[20] = src[8];
1051 dst[21] = src[9];
1052 dst[22] = src[10];
1053 dst[23] = src[11];
1054 }
1055 break;
1056 }
1057 cvt->len_cvt *= 2;
1058 if ( cvt->filters[++cvt->filter_index] ) {
1059 cvt->filters[cvt->filter_index](cvt, format);
1060 }
1061}
1062
1063/* Convert rate down by multiple of 2 */
1064void SDLCALL SDL_RateDIV2(SDL_AudioCVT *cvt, Uint16 format)
1065{
1066 int i;
1067 Uint8 *src, *dst;
1068
1069#ifdef DEBUG_CONVERT
1070 fprintf(stderr, "Converting audio rate / 2\n");
1071#endif
1072 src = cvt->buf;
1073 dst = cvt->buf;
1074 switch (format & 0xFF) {
1075 case 8:
1076 for ( i=cvt->len_cvt/2; i; --i ) {
1077 dst[0] = src[0];
1078 src += 2;
1079 dst += 1;
1080 }
1081 break;
1082 case 16:
1083 for ( i=cvt->len_cvt/4; i; --i ) {
1084 dst[0] = src[0];
1085 dst[1] = src[1];
1086 src += 4;
1087 dst += 2;
1088 }
1089 break;
1090 }
1091 cvt->len_cvt /= 2;
1092 if ( cvt->filters[++cvt->filter_index] ) {
1093 cvt->filters[cvt->filter_index](cvt, format);
1094 }
1095}
1096
1097
1098/* Convert rate down by multiple of 2, for stereo */
1099void SDLCALL SDL_RateDIV2_c2(SDL_AudioCVT *cvt, Uint16 format)
1100{
1101 int i;
1102 Uint8 *src, *dst;
1103
1104#ifdef DEBUG_CONVERT
1105 fprintf(stderr, "Converting audio rate / 2\n");
1106#endif
1107 src = cvt->buf;
1108 dst = cvt->buf;
1109 switch (format & 0xFF) {
1110 case 8:
1111 for ( i=cvt->len_cvt/4; i; --i ) {
1112 dst[0] = src[0];
1113 dst[1] = src[1];
1114 src += 4;
1115 dst += 2;
1116 }
1117 break;
1118 case 16:
1119 for ( i=cvt->len_cvt/8; i; --i ) {
1120 dst[0] = src[0];
1121 dst[1] = src[1];
1122 dst[2] = src[2];
1123 dst[3] = src[3];
1124 src += 8;
1125 dst += 4;
1126 }
1127 break;
1128 }
1129 cvt->len_cvt /= 2;
1130 if ( cvt->filters[++cvt->filter_index] ) {
1131 cvt->filters[cvt->filter_index](cvt, format);
1132 }
1133}
1134
1135
1136/* Convert rate down by multiple of 2, for quad */
1137void SDLCALL SDL_RateDIV2_c4(SDL_AudioCVT *cvt, Uint16 format)
1138{
1139 int i;
1140 Uint8 *src, *dst;
1141
1142#ifdef DEBUG_CONVERT
1143 fprintf(stderr, "Converting audio rate / 2\n");
1144#endif
1145 src = cvt->buf;
1146 dst = cvt->buf;
1147 switch (format & 0xFF) {
1148 case 8:
1149 for ( i=cvt->len_cvt/8; i; --i ) {
1150 dst[0] = src[0];
1151 dst[1] = src[1];
1152 dst[2] = src[2];
1153 dst[3] = src[3];
1154 src += 8;
1155 dst += 4;
1156 }
1157 break;
1158 case 16:
1159 for ( i=cvt->len_cvt/16; i; --i ) {
1160 dst[0] = src[0];
1161 dst[1] = src[1];
1162 dst[2] = src[2];
1163 dst[3] = src[3];
1164 dst[4] = src[4];
1165 dst[5] = src[5];
1166 dst[6] = src[6];
1167 dst[7] = src[7];
1168 src += 16;
1169 dst += 8;
1170 }
1171 break;
1172 }
1173 cvt->len_cvt /= 2;
1174 if ( cvt->filters[++cvt->filter_index] ) {
1175 cvt->filters[cvt->filter_index](cvt, format);
1176 }
1177}
1178
1179/* Convert rate down by multiple of 2, for 5.1 */
1180void SDLCALL SDL_RateDIV2_c6(SDL_AudioCVT *cvt, Uint16 format)
1181{
1182 int i;
1183 Uint8 *src, *dst;
1184
1185#ifdef DEBUG_CONVERT
1186 fprintf(stderr, "Converting audio rate / 2\n");
1187#endif
1188 src = cvt->buf;
1189 dst = cvt->buf;
1190 switch (format & 0xFF) {
1191 case 8:
1192 for ( i=cvt->len_cvt/12; i; --i ) {
1193 dst[0] = src[0];
1194 dst[1] = src[1];
1195 dst[2] = src[2];
1196 dst[3] = src[3];
1197 dst[4] = src[4];
1198 dst[5] = src[5];
1199 src += 12;
1200 dst += 6;
1201 }
1202 break;
1203 case 16:
1204 for ( i=cvt->len_cvt/24; i; --i ) {
1205 dst[0] = src[0];
1206 dst[1] = src[1];
1207 dst[2] = src[2];
1208 dst[3] = src[3];
1209 dst[4] = src[4];
1210 dst[5] = src[5];
1211 dst[6] = src[6];
1212 dst[7] = src[7];
1213 dst[8] = src[8];
1214 dst[9] = src[9];
1215 dst[10] = src[10];
1216 dst[11] = src[11];
1217 src += 24;
1218 dst += 12;
1219 }
1220 break;
1221 }
1222 cvt->len_cvt /= 2;
1223 if ( cvt->filters[++cvt->filter_index] ) {
1224 cvt->filters[cvt->filter_index](cvt, format);
1225 }
1226}
1227
1228/* Very slow rate conversion routine */
1229void SDLCALL SDL_RateSLOW(SDL_AudioCVT *cvt, Uint16 format)
1230{
1231 double ipos;
1232 int i, clen;
1233
1234#ifdef DEBUG_CONVERT
1235 fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr);
1236#endif
1237 clen = (int)((double)cvt->len_cvt / cvt->rate_incr);
1238 if ( cvt->rate_incr > 1.0 ) {
1239 switch (format & 0xFF) {
1240 case 8: {
1241 Uint8 *output;
1242
1243 output = cvt->buf;
1244 ipos = 0.0;
1245 for ( i=clen; i; --i ) {
1246 *output = cvt->buf[(int)ipos];
1247 ipos += cvt->rate_incr;
1248 output += 1;
1249 }
1250 }
1251 break;
1252
1253 case 16: {
1254 Uint16 *output;
1255
1256 clen &= ~1;
1257 output = (Uint16 *)cvt->buf;
1258 ipos = 0.0;
1259 for ( i=clen/2; i; --i ) {
1260 *output=((Uint16 *)cvt->buf)[(int)ipos];
1261 ipos += cvt->rate_incr;
1262 output += 1;
1263 }
1264 }
1265 break;
1266 }
1267 } else {
1268 switch (format & 0xFF) {
1269 case 8: {
1270 Uint8 *output;
1271
1272 output = cvt->buf+clen;
1273 ipos = (double)cvt->len_cvt;
1274 for ( i=clen; i; --i ) {
1275 ipos -= cvt->rate_incr;
1276 output -= 1;
1277 *output = cvt->buf[(int)ipos];
1278 }
1279 }
1280 break;
1281
1282 case 16: {
1283 Uint16 *output;
1284
1285 clen &= ~1;
1286 output = (Uint16 *)(cvt->buf+clen);
1287 ipos = (double)cvt->len_cvt/2;
1288 for ( i=clen/2; i; --i ) {
1289 ipos -= cvt->rate_incr;
1290 output -= 1;
1291 *output=((Uint16 *)cvt->buf)[(int)ipos];
1292 }
1293 }
1294 break;
1295 }
1296 }
1297 cvt->len_cvt = clen;
1298 if ( cvt->filters[++cvt->filter_index] ) {
1299 cvt->filters[cvt->filter_index](cvt, format);
1300 }
1301}
1302
1303int SDL_ConvertAudio(SDL_AudioCVT *cvt)
1304{
1305 /* Make sure there's data to convert */
1306 if ( cvt->buf == NULL ) {
1307 SDL_SetError("No buffer allocated for conversion");
1308 return(-1);
1309 }
1310 /* Return okay if no conversion is necessary */
1311 cvt->len_cvt = cvt->len;
1312 if ( cvt->filters[0] == NULL ) {
1313 return(0);
1314 }
1315
1316 /* Set up the conversion and go! */
1317 cvt->filter_index = 0;
1318 cvt->filters[0](cvt, cvt->src_format);
1319 return(0);
1320}
1321
1322/* Creates a set of audio filters to convert from one format to another.
1323 Returns -1 if the format conversion is not supported, or 1 if the
1324 audio filter is set up.
1325*/
1326
1327int SDL_BuildAudioCVT(SDL_AudioCVT *cvt,
1328 Uint16 src_format, Uint8 src_channels, int src_rate,
1329 Uint16 dst_format, Uint8 dst_channels, int dst_rate)
1330{
1331/*printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
1332 src_format, dst_format, src_channels, dst_channels, src_rate, dst_rate);*/
1333 /* Start off with no conversion necessary */
1334 cvt->needed = 0;
1335 cvt->filter_index = 0;
1336 cvt->filters[0] = NULL;
1337 cvt->len_mult = 1;
1338 cvt->len_ratio = 1.0;
1339
1340 /* First filter: Endian conversion from src to dst */
1341 if ( (src_format & 0x1000) != (dst_format & 0x1000)
1342 && ((src_format & 0xff) == 16) && ((dst_format & 0xff) == 16)) {
1343 cvt->filters[cvt->filter_index++] = SDL_ConvertEndian;
1344 }
1345
1346 /* Second filter: Sign conversion -- signed/unsigned */
1347 if ( (src_format & 0x8000) != (dst_format & 0x8000) ) {
1348 cvt->filters[cvt->filter_index++] = SDL_ConvertSign;
1349 }
1350
1351 /* Next filter: Convert 16 bit <--> 8 bit PCM */
1352 if ( (src_format & 0xFF) != (dst_format & 0xFF) ) {
1353 switch (dst_format&0x10FF) {
1354 case AUDIO_U8:
1355 cvt->filters[cvt->filter_index++] =
1356 SDL_Convert8;
1357 cvt->len_ratio /= 2;
1358 break;
1359 case AUDIO_U16LSB:
1360 cvt->filters[cvt->filter_index++] =
1361 SDL_Convert16LSB;
1362 cvt->len_mult *= 2;
1363 cvt->len_ratio *= 2;
1364 break;
1365 case AUDIO_U16MSB:
1366 cvt->filters[cvt->filter_index++] =
1367 SDL_Convert16MSB;
1368 cvt->len_mult *= 2;
1369 cvt->len_ratio *= 2;
1370 break;
1371 }
1372 }
1373
1374 /* Last filter: Mono/Stereo conversion */
1375 if ( src_channels != dst_channels ) {
1376 if ( (src_channels == 1) && (dst_channels > 1) ) {
1377 cvt->filters[cvt->filter_index++] =
1378 SDL_ConvertStereo;
1379 cvt->len_mult *= 2;
1380 src_channels = 2;
1381 cvt->len_ratio *= 2;
1382 }
1383 if ( (src_channels == 2) &&
1384 (dst_channels == 6) ) {
1385 cvt->filters[cvt->filter_index++] =
1386 SDL_ConvertSurround;
1387 src_channels = 6;
1388 cvt->len_mult *= 3;
1389 cvt->len_ratio *= 3;
1390 }
1391 if ( (src_channels == 2) &&
1392 (dst_channels == 4) ) {
1393 cvt->filters[cvt->filter_index++] =
1394 SDL_ConvertSurround_4;
1395 src_channels = 4;
1396 cvt->len_mult *= 2;
1397 cvt->len_ratio *= 2;
1398 }
1399 while ( (src_channels*2) <= dst_channels ) {
1400 cvt->filters[cvt->filter_index++] =
1401 SDL_ConvertStereo;
1402 cvt->len_mult *= 2;
1403 src_channels *= 2;
1404 cvt->len_ratio *= 2;
1405 }
1406 if ( (src_channels == 6) &&
1407 (dst_channels <= 2) ) {
1408 cvt->filters[cvt->filter_index++] =
1409 SDL_ConvertStrip;
1410 src_channels = 2;
1411 cvt->len_ratio /= 3;
1412 }
1413 if ( (src_channels == 6) &&
1414 (dst_channels == 4) ) {
1415 cvt->filters[cvt->filter_index++] =
1416 SDL_ConvertStrip_2;
1417 src_channels = 4;
1418 cvt->len_ratio /= 2;
1419 }
1420 /* This assumes that 4 channel audio is in the format:
1421 Left {front/back} + Right {front/back}
1422 so converting to L/R stereo works properly.
1423 */
1424 while ( ((src_channels%2) == 0) &&
1425 ((src_channels/2) >= dst_channels) ) {
1426 cvt->filters[cvt->filter_index++] =
1427 SDL_ConvertMono;
1428 src_channels /= 2;
1429 cvt->len_ratio /= 2;
1430 }
1431 if ( src_channels != dst_channels ) {
1432 /* Uh oh.. */;
1433 }
1434 }
1435
1436 /* Do rate conversion */
1437 cvt->rate_incr = 0.0;
1438 if ( (src_rate/100) != (dst_rate/100) ) {
1439 Uint32 hi_rate, lo_rate;
1440 int len_mult;
1441 double len_ratio;
1442 void (SDLCALL *rate_cvt)(SDL_AudioCVT *cvt, Uint16 format);
1443
1444 if ( src_rate > dst_rate ) {
1445 hi_rate = src_rate;
1446 lo_rate = dst_rate;
1447 switch (src_channels) {
1448 case 1: rate_cvt = SDL_RateDIV2; break;
1449 case 2: rate_cvt = SDL_RateDIV2_c2; break;
1450 case 4: rate_cvt = SDL_RateDIV2_c4; break;
1451 case 6: rate_cvt = SDL_RateDIV2_c6; break;
1452 default: return -1;
1453 }
1454 len_mult = 1;
1455 len_ratio = 0.5;
1456 } else {
1457 hi_rate = dst_rate;
1458 lo_rate = src_rate;
1459 switch (src_channels) {
1460 case 1: rate_cvt = SDL_RateMUL2; break;
1461 case 2: rate_cvt = SDL_RateMUL2_c2; break;
1462 case 4: rate_cvt = SDL_RateMUL2_c4; break;
1463 case 6: rate_cvt = SDL_RateMUL2_c6; break;
1464 default: return -1;
1465 }
1466 len_mult = 2;
1467 len_ratio = 2.0;
1468 }
1469 /* If hi_rate = lo_rate*2^x then conversion is easy */
1470 while ( ((lo_rate*2)/100) <= (hi_rate/100) ) {
1471 cvt->filters[cvt->filter_index++] = rate_cvt;
1472 cvt->len_mult *= len_mult;
1473 lo_rate *= 2;
1474 cvt->len_ratio *= len_ratio;
1475 }
1476 /* We may need a slow conversion here to finish up */
1477 if ( (lo_rate/100) != (hi_rate/100) ) {
1478#if 1
1479 /* The problem with this is that if the input buffer is
1480 say 1K, and the conversion rate is say 1.1, then the
1481 output buffer is 1.1K, which may not be an acceptable
1482 buffer size for the audio driver (not a power of 2)
1483 */
1484 /* For now, punt and hope the rate distortion isn't great.
1485 */
1486#else
1487 if ( src_rate < dst_rate ) {
1488 cvt->rate_incr = (double)lo_rate/hi_rate;
1489 cvt->len_mult *= 2;
1490 cvt->len_ratio /= cvt->rate_incr;
1491 } else {
1492 cvt->rate_incr = (double)hi_rate/lo_rate;
1493 cvt->len_ratio *= cvt->rate_incr;
1494 }
1495 cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
1496#endif
1497 }
1498 }
1499
1500 /* Set up the filter information */
1501 if ( cvt->filter_index != 0 ) {
1502 cvt->needed = 1;
1503 cvt->src_format = src_format;
1504 cvt->dst_format = dst_format;
1505 cvt->len = 0;
1506 cvt->buf = NULL;
1507 cvt->filters[cvt->filter_index] = NULL;
1508 }
1509 return(cvt->needed);
1510}