Mercurial > SDL_sound_CoreAudio
annotate audio_convert.c @ 562:7e08477b0fc1
MP3 decoder upgrade work.
Ripped out SMPEG and mpglib support, replaced it with "mpg123.c" and libmpg123.
libmpg123 is a much better version of mpglib, so it should solve all the
problems about MP3's not seeking, or most modern MP3's not playing at all,
etc. Since you no longer have to make a tradeoff with SMPEG for features, and
SMPEG is basically rotting, I removed it from the project.
There is still work to be done with libmpg123...there are MMX, 3DNow, SSE,
Altivec, etc decoders which we don't have enabled at the moment, and the
build system could use some work to make this compile more cleanly, etc.
Still: huge win.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 30 Jan 2009 02:44:47 -0500 |
parents | 9e761a594df1 |
children |
rev | line source |
---|---|
141 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 */ | |
22 | |
23 /* | |
24 * This file was derived from SDL's SDL_audiocvt.c and is an attempt to | |
25 * address the shortcomings of it. | |
26 * | |
27 * Perhaps we can adapt some good filters from SoX? | |
28 */ | |
29 | |
30 #if HAVE_CONFIG_H | |
31 # include <config.h> | |
32 #endif | |
33 | |
34 #include "SDL.h" | |
35 #include "SDL_sound.h" | |
36 | |
37 #define __SDL_SOUND_INTERNAL__ | |
38 #include "SDL_sound_internal.h" | |
39 | |
40 /* Functions for audio drivers to perform runtime conversion of audio format */ | |
41 | |
42 | |
43 /* | |
44 * Toggle endianness. This filter is, of course, only applied to 16-bit | |
45 * audio data. | |
46 */ | |
47 | |
342 | 48 static void Sound_ConvertEndian(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 49 { |
50 int i; | |
51 Uint8 *data, tmp; | |
52 | |
53 /* SNDDBG(("Converting audio endianness\n")); */ | |
54 | |
55 data = cvt->buf; | |
56 | |
57 for (i = cvt->len_cvt / 2; i; --i) | |
58 { | |
59 tmp = data[0]; | |
60 data[0] = data[1]; | |
61 data[1] = tmp; | |
62 data += 2; | |
63 } /* for */ | |
64 | |
65 *format = (*format ^ 0x1000); | |
66 } /* Sound_ConvertEndian */ | |
67 | |
68 | |
69 /* | |
70 * Toggle signed/unsigned. Apparently this is done by toggling the most | |
71 * significant bit of each sample. | |
72 */ | |
73 | |
342 | 74 static void Sound_ConvertSign(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 75 { |
76 int i; | |
77 Uint8 *data; | |
78 | |
79 /* SNDDBG(("Converting audio signedness\n")); */ | |
80 | |
81 data = cvt->buf; | |
82 | |
83 /* 16-bit sound? */ | |
84 if ((*format & 0xFF) == 16) | |
85 { | |
86 /* Little-endian? */ | |
87 if ((*format & 0x1000) != 0x1000) | |
88 ++data; | |
89 | |
90 for (i = cvt->len_cvt / 2; i; --i) | |
91 { | |
92 *data ^= 0x80; | |
93 data += 2; | |
94 } /* for */ | |
95 } /* if */ | |
96 else | |
97 { | |
98 for (i = cvt->len_cvt; i; --i) | |
99 *data++ ^= 0x80; | |
100 } /* else */ | |
101 | |
102 *format = (*format ^ 0x8000); | |
103 } /* Sound_ConvertSign */ | |
104 | |
105 | |
106 /* | |
107 * Convert 16-bit to 8-bit. This is done by taking the most significant byte | |
108 * of each 16-bit sample. | |
109 */ | |
110 | |
342 | 111 static void Sound_Convert8(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 112 { |
113 int i; | |
114 Uint8 *src, *dst; | |
115 | |
116 /* SNDDBG(("Converting to 8-bit\n")); */ | |
117 | |
118 src = cvt->buf; | |
119 dst = cvt->buf; | |
120 | |
121 /* Little-endian? */ | |
122 if ((*format & 0x1000) != 0x1000) | |
123 ++src; | |
124 | |
125 for (i = cvt->len_cvt / 2; i; --i) | |
126 { | |
127 *dst = *src; | |
128 src += 2; | |
129 dst += 1; | |
130 } /* for */ | |
131 | |
132 *format = ((*format & ~0x9010) | AUDIO_U8); | |
133 cvt->len_cvt /= 2; | |
134 } /* Sound_Convert8 */ | |
135 | |
136 | |
137 /* Convert 8-bit to 16-bit - LSB */ | |
138 | |
342 | 139 static void Sound_Convert16LSB(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 140 { |
141 int i; | |
142 Uint8 *src, *dst; | |
143 | |
144 /* SNDDBG(("Converting to 16-bit LSB\n")); */ | |
145 | |
146 src = cvt->buf + cvt->len_cvt; | |
147 dst = cvt->buf + cvt->len_cvt * 2; | |
148 | |
149 for (i = cvt->len_cvt; i; --i) | |
150 { | |
151 src -= 1; | |
152 dst -= 2; | |
153 dst[1] = *src; | |
154 dst[0] = 0; | |
155 } /* for */ | |
156 | |
157 *format = ((*format & ~0x0008) | AUDIO_U16LSB); | |
158 cvt->len_cvt *= 2; | |
159 } /* Sound_Convert16LSB */ | |
160 | |
161 | |
162 /* Convert 8-bit to 16-bit - MSB */ | |
163 | |
342 | 164 static void Sound_Convert16MSB(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 165 { |
166 int i; | |
167 Uint8 *src, *dst; | |
168 | |
169 /* SNDDBG(("Converting to 16-bit MSB\n")); */ | |
170 | |
171 src = cvt->buf + cvt->len_cvt; | |
172 dst = cvt->buf + cvt->len_cvt * 2; | |
173 | |
174 for (i = cvt->len_cvt; i; --i) | |
175 { | |
176 src -= 1; | |
177 dst -= 2; | |
178 dst[0] = *src; | |
179 dst[1] = 0; | |
180 } /* for */ | |
181 | |
182 *format = ((*format & ~0x0008) | AUDIO_U16MSB); | |
183 cvt->len_cvt *= 2; | |
184 } /* Sound_Convert16MSB */ | |
185 | |
186 | |
187 /* Duplicate a mono channel to both stereo channels */ | |
188 | |
342 | 189 static void Sound_ConvertStereo(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 190 { |
191 int i; | |
192 | |
193 /* SNDDBG(("Converting to stereo\n")); */ | |
194 | |
195 /* 16-bit sound? */ | |
196 if ((*format & 0xFF) == 16) | |
197 { | |
198 Uint16 *src, *dst; | |
199 | |
200 src = (Uint16 *) (cvt->buf + cvt->len_cvt); | |
201 dst = (Uint16 *) (cvt->buf + cvt->len_cvt * 2); | |
202 | |
203 for (i = cvt->len_cvt/2; i; --i) | |
204 { | |
205 dst -= 2; | |
206 src -= 1; | |
207 dst[0] = src[0]; | |
208 dst[1] = src[0]; | |
209 } /* for */ | |
210 } /* if */ | |
211 else | |
212 { | |
213 Uint8 *src, *dst; | |
214 | |
215 src = cvt->buf + cvt->len_cvt; | |
216 dst = cvt->buf + cvt->len_cvt * 2; | |
217 | |
218 for (i = cvt->len_cvt; i; --i) | |
219 { | |
220 dst -= 2; | |
221 src -= 1; | |
222 dst[0] = src[0]; | |
223 dst[1] = src[0]; | |
224 } /* for */ | |
225 } /* else */ | |
226 | |
227 cvt->len_cvt *= 2; | |
228 } /* Sound_ConvertStereo */ | |
229 | |
230 | |
231 /* Effectively mix right and left channels into a single channel */ | |
232 | |
342 | 233 static void Sound_ConvertMono(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 234 { |
235 int i; | |
236 Sint32 sample; | |
237 Uint8 *u_src, *u_dst; | |
238 Sint8 *s_src, *s_dst; | |
239 | |
240 /* SNDDBG(("Converting to mono\n")); */ | |
241 | |
242 switch (*format) | |
243 { | |
244 case AUDIO_U8: | |
245 u_src = cvt->buf; | |
246 u_dst = cvt->buf; | |
247 | |
248 for (i = cvt->len_cvt / 2; i; --i) | |
249 { | |
250 sample = u_src[0] + u_src[1]; | |
251 *u_dst = (sample > 255) ? 255 : sample; | |
252 u_src += 2; | |
253 u_dst += 1; | |
254 } /* for */ | |
255 break; | |
256 | |
257 case AUDIO_S8: | |
258 s_src = (Sint8 *) cvt->buf; | |
259 s_dst = (Sint8 *) cvt->buf; | |
260 | |
261 for (i = cvt->len_cvt / 2; i; --i) | |
262 { | |
263 sample = s_src[0] + s_src[1]; | |
264 if (sample > 127) | |
265 *s_dst = 127; | |
266 else if (sample < -128) | |
267 *s_dst = -128; | |
268 else | |
269 *s_dst = sample; | |
270 | |
271 s_src += 2; | |
272 s_dst += 1; | |
273 } /* for */ | |
274 break; | |
275 | |
276 case AUDIO_U16MSB: | |
277 u_src = cvt->buf; | |
278 u_dst = cvt->buf; | |
279 | |
280 for (i = cvt->len_cvt / 4; i; --i) | |
281 { | |
282 sample = (Uint16) ((u_src[0] << 8) | u_src[1]) | |
283 + (Uint16) ((u_src[2] << 8) | u_src[3]); | |
284 if (sample > 65535) | |
285 { | |
286 u_dst[0] = 0xFF; | |
287 u_dst[1] = 0xFF; | |
288 } /* if */ | |
289 else | |
290 { | |
291 u_dst[1] = (sample & 0xFF); | |
292 sample >>= 8; | |
293 u_dst[0] = (sample & 0xFF); | |
294 } /* else */ | |
295 u_src += 4; | |
296 u_dst += 2; | |
297 } /* for */ | |
298 break; | |
299 | |
300 case AUDIO_U16LSB: | |
301 u_src = cvt->buf; | |
302 u_dst = cvt->buf; | |
303 | |
304 for (i = cvt->len_cvt / 4; i; --i) | |
305 { | |
306 sample = (Uint16) ((u_src[1] << 8) | u_src[0]) | |
307 + (Uint16) ((u_src[3] << 8) | u_src[2]); | |
308 if (sample > 65535) | |
309 { | |
310 u_dst[0] = 0xFF; | |
311 u_dst[1] = 0xFF; | |
312 } /* if */ | |
313 else | |
314 { | |
315 u_dst[0] = (sample & 0xFF); | |
316 sample >>= 8; | |
317 u_dst[1] = (sample & 0xFF); | |
318 } /* else */ | |
319 u_src += 4; | |
320 u_dst += 2; | |
321 } /* for */ | |
322 break; | |
323 | |
324 case AUDIO_S16MSB: | |
325 u_src = cvt->buf; | |
326 u_dst = cvt->buf; | |
327 | |
328 for (i = cvt->len_cvt / 4; i; --i) | |
329 { | |
330 sample = (Sint16) ((u_src[0] << 8) | u_src[1]) | |
331 + (Sint16) ((u_src[2] << 8) | u_src[3]); | |
332 if (sample > 32767) | |
333 { | |
334 u_dst[0] = 0x7F; | |
335 u_dst[1] = 0xFF; | |
336 } /* if */ | |
337 else if (sample < -32768) | |
338 { | |
339 u_dst[0] = 0x80; | |
340 u_dst[1] = 0x00; | |
341 } /* else if */ | |
342 else | |
343 { | |
344 u_dst[1] = (sample & 0xFF); | |
345 sample >>= 8; | |
346 u_dst[0] = (sample & 0xFF); | |
347 } /* else */ | |
348 u_src += 4; | |
349 u_dst += 2; | |
350 } /* for */ | |
351 break; | |
352 | |
353 case AUDIO_S16LSB: | |
354 u_src = cvt->buf; | |
355 u_dst = cvt->buf; | |
356 | |
357 for (i = cvt->len_cvt / 4; i; --i) | |
358 { | |
359 sample = (Sint16) ((u_src[1] << 8) | u_src[0]) | |
360 + (Sint16) ((u_src[3] << 8) | u_src[2]); | |
361 if (sample > 32767) | |
362 { | |
363 u_dst[1] = 0x7F; | |
364 u_dst[0] = 0xFF; | |
365 } /* if */ | |
366 else if (sample < -32768) | |
367 { | |
368 u_dst[1] = 0x80; | |
369 u_dst[0] = 0x00; | |
370 } /* else if */ | |
371 else | |
372 { | |
373 u_dst[0] = (sample & 0xFF); | |
374 sample >>= 8; | |
375 u_dst[1] = (sample & 0xFF); | |
376 } /* else */ | |
377 u_src += 4; | |
378 u_dst += 2; | |
379 } /* for */ | |
380 break; | |
381 } /* switch */ | |
382 | |
383 cvt->len_cvt /= 2; | |
384 } /* Sound_ConvertMono */ | |
385 | |
386 | |
387 /* Convert rate up by multiple of 2 */ | |
388 | |
342 | 389 static void Sound_RateMUL2(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 390 { |
391 int i; | |
392 Uint8 *src, *dst; | |
393 | |
394 /* SNDDBG(("Converting audio rate * 2\n")); */ | |
395 | |
396 src = cvt->buf + cvt->len_cvt; | |
397 dst = cvt->buf + cvt->len_cvt*2; | |
398 | |
399 /* 8- or 16-bit sound? */ | |
400 switch (*format & 0xFF) | |
401 { | |
402 case 8: | |
403 for (i = cvt->len_cvt; i; --i) | |
404 { | |
405 src -= 1; | |
406 dst -= 2; | |
407 dst[0] = src[0]; | |
408 dst[1] = src[0]; | |
409 } /* for */ | |
410 break; | |
411 | |
412 case 16: | |
413 for (i = cvt->len_cvt / 2; i; --i) | |
414 { | |
415 src -= 2; | |
416 dst -= 4; | |
417 dst[0] = src[0]; | |
418 dst[1] = src[1]; | |
419 dst[2] = src[0]; | |
420 dst[3] = src[1]; | |
421 } /* for */ | |
422 break; | |
423 } /* switch */ | |
424 | |
425 cvt->len_cvt *= 2; | |
426 } /* Sound_RateMUL2 */ | |
427 | |
428 | |
429 /* Convert rate down by multiple of 2 */ | |
430 | |
342 | 431 static void Sound_RateDIV2(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 432 { |
433 int i; | |
434 Uint8 *src, *dst; | |
435 | |
436 /* SNDDBG(("Converting audio rate / 2\n")); */ | |
437 | |
438 src = cvt->buf; | |
439 dst = cvt->buf; | |
440 | |
441 /* 8- or 16-bit sound? */ | |
442 switch (*format & 0xFF) | |
443 { | |
444 case 8: | |
445 for (i = cvt->len_cvt / 2; i; --i) | |
446 { | |
447 dst[0] = src[0]; | |
448 src += 2; | |
449 dst += 1; | |
450 } /* for */ | |
451 break; | |
452 | |
453 case 16: | |
454 for (i = cvt->len_cvt / 4; i; --i) | |
455 { | |
456 dst[0] = src[0]; | |
457 dst[1] = src[1]; | |
458 src += 4; | |
459 dst += 2; | |
460 } | |
461 break; | |
462 } /* switch */ | |
463 | |
464 cvt->len_cvt /= 2; | |
465 } /* Sound_RateDIV2 */ | |
466 | |
467 | |
468 /* Very slow rate conversion routine */ | |
469 | |
342 | 470 static void Sound_RateSLOW(Sound_AudioCVT *cvt, Uint16 *format) |
141 | 471 { |
472 double ipos; | |
473 int i, clen; | |
474 Uint8 *output8; | |
475 Uint16 *output16; | |
476 | |
477 /* SNDDBG(("Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr)); */ | |
478 | |
479 clen = (int) ((double) cvt->len_cvt / cvt->rate_incr); | |
480 | |
481 if (cvt->rate_incr > 1.0) | |
482 { | |
483 /* 8- or 16-bit sound? */ | |
484 switch (*format & 0xFF) | |
485 { | |
486 case 8: | |
487 output8 = cvt->buf; | |
488 | |
489 ipos = 0.0; | |
490 for (i = clen; i; --i) | |
491 { | |
492 *output8 = cvt->buf[(int) ipos]; | |
493 ipos += cvt->rate_incr; | |
494 output8 += 1; | |
495 } /* for */ | |
496 break; | |
497 | |
498 case 16: | |
499 output16 = (Uint16 *) cvt->buf; | |
500 | |
501 clen &= ~1; | |
502 ipos = 0.0; | |
503 for (i = clen / 2; i; --i) | |
504 { | |
505 *output16 = ((Uint16 *) cvt->buf)[(int) ipos]; | |
506 ipos += cvt->rate_incr; | |
507 output16 += 1; | |
508 } /* for */ | |
509 break; | |
510 } /* switch */ | |
511 } /* if */ | |
512 else | |
513 { | |
514 /* 8- or 16-bit sound */ | |
515 switch (*format & 0xFF) | |
516 { | |
517 case 8: | |
518 output8 = cvt->buf + clen; | |
519 | |
520 ipos = (double) cvt->len_cvt; | |
521 for (i = clen; i; --i) | |
522 { | |
523 ipos -= cvt->rate_incr; | |
524 output8 -= 1; | |
525 *output8 = cvt->buf[(int) ipos]; | |
526 } /* for */ | |
527 break; | |
528 | |
529 case 16: | |
530 clen &= ~1; | |
531 output16 = (Uint16 *) (cvt->buf + clen); | |
532 ipos = (double) cvt->len_cvt / 2; | |
533 for (i = clen / 2; i; --i) | |
534 { | |
535 ipos -= cvt->rate_incr; | |
536 output16 -= 1; | |
537 *output16 = ((Uint16 *) cvt->buf)[(int) ipos]; | |
538 } /* for */ | |
539 break; | |
540 } /* switch */ | |
541 } /* else */ | |
542 | |
543 cvt->len_cvt = clen; | |
544 } /* Sound_RateSLOW */ | |
545 | |
546 | |
547 int Sound_ConvertAudio(Sound_AudioCVT *cvt) | |
548 { | |
549 Uint16 format; | |
550 | |
551 /* Make sure there's data to convert */ | |
552 if (cvt->buf == NULL) | |
553 { | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
382
diff
changeset
|
554 __Sound_SetError("No buffer allocated for conversion"); |
141 | 555 return(-1); |
556 } /* if */ | |
557 | |
558 /* Return okay if no conversion is necessary */ | |
559 cvt->len_cvt = cvt->len; | |
560 if (cvt->filters[0] == NULL) | |
561 return(0); | |
562 | |
563 /* Set up the conversion and go! */ | |
564 format = cvt->src_format; | |
565 for (cvt->filter_index = 0; cvt->filters[cvt->filter_index]; | |
566 cvt->filter_index++) | |
567 { | |
568 cvt->filters[cvt->filter_index](cvt, &format); | |
569 } | |
570 return(0); | |
571 } /* Sound_ConvertAudio */ | |
572 | |
573 | |
574 /* | |
575 * Creates a set of audio filters to convert from one format to another. | |
576 * Returns -1 if the format conversion is not supported, or 1 if the | |
577 * audio filter is set up. | |
578 */ | |
579 | |
580 int Sound_BuildAudioCVT(Sound_AudioCVT *cvt, | |
581 Uint16 src_format, Uint8 src_channels, Uint32 src_rate, | |
382
ce998ee6194f
Sync'd with latest altcvt.
Ryan C. Gordon <icculus@icculus.org>
parents:
342
diff
changeset
|
582 Uint16 dst_format, Uint8 dst_channels, Uint32 dst_rate, |
ce998ee6194f
Sync'd with latest altcvt.
Ryan C. Gordon <icculus@icculus.org>
parents:
342
diff
changeset
|
583 Uint32 dst_size) |
141 | 584 { |
585 /* Start off with no conversion necessary */ | |
586 cvt->needed = 0; | |
587 cvt->filter_index = 0; | |
588 cvt->filters[0] = NULL; | |
589 cvt->len_mult = 1; | |
590 cvt->len_ratio = 1.0; | |
591 | |
592 /* First filter: Endian conversion from src to dst */ | |
593 if ((src_format & 0x1000) != (dst_format & 0x1000) && | |
594 ((src_format & 0xff) != 8)) | |
595 { | |
596 SNDDBG(("Adding filter: Sound_ConvertEndian\n")); | |
597 cvt->filters[cvt->filter_index++] = Sound_ConvertEndian; | |
598 } /* if */ | |
599 | |
600 /* Second filter: Sign conversion -- signed/unsigned */ | |
601 if ((src_format & 0x8000) != (dst_format & 0x8000)) | |
602 { | |
603 SNDDBG(("Adding filter: Sound_ConvertSign\n")); | |
604 cvt->filters[cvt->filter_index++] = Sound_ConvertSign; | |
605 } /* if */ | |
606 | |
607 /* Next filter: Convert 16 bit <--> 8 bit PCM. */ | |
608 if ((src_format & 0xFF) != (dst_format & 0xFF)) | |
609 { | |
610 switch (dst_format & 0x10FF) | |
611 { | |
612 case AUDIO_U8: | |
613 SNDDBG(("Adding filter: Sound_Convert8\n")); | |
614 cvt->filters[cvt->filter_index++] = Sound_Convert8; | |
615 cvt->len_ratio /= 2; | |
616 break; | |
617 | |
618 case AUDIO_U16LSB: | |
619 SNDDBG(("Adding filter: Sound_Convert16LSB\n")); | |
620 cvt->filters[cvt->filter_index++] = Sound_Convert16LSB; | |
621 cvt->len_mult *= 2; | |
622 cvt->len_ratio *= 2; | |
623 break; | |
624 | |
625 case AUDIO_U16MSB: | |
626 SNDDBG(("Adding filter: Sound_Convert16MSB\n")); | |
627 cvt->filters[cvt->filter_index++] = Sound_Convert16MSB; | |
628 cvt->len_mult *= 2; | |
629 cvt->len_ratio *= 2; | |
630 break; | |
631 } /* switch */ | |
632 } /* if */ | |
633 | |
634 /* Next filter: Mono/Stereo conversion */ | |
635 if (src_channels != dst_channels) | |
636 { | |
637 while ((src_channels * 2) <= dst_channels) | |
638 { | |
639 SNDDBG(("Adding filter: Sound_ConvertStereo\n")); | |
640 cvt->filters[cvt->filter_index++] = Sound_ConvertStereo; | |
641 cvt->len_mult *= 2; | |
642 src_channels *= 2; | |
643 cvt->len_ratio *= 2; | |
644 } /* while */ | |
645 | |
646 /* This assumes that 4 channel audio is in the format: | |
647 * Left {front/back} + Right {front/back} | |
648 * so converting to L/R stereo works properly. | |
649 */ | |
650 while (((src_channels % 2) == 0) && | |
651 ((src_channels / 2) >= dst_channels)) | |
652 { | |
653 SNDDBG(("Adding filter: Sound_ConvertMono\n")); | |
654 cvt->filters[cvt->filter_index++] = Sound_ConvertMono; | |
655 src_channels /= 2; | |
656 cvt->len_ratio /= 2; | |
657 } /* while */ | |
658 | |
659 if ( src_channels != dst_channels ) { | |
660 /* Uh oh.. */; | |
661 } /* if */ | |
662 } /* if */ | |
663 | |
664 /* Do rate conversion */ | |
665 cvt->rate_incr = 0.0; | |
666 if ((src_rate / 100) != (dst_rate / 100)) | |
667 { | |
668 Uint32 hi_rate, lo_rate; | |
669 int len_mult; | |
670 double len_ratio; | |
671 void (*rate_cvt)(Sound_AudioCVT *cvt, Uint16 *format); | |
672 | |
673 if (src_rate > dst_rate) | |
674 { | |
675 hi_rate = src_rate; | |
676 lo_rate = dst_rate; | |
677 SNDDBG(("Adding filter: Sound_RateDIV2\n")); | |
678 rate_cvt = Sound_RateDIV2; | |
679 len_mult = 1; | |
680 len_ratio = 0.5; | |
681 } /* if */ | |
682 else | |
683 { | |
684 hi_rate = dst_rate; | |
685 lo_rate = src_rate; | |
686 SNDDBG(("Adding filter: Sound_RateMUL2\n")); | |
687 rate_cvt = Sound_RateMUL2; | |
688 len_mult = 2; | |
689 len_ratio = 2.0; | |
690 } /* else */ | |
691 | |
692 /* If hi_rate = lo_rate*2^x then conversion is easy */ | |
693 while (((lo_rate * 2) / 100) <= (hi_rate / 100)) | |
694 { | |
695 cvt->filters[cvt->filter_index++] = rate_cvt; | |
696 cvt->len_mult *= len_mult; | |
697 lo_rate *= 2; | |
698 cvt->len_ratio *= len_ratio; | |
699 } /* while */ | |
700 | |
701 /* We may need a slow conversion here to finish up */ | |
702 if ((lo_rate / 100) != (hi_rate / 100)) | |
703 { | |
704 if (src_rate < dst_rate) | |
705 { | |
706 cvt->rate_incr = (double) lo_rate / hi_rate; | |
707 cvt->len_mult *= 2; | |
708 cvt->len_ratio /= cvt->rate_incr; | |
709 } /* if */ | |
710 else | |
711 { | |
712 cvt->rate_incr = (double) hi_rate / lo_rate; | |
713 cvt->len_ratio *= cvt->rate_incr; | |
714 } /* else */ | |
715 SNDDBG(("Adding filter: Sound_RateSLOW\n")); | |
716 cvt->filters[cvt->filter_index++] = Sound_RateSLOW; | |
717 } /* if */ | |
718 } /* if */ | |
719 | |
720 /* Set up the filter information */ | |
721 if (cvt->filter_index != 0) | |
722 { | |
723 cvt->needed = 1; | |
724 cvt->src_format = src_format; | |
725 cvt->dst_format = dst_format; | |
726 cvt->len = 0; | |
727 cvt->buf = NULL; | |
728 cvt->filters[cvt->filter_index] = NULL; | |
729 } /* if */ | |
730 | |
731 return(cvt->needed); | |
732 } /* Sound_BuildAudioCVT */ | |
465
636796aed4e2
Build/packaging fixes.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
733 |
636796aed4e2
Build/packaging fixes.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
734 /* end of audio_convert.c ... */ |
636796aed4e2
Build/packaging fixes.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
735 |