comparison alt_audio_convert.c @ 365:f61eadea1f44

More revisions from Frank.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 18 Jun 2002 21:49:44 +0000
parents c984aa6990f7
children eda146d666d1
comparison
equal deleted inserted replaced
364:4bcbc442d145 365:f61eadea1f44
1 /* 1 /*
2 Extended Audio Converter for SDL (Simple DirectMedia Layer) 2 * Extended Audio Converter for SDL (Simple DirectMedia Layer)
3 Copyright (C) 2002 Frank Ranostaj 3 * Copyright (C) 2002 Frank Ranostaj
4 Institute of Applied Physik 4 * Institute of Applied Physik
5 Johann Wolfgang Goethe-Universität 5 * Johann Wolfgang Goethe-Universität
6 Frankfurt am Main, Germany 6 * Frankfurt am Main, Germany
7 7 *
8 This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version. 11 * version 2 of the License, or (at your option) any later version.
12 12 *
13 This library is distributed in the hope that it will be useful, 13 * This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details. 16 * Library General Public License for more details.
17 17 *
18 You should have received a copy of the GNU Library General Public 18 * You should have received a copy of the GNU Library General Public
19 License along with this library; if not, write to the Free 19 * License along with this library; if not, write to the Free
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 21 *
22 Frank Ranostaj 22 * Frank Ranostaj
23 ranostaj@stud.uni-frankfurt.de 23 * ranostaj@stud.uni-frankfurt.de
24 24 *
25 (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) 25 * (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.)
26 26 */
27 */ 27
28 #include "alt_audio_convert.h" 28 #include "alt_audio_convert.h"
29 #include <stdlib.h> 29 #include <stdlib.h>
30 #include <math.h> 30 #include <math.h>
31 31
32 /* just to make sure this is defined... */
33
34 #ifndef min
35 #define min(x, y) ( ((x) < (y)) ? (x) : (y) )
36 #endif
37
38 #ifndef max
39 #define max(x, y) ( ((x) > (y)) ? (x) : (y) )
40 #endif
41
42
32 /* some macros for "parsing" format */ 43 /* some macros for "parsing" format */
33 44
34 #define IS_8BIT(x) ((x).format & 0x0008) 45 #define IS_8BIT(x) ((x).format & 0x0008)
35 #define IS_16BIT(x) ((x).format & 0x0010) 46 #define IS_16BIT(x) ((x).format & 0x0010)
36 #define IS_FLOAT(x) ((x).format & 0x0020) /* !!! FIXME: is this ok? */ 47 #define IS_FLOAT(x) ((x).format & 0x0020)
37 #define IS_SIGNED(x) ((x).format & 0x8000) 48 #define IS_SIGNED(x) ((x).format & 0x8000)
38 #define IS_SYSENDIAN(x) ((AUDIO_U16SYS ^ (x).format) & 0x1000) 49 #define IS_SYSENDIAN(x) ((~AUDIO_U16SYS ^ (x).format) & 0x1000)
39 50
40 51
41 /*-------------------------------------------------------------------------*/ 52 /*-------------------------------------------------------------------------*/
42 /* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation */ 53 /* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation */
43 static const int filter[_fsize/2] = { 54 static const int filter[_fsize / 2] =
55 {
44 0, 20798, 0, -6764, 0, 3863, 0, -2560, 56 0, 20798, 0, -6764, 0, 3863, 0, -2560,
45 0, 1800, 0, -1295, 0, 936, 0, -671, 57 0, 1800, 0, -1295, 0, 936, 0, -671,
46 0, 474, 0, -326, 0, 217, 0, -138, 58 0, 474, 0, -326, 0, 217, 0, -138,
47 0, 83, 0, -46, 0, 23, 0, -9 }; 59 0, 83, 0, -46, 0, 23, 0, -9
60 };
61
62
63 /*-------------------------------------------------------------------------*/
64 /* the purpose of the RateConverterBuffer is to provide a continous storage
65 for head and tail of the (sample)-buffer. This allows a simple and
66 perfomant implemantation of the sample rate converters. Depending of the
67 operation mode, two layouts for the RateConverterBuffer.inbuffer are
68 possible:
69
70 in the Loop Mode:
71 ... T-4 T-3 T-2 T-1 H+0 H+1 H+2 H+3 H+4 ...
72 |
73 linp, finp
74
75 in the Single Mode (non Loop):
76 ... T-4 T-3 T-2 T-1 0 0 0 ... 0 0 0 H+0 H+1 H+2 H+3 H+4 ...
77 | |
78 linp finp
79
80 The RateConverterBuffer allows an accurate attack and decay of the
81 filters in the rate Converters.
82
83 The pointer finp are actually shifted against the depicted position so
84 that on the first invocation of the rate converter the input of the
85 filter is nearly complete in the zero region, only one input value is
86 used. After the calculation of the first output value, the pointer are
87 incremented or decremented depending on down or up conversion and the
88 first two input value are taken into account. This procedure repeats
89 until the filter has processed all zeroes. The distance of the pointer
90 movement is stored in flength.
91
92 Further a pointer cinp to the sample buffer itself is stored. The pointer
93 to the sample buffer is shifted too, so that on the first use of this
94 pointer the filter is complete in the sample buffer. The pointer moves
95 over the sample buffer until it reaches the other end. The distance of
96 the movement is stored in clength.
97
98 Finally the decay of the filter is done by linp, llength like finp,
99 flength, but in reverse order.
100
101 buffer denotes the start or the end of the output buffer, depending
102 on direction of the rate conversion.
103
104 All pointer and length referring the buffer as Sint16. All length
105 are refering to the input buffer */
106
107 typedef struct
108 {
109 Sint16 inbuffer[6*_fsize];
110 Sint16 *finp, *cinp, *linp;
111 Sint16 *buffer;
112 int flength, clength, llength;
113 } RateConverterBuffer;
114
48 115
49 /* Mono (1 channel ) */ 116 /* Mono (1 channel ) */
50 #define Suffix(x) x##1 117 #define Suffix(x) x##1
51 #include "filter_templates.h" 118 #include "filter_templates.h"
52 #undef Suffix 119 #undef Suffix
54 /* Stereo (2 channel ) */ 121 /* Stereo (2 channel ) */
55 #define Suffix(x) x##2 122 #define Suffix(x) x##2
56 #include "filter_templates.h" 123 #include "filter_templates.h"
57 #undef Suffix 124 #undef Suffix
58 125
126
59 /*-------------------------------------------------------------------------*/ 127 /*-------------------------------------------------------------------------*/
60 static int ConvertAudio( Sound_AudioCVT *Data, 128 static int ConvertAudio( Sound_AudioCVT *Data,
61 Uint8* buffer, int length, int mode ) 129 Uint8* buffer, int length, int mode )
62 { 130 {
63 AdapterC Temp; 131 AdapterC Temp;
64 int i; 132 int i;
65 133
66 /* Make sure there's a converter */ 134 /* Make sure there's a converter */
291 buffer[i]= 38084 * buffer[i] >> 16; 359 buffer[i]= 38084 * buffer[i] >> 16;
292 return length; 360 return length;
293 } 361 }
294 362
295 /*-------------------------------------------------------------------------*/ 363 /*-------------------------------------------------------------------------*/
364 static void initRateConverterBuffer( RateConverterBuffer *rcb,
365 AdapterC* Data, int length, int rel_size )
366 {
367 int size, slength;
368 int den, num;
369 int i;
370
371 den = Data->filter->denominator;
372 num = Data->filter->numerator;
373 size = _fsize * rel_size;
374 length >>= 1;
375 slength = rel_size > 0 ? length : -length;
376
377 rcb->buffer = (Sint16*)( Data->buffer );
378
379 if( Data->mode & SDL_AI_Loop )
380 {
381 // !!!FIXME: modulo length, take scale into account
382 for( i = 0; i < size; i++ )
383 {
384 rcb->inbuffer[i] = rcb->buffer[length-size+i];
385 rcb->inbuffer[i+size] = rcb->buffer[i];
386 }
387 rcb->finp = rcb->linp = rcb->inbuffer + size;
388 if( size < 0 )
389 rcb->buffer += num * ( length + 2 * size ) / den;
390 }
391 else
392 {
393 for( i = 0; i < size; i++ )
394 {
395 int j;
396 j = length-size+i;
397 rcb->inbuffer[i] = j < 0 ? 0 : rcb->buffer[j];
398 rcb->inbuffer[i+size] = 0;
399 rcb->inbuffer[i+2*size] = i < length ? rcb->buffer[i] : 0;
400 }
401 // !!!FIXME: take lenght < size into account
402 rcb->finp = rcb->inbuffer + abs( 3*size/2 ) + size/2;
403 rcb->linp = rcb->inbuffer + abs( 3*size/2 ) - size/2;
404 rcb->flength = rcb->llength = 2*size;
405 rcb->clength = slength - 2*size;
406
407 if( size < 0 )
408 rcb->buffer += num * ( length + 2 * size ) / den;
409 }
410 }
411
412 static void nextRateConverterBuffer( RateConverterBuffer *rcb )
413 {
414 rcb->buffer++;
415 rcb->finp++;
416 rcb->cinp++;
417 rcb->linp++;
418 }
419
420 typedef Sint16* (*RateConverter)( Sint16*, Sint16*, int, VarFilter*, int*);
421 static int doRateConversion( RateConverterBuffer* rcb,
422 RateConverter ffp, VarFilter* filter )
423 {
424 int pos = 0;
425 Sint16 *outp;
426 outp = rcb->buffer;
427
428 outp = (*ffp)( outp, rcb->finp, rcb->flength, filter, &pos );
429 outp = (*ffp)( outp, rcb->cinp, rcb->clength, filter, &pos );
430 outp = (*ffp)( outp, rcb->linp, rcb->llength, filter, &pos );
431 return 2 * abs( rcb->buffer - outp );
432 }
433
434
435 /*-------------------------------------------------------------------------*/
436 static int doubleRateMono( AdapterC Data, int length )
437 {
438 RateConverterBuffer rcb;
439 initRateConverterBuffer( &rcb, &Data, length, 1 );
440 return doRateConversion( &rcb, doubleRate1, NULL );
441 }
442
296 static int doubleRateStereo( AdapterC Data, int length ) 443 static int doubleRateStereo( AdapterC Data, int length )
297 { 444 {
298 length >>= 2; 445 RateConverterBuffer rcb;
299 _doubleRate2( (Sint16*)Data.buffer, Data.mode, length ); 446 initRateConverterBuffer( &rcb, &Data, length, 2 );
300 return 4*_doubleRate2( (Sint16*)Data.buffer+1, Data.mode, length ); 447 doRateConversion( &rcb, doubleRate2, NULL );
301 } 448 nextRateConverterBuffer( &rcb );
302 449 return 2 + doRateConversion( &rcb, doubleRate2, NULL );
303 static int doubleRateMono( AdapterC Data, int length ) 450 }
304 { 451
305 return 2*_doubleRate1( (Sint16*)Data.buffer, Data.mode, length>>1 ); 452 /*-------------------------------------------------------------------------*/
306 } 453 static int halfRateMono( AdapterC Data, int length )
307 454 {
308 /*-------------------------------------------------------------------------*/ 455 RateConverterBuffer rcb;
456 initRateConverterBuffer( &rcb, &Data, length, -1 );
457 return doRateConversion( &rcb, halfRate1, NULL );
458 }
459
309 static int halfRateStereo( AdapterC Data, int length ) 460 static int halfRateStereo( AdapterC Data, int length )
310 { 461 {
311 length >>= 2; 462 RateConverterBuffer rcb;
312 _halfRate2( (Sint16*)Data.buffer, Data.mode, length ); 463 initRateConverterBuffer( &rcb, &Data, length, -2 );
313 return 4*_halfRate2( (Sint16*)Data.buffer+1, Data.mode, length ); 464 doRateConversion( &rcb, halfRate2, NULL );
314 } 465 nextRateConverterBuffer( &rcb );
315 466 return 2 + doRateConversion( &rcb, halfRate2, NULL );
316 static int halfRateMono( AdapterC Data, int length ) 467 }
317 { 468
318 return 2*_halfRate2( (Sint16*)Data.buffer, Data.mode, length>>1 ); 469 /*-------------------------------------------------------------------------*/
319 } 470 static int increaseRateMono( AdapterC Data, int length )
320 471 {
321 /*-------------------------------------------------------------------------*/ 472 RateConverterBuffer rcb;
322 static int varRateUpStereo( AdapterC Data, int length ) 473 initRateConverterBuffer( &rcb, &Data, length, 2 );
323 { 474 return doRateConversion( &rcb, increaseRate1, Data.filter );
324 length >>= 2; 475 }
325 _varRateUp2( (Sint16*)Data.buffer, Data.mode, Data.filter, length ); 476
326 return 4 * _varRateUp2( (Sint16*)Data.buffer+1, 477 static int increaseRateStereo( AdapterC Data, int length )
327 Data.mode, Data.filter, length ); 478 {
328 } 479 RateConverterBuffer rcb;
329 480 initRateConverterBuffer( &rcb, &Data, length, 4 );
330 static int varRateUpMono( AdapterC Data, int length ) 481 doRateConversion( &rcb, increaseRate2, Data.filter );
331 { 482 nextRateConverterBuffer( &rcb );
332 return 2 * _varRateUp1( (Sint16*)Data.buffer, 483 return 2 + doRateConversion( &rcb, increaseRate2, Data.filter );
333 Data.mode, Data.filter, length>>1 ); 484 }
334 } 485
335 486 /*-------------------------------------------------------------------------*/
336 static int varRateDownStereo( AdapterC Data, int length ) 487 static int decreaseRateMono( AdapterC Data, int length )
337 { 488 {
338 length >>= 2; 489 RateConverterBuffer rcb;
339 _varRateDown2( (Sint16*)Data.buffer, Data.mode, Data.filter, length ); 490 initRateConverterBuffer( &rcb, &Data, length, -2 );
340 return 2 * _varRateDown2( (Sint16*)Data.buffer+1, 491 return doRateConversion( &rcb, decreaseRate1, Data.filter );
341 Data.mode, Data.filter, length ); 492 }
342 } 493
343 494 static int decreaseRateStereo( AdapterC Data, int length )
344 static int varRateDownMono( AdapterC Data, int length ) 495 {
345 { 496 RateConverterBuffer rcb;
346 return _varRateDown1( (Sint16*)Data.buffer, 497 initRateConverterBuffer( &rcb, &Data, length, -4 );
347 Data.mode, Data.filter, length>>1 ); 498 doRateConversion( &rcb, decreaseRate2, Data.filter );
348 } 499 nextRateConverterBuffer( &rcb );
500 return doRateConversion( &rcb, decreaseRate2, Data.filter );
501 }
502
349 503
350 /*-------------------------------------------------------------------------*/ 504 /*-------------------------------------------------------------------------*/
351 typedef struct{ 505 typedef struct{
352 Sint16 denominator; 506 Sint16 denominator;
353 Sint16 numerator; 507 Sint16 numerator;
354 } Fraction; 508 } Fraction;
355 509
510 /* gives a maximal error of 3% and typical less than 0.2% */
356 static Fraction findFraction( float Value ) 511 static Fraction findFraction( float Value )
357 { 512 {
358 /* gives a maximal error of 3% and typical less than 0.2% */ 513 const Sint8 frac[95]={
359 const Uint8 frac[96]={ 514 2, -1, /* /1 */
360 1, 2, -1, /* /1 */
361 1, 3, -1, /* /2 */ 515 1, 3, -1, /* /2 */
362 2, 4, 5, -1, /* /3 */ 516 2, 4, 5, -1, /* /3 */
363 3, 5, 7, -1, /* /4 */ 517 3, 5, 7, -1, /* /4 */
364 3, 4, 6, 7, 8, 9, -1, /* /5 */ 518 3, 4, 6, 7, 8, 9, -1, /* /5 */
365 5, 7, 11, -1, /* /6 */ 519 5, 7, 11, -1, /* /6 */
374 8, 11, 13, 14, 16, -1, /* /15 */ 528 8, 11, 13, 14, 16, -1, /* /15 */
375 9, 11, 13, 15 }; /* /16 */ 529 9, 11, 13, 15 }; /* /16 */
376 530
377 531
378 Fraction Result = {0,0}; 532 Fraction Result = {0,0};
379 int n,num,den=1; 533 int n,num=1,den=1;
380 534
381 float RelErr, BestErr = 0; 535 float RelErr, BestErr = 0;
382 if( Value < 31/64. || Value > 64/31. ) return Result; 536 if( Value < 31/64. || Value > 64/31. ) return Result;
383 537
384 for( n = 0; n < sizeof(frac); num=frac[++n] ) 538 for( n = 0; n < sizeof(frac); num=frac[n++] )
385 { 539 {
386 if( num < 0 ) den++; 540 if( num < 0 ) den++;
387 RelErr = Value * num / den; 541 RelErr = Value * num / den;
388 RelErr = min( RelErr, 1/RelErr ); 542 RelErr = min( RelErr, 1/RelErr );
389 if( RelErr > BestErr ) 543 if( RelErr > BestErr )
401 { 555 {
402 if( x > -1e-24 && x < 1e-24 ) return 1.; 556 if( x > -1e-24 && x < 1e-24 ) return 1.;
403 else return sin(x)/x; 557 else return sin(x)/x;
404 } 558 }
405 559
406 static void calculateVarFilter( Sint16* dst, float Ratio, float phase, float scale ) 560 static void calculateVarFilter( Sint16* dst,
561 float Ratio, float phase, float scale )
407 { 562 {
408 const Uint16 KaiserWindow7[]= { 563 const Uint16 KaiserWindow7[]= {
409 22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404, 564 22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404,
410 17304, 18289, 19347, 20467, 21644, 22872, 24145, 25460, 565 17304, 18289, 19347, 20467, 21644, 22872, 24145, 25460,
411 26812, 28198, 29612, 31052, 32513, 33991, 35482, 36983, 566 26812, 28198, 29612, 31052, 32513, 33991, 35482, 36983,
438 static void setupVarFilter( VarFilter* filter, 593 static void setupVarFilter( VarFilter* filter,
439 float Ratio, VarFilterMode Direction ) 594 float Ratio, VarFilterMode Direction )
440 { 595 {
441 int i,n,d; 596 int i,n,d;
442 Fraction IRatio; 597 Fraction IRatio;
443 float phase; 598 float phase = 0.;
444 IRatio = findFraction( Ratio ); 599 IRatio = findFraction( Ratio );
445 Ratio = min( Ratio, 1/Ratio ); 600 Ratio = min( Ratio, 1/Ratio );
446 601
447 n = IRatio.numerator; 602 n = IRatio.numerator;
448 d = IRatio.denominator; 603 d = IRatio.denominator;
449 filter->pos_mod = d; 604 filter->denominator = d;
605 filter->numerator = n;
450 606
451 for( i = 0; i < d; i++ ) 607 for( i = 0; i < d; i++ )
452 { 608 {
453 if( phase >= n ) 609 if( phase >= n )
454 { 610 {
464 } 620 }
465 } 621 }
466 622
467 /*-------------------------------------------------------------------------*/ 623 /*-------------------------------------------------------------------------*/
468 static void createRateConverter( Sound_AudioCVT *Data, int* fip, 624 static void createRateConverter( Sound_AudioCVT *Data, int* fip,
469 int SrcRate, int DestRate, int Channel ) 625 int SrcRate, int DestRate, int Channel )
470 { 626 {
471 int filter_index = *fip; 627 int filter_index = *fip;
472 628
473 int VarPos = 0; 629 int VarPos = 0;
474 int Mono = 2 - Channel; 630 int Mono = 2 - Channel;
504 660
505 if( Ratio > 1. ) 661 if( Ratio > 1. )
506 { 662 {
507 setupVarFilter( &Data->filter, Ratio, Up ); 663 setupVarFilter( &Data->filter, Ratio, Up );
508 Data->adapter[VarPos] = 664 Data->adapter[VarPos] =
509 Mono ? varRateUpMono : varRateUpStereo; 665 Mono ? increaseRateMono : increaseRateStereo;
510 Data->len_mult *= 2; 666 Data->len_mult *= 2;
511 Data->add *= 2; 667 Data->add *= 2;
512 Data->add += _fsize; 668 Data->add += _fsize;
513 } 669 }
514 else 670 else
515 { 671 {
516 setupVarFilter( &Data->filter, Ratio, Down ); 672 setupVarFilter( &Data->filter, Ratio, Down );
517 Data->adapter[filter_index++] = 673 Data->adapter[filter_index++] =
518 Mono ? varRateDownMono : varRateDownStereo; 674 Mono ? decreaseRateMono : decreaseRateStereo;
519 } 675 }
520 *fip = filter_index; 676 *fip = filter_index;
521 } 677 }
522 678
523 /*-------------------------------------------------------------------------*/ 679 /*-------------------------------------------------------------------------*/
641 *fip = filter_index; 797 *fip = filter_index;
642 } 798 }
643 799
644 800
645 /*-------------------------------------------------------------------------*/ 801 /*-------------------------------------------------------------------------*/
646 DECLSPEC int BuildAudioCVT(Sound_AudioCVT *Data, 802 int BuildAudioCVT( Sound_AudioCVT *Data,
647 SDL_AudioSpec src, SDL_AudioSpec dst ) 803 SDL_AudioSpec src, SDL_AudioSpec dst )
648 { 804 {
649 SDL_AudioSpec intrm; 805 SDL_AudioSpec intrm;
650 int filter_index = 0; 806 int filter_index = 0;
651 807
652 if( Data == NULL ) return -1; 808 if( Data == NULL ) return -1;
731 AdapterDesc(convertStereoToMonoS8Bit), 887 AdapterDesc(convertStereoToMonoS8Bit),
732 AdapterDesc(convertStereoToMonoU8Bit), 888 AdapterDesc(convertStereoToMonoU8Bit),
733 AdapterDesc(convertMonoToStereo16Bit), 889 AdapterDesc(convertMonoToStereo16Bit),
734 AdapterDesc(convertMonoToStereo8Bit), 890 AdapterDesc(convertMonoToStereo8Bit),
735 AdapterDesc(minus5dB), 891 AdapterDesc(minus5dB),
892 AdapterDesc(doubleRateMono),
736 AdapterDesc(doubleRateStereo), 893 AdapterDesc(doubleRateStereo),
737 AdapterDesc(doubleRateMono), 894 AdapterDesc(halfRateMono),
738 AdapterDesc(halfRateStereo), 895 AdapterDesc(halfRateStereo),
739 AdapterDesc(halfRateMono), 896 AdapterDesc(increaseRateMono),
740 AdapterDesc(varRateUpStereo), 897 AdapterDesc(increaseRateStereo),
741 AdapterDesc(varRateUpMono), 898 AdapterDesc(decreaseRateMono),
742 AdapterDesc(varRateDownStereo), 899 AdapterDesc(decreaseRateStereo),
743 AdapterDesc(varRateDownMono),
744 { NULL, "----------NULL-----------" } 900 { NULL, "----------NULL-----------" }
745 }; 901 };
746 const int AdapterDescMax = sizeof(AdapterDescription) 902 const int AdapterDescMax = sizeof(AdapterDescription)
747 / sizeof(*AdapterDescription); 903 / sizeof(*AdapterDescription);
748 904
764 fprintf( stderr, " Error: NULL adapter missing\n" ); 920 fprintf( stderr, " Error: NULL adapter missing\n" );
765 } 921 }
766 922
767 923
768 int Sound_BuildAudioCVT(Sound_AudioCVT *Data, 924 int Sound_BuildAudioCVT(Sound_AudioCVT *Data,
769 Uint16 src_format, Uint8 src_channels, int src_rate, 925 Uint16 src_format, Uint8 src_channels, int src_rate,
770 Uint16 dst_format, Uint8 dst_channels, int dst_rate) 926 Uint16 dst_format, Uint8 dst_channels, int dst_rate)
771 { 927 {
772 SDL_AudioSpec src, dst; 928 SDL_AudioSpec src, dst;
773 int ret; 929 int ret;
774 930
775 fprintf (stderr, 931 fprintf (stderr,