190bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard/*
290bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    SDL - Simple DirectMedia Layer
390bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    Copyright (C) 1997-2012 Sam Lantinga
490bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard
590bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    This library is free software; you can redistribute it and/or
690bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    modify it under the terms of the GNU Lesser General Public
790bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    License as published by the Free Software Foundation; either
890bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    version 2.1 of the License, or (at your option) any later version.
990bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard
1090bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    This library is distributed in the hope that it will be useful,
1190bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    but WITHOUT ANY WARRANTY; without even the implied warranty of
1290bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1390bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    Lesser General Public License for more details.
1490bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard
1590bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    You should have received a copy of the GNU Lesser General Public
1690bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    License along with this library; if not, write to the Free Software
1790bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1890bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard
1990bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    Sam Lantinga
2090bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard    slouken@libsdl.org
2190bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard*/
2290bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard#include "SDL_config.h"
2390bd1d52bbf95947955a66ec67f5f6c7dc87119aTom Stellard
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}
1511