Mercurial > SDL_sound_CoreAudio
comparison alt_audio_convert.c @ 420:5b8a07b5162e
Latest altcvt from Frank.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 26 Sep 2002 04:34:35 +0000 |
parents | b1e511c879d1 |
children | a65440b3a057 |
comparison
equal
deleted
inserted
replaced
419:25a8f66112fd | 420:5b8a07b5162e |
---|---|
123 #include "filter_templates.h" | 123 #include "filter_templates.h" |
124 #undef Suffix | 124 #undef Suffix |
125 | 125 |
126 | 126 |
127 /*-------------------------------------------------------------------------*/ | 127 /*-------------------------------------------------------------------------*/ |
128 static int ConvertAudio( Sound_AudioCVT *Data, | 128 int Sound_estimateBufferSize( Sound_AudioCVT *Data, int size ) |
129 Uint8* buffer, int length, int mode ) | 129 { |
130 size *= Data->len_mult; | |
131 size += Data->len_add; | |
132 return ( size + 3 ) & -4; /* force Size in multipels of 4 Byte */ | |
133 } | |
134 | |
135 /*-------------------------------------------------------------------------*/ | |
136 int Sound_AltConvertAudio( Sound_AudioCVT *Data, | |
137 Uint8* buffer, int length, int mode ) | |
130 { | 138 { |
131 AdapterC Temp; | 139 AdapterC Temp; |
132 int i; | 140 int i; |
133 | 141 |
134 /* Make sure there's a converter */ | 142 /* Make sure there's a converter */ |
135 if( Data == NULL ) { | 143 if( Data == NULL ) { |
136 SDL_SetError("altcvt: No converter given"); | 144 SDL_SetError("No converter given"); |
137 return(-1); | 145 return(-1); |
138 } | 146 } |
139 | 147 |
140 /* Make sure there's data to convert */ | 148 /* Make sure there's data to convert */ |
141 if( buffer == NULL ) { | 149 if( buffer == NULL ) { |
142 SDL_SetError("altcvt: No buffer allocated for conversion"); | 150 SDL_SetError("No buffer allocated for conversion"); |
143 return(-1); | 151 return(-1); |
144 } | 152 } |
145 | 153 |
146 if( length < 0 ) { | 154 if( length < 0 ) { |
147 SDL_SetError("altcvt: Length < 0"); | 155 SDL_SetError("Lenght < 0"); |
148 return(-1); | 156 return(-1); |
149 } | 157 } |
150 | 158 |
151 /* Set up the conversion and go! */ | 159 /* Set up the conversion and go! */ |
152 Temp.buffer = buffer; | 160 Temp.buffer = buffer; |
161 | 169 |
162 int Sound_ConvertAudio( Sound_AudioCVT *Data ) | 170 int Sound_ConvertAudio( Sound_AudioCVT *Data ) |
163 { | 171 { |
164 int length; | 172 int length; |
165 /* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */ | 173 /* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */ |
166 length = ConvertAudio( Data, Data->buf, Data->len, 0 ); | 174 length = Sound_AltConvertAudio( Data, Data->buf, Data->len, 0 ); |
167 Data->len_cvt = length; | 175 Data->len_cvt = length; |
168 return length; | 176 return length; |
169 } | 177 } |
170 | 178 |
171 /*-------------------------------------------------------------------------*/ | 179 /*-------------------------------------------------------------------------*/ |
336 | 344 |
337 /*-------------------------------------------------------------------------*/ | 345 /*-------------------------------------------------------------------------*/ |
338 static int convertMonoToStereo16Bit( AdapterC Data, int length ) | 346 static int convertMonoToStereo16Bit( AdapterC Data, int length ) |
339 { | 347 { |
340 int i; | 348 int i; |
349 length >>=1; | |
341 Uint16* buffer = (Uint16*)Data.buffer - 1; | 350 Uint16* buffer = (Uint16*)Data.buffer - 1; |
342 Uint16* dst = (Uint16*)Data.buffer + length - 2; | 351 Uint16* dst = (Uint16*)Data.buffer + 2*length - 2; |
343 for( i = length>>1 + 1; --i; dst-=2 ) | 352 for( i = length + 1; --i; dst-=2 ) |
344 dst[0] = dst[1] = buffer[i]; | 353 dst[0] = dst[1] = buffer[i]; |
345 return 2*length; | 354 return 4*length; |
346 } | 355 } |
347 | 356 |
348 static int convertMonoToStereo8Bit( AdapterC Data, int length ) | 357 static int convertMonoToStereo8Bit( AdapterC Data, int length ) |
349 { | 358 { |
350 int i; | 359 int i; |
351 Uint8* buffer = Data.buffer - 1; | 360 Uint8* buffer = Data.buffer - 1; |
352 Uint8* dst = Data.buffer + length - 2; | 361 Uint8* dst = Data.buffer + 2*length - 2; |
353 for( i = length + 1; --i; dst-=2 ) | 362 for( i = length + 1; --i; dst-=2 ) |
354 dst[0] = dst[1] = buffer[i]; | 363 dst[0] = dst[1] = buffer[i]; |
355 return 2*length; | 364 return 2*length; |
356 } | 365 } |
357 | 366 |
366 } | 375 } |
367 | 376 |
368 /*-------------------------------------------------------------------------*/ | 377 /*-------------------------------------------------------------------------*/ |
369 const Fraction Half = {1, 2}; | 378 const Fraction Half = {1, 2}; |
370 const Fraction Double = {2, 1}; | 379 const Fraction Double = {2, 1}; |
380 const Fraction One = {1, 1}; | |
381 | |
371 | 382 |
372 static void initStraigthBuffer( RateConverterBuffer *rcb, | 383 static void initStraigthBuffer( RateConverterBuffer *rcb, |
373 int length, Fraction r, int dir ) | 384 int length, Fraction r ) |
374 { | 385 { |
375 int i, size, minsize; | 386 int i, size, minsize; |
376 size = 8 * _fsize; | 387 size = 8 * _fsize; |
377 minsize = min( size, length ); | 388 minsize = min( size, length ); |
378 | 389 |
391 | 402 |
392 length = max( length, size ); | 403 length = max( length, size ); |
393 rcb->flength = rcb->llength = size; | 404 rcb->flength = rcb->llength = size; |
394 rcb->clength = length - size; | 405 rcb->clength = length - size; |
395 | 406 |
396 if( dir ) | 407 if( r.numerator < r.denominator ) |
397 { | 408 { |
398 rcb->finp = rcb->inbuffer + 5 * size/2; | 409 rcb->finp = rcb->inbuffer + 5*size/2; |
399 rcb->cinp = rcb->buffer + length - size/2; | 410 rcb->cinp = rcb->buffer + length - size/2; |
400 rcb->linp = rcb->inbuffer + 3*size/2; | 411 rcb->linp = rcb->inbuffer + 3*size/2; |
401 rcb->buffer += r.denominator * ( length + size ) | 412 rcb->buffer += ( 1 + r.denominator * ( length + size ) |
402 / r.numerator; | 413 / r.numerator ) & -2; |
403 } | 414 } |
404 else | 415 else |
405 { | 416 { |
406 rcb->finp = rcb->inbuffer + size/2; | 417 rcb->finp = rcb->inbuffer + size/2; |
407 rcb->cinp = rcb->buffer + size/2; | 418 rcb->cinp = rcb->buffer + size/2; |
408 rcb->linp = rcb->inbuffer + 3*size/2; | 419 rcb->linp = rcb->inbuffer + 3*size/2; |
409 } | 420 } |
410 } | 421 } |
411 | 422 |
412 static void initLoopBuffer( RateConverterBuffer *rcb, | 423 static void initLoopBuffer( RateConverterBuffer *rcb, |
413 int length, Fraction r, int dir ) | 424 int length, Fraction r ) |
414 { | 425 { |
415 /* !!!FIXME: modulo length, take scale into account, | 426 /* !!!FIXME: modulo length, take scale into account, |
416 check against the Straight part -frank */ | 427 check against the Straight part -frank */ |
417 int i, size; | 428 int i, size; |
418 size = 8 * _fsize; | 429 size = 8 * _fsize; |
428 } | 439 } |
429 | 440 |
430 static void initRateConverterBuffer( RateConverterBuffer *rcb, | 441 static void initRateConverterBuffer( RateConverterBuffer *rcb, |
431 AdapterC* Data, int length, Fraction ratio ) | 442 AdapterC* Data, int length, Fraction ratio ) |
432 { | 443 { |
433 int dir; | |
434 dir = ratio.numerator < ratio.denominator ? 1 : 0; | |
435 length >>= 1; | 444 length >>= 1; |
436 rcb->buffer = (Sint16*)( Data->buffer ); | 445 rcb->buffer = (Sint16*)( Data->buffer ); |
437 rcb->filter = Data->filter; | 446 rcb->filter = Data->filter; |
438 | 447 |
439 if( Data->mode & SDL_SOUND_Loop ) | 448 if( Data->mode & SDL_SOUND_Loop ) |
440 initLoopBuffer( rcb, length, ratio, dir ); | 449 initLoopBuffer( rcb, length, ratio ); |
441 else | 450 else |
442 initStraigthBuffer( rcb, length, ratio, dir ); | 451 initStraigthBuffer( rcb, length, ratio ); |
452 | |
453 fprintf( stderr, " finp: %8x length: %8x\n", rcb->finp, rcb->flength ); | |
454 fprintf( stderr, " cinp: %8x length: %8x\n", rcb->cinp, rcb->clength ); | |
455 fprintf( stderr, " linp: %8x length: %8x\n", rcb->linp, rcb->llength ); | |
443 } | 456 } |
444 | 457 |
445 static void nextRateConverterBuffer( RateConverterBuffer *rcb ) | 458 static void nextRateConverterBuffer( RateConverterBuffer *rcb ) |
446 { | 459 { |
447 rcb->buffer++; | 460 rcb->buffer++; |
451 } | 464 } |
452 | 465 |
453 typedef Sint16* (*RateConverter)( Sint16*, Sint16*, int, | 466 typedef Sint16* (*RateConverter)( Sint16*, Sint16*, int, |
454 VarFilter*, RateAux* ); | 467 VarFilter*, RateAux* ); |
455 | 468 |
456 static int doRateConversion( RateConverterBuffer* rcb, RateConverter ffp ) | 469 static Sint16* doRateConversion( RateConverterBuffer* rcb, RateConverter rc ) |
457 { | 470 { |
458 RateAux aux = {0,0}; | 471 RateAux aux = {0,0}; |
459 Sint16 *outp = rcb->buffer; | 472 Sint16 *outp = rcb->buffer; |
460 VarFilter* filter = rcb->filter; | 473 VarFilter* filter = rcb->filter; |
461 | 474 |
462 outp = (*ffp)( outp, rcb->finp, rcb->flength, filter, &aux ); | 475 outp = (*rc)( outp, rcb->finp, rcb->flength, filter, &aux ); |
463 outp = (*ffp)( outp, rcb->cinp, rcb->clength, filter, &aux ); | 476 fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry ); |
464 outp = (*ffp)( outp, rcb->linp, rcb->llength, filter, &aux ); | 477 outp = (*rc)( outp, rcb->cinp, rcb->clength, filter, &aux ); |
465 return 2 * abs( rcb->buffer - outp ); | 478 fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry ); |
466 } | 479 outp = (*rc)( outp, rcb->linp, rcb->llength, filter, &aux ); |
467 | 480 fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry ); |
481 return outp; | |
482 } | |
483 | |
484 | |
485 /*-------------------------------------------------------------------------*/ | |
486 static void clearSint16Buffer( Sint8* buffer, Sint16*r ) | |
487 { | |
488 while( r >= (Sint16*)buffer ) *r-- = 0; | |
489 } | |
468 | 490 |
469 /*-------------------------------------------------------------------------*/ | 491 /*-------------------------------------------------------------------------*/ |
470 static int doubleRateMono( AdapterC Data, int length ) | 492 static int doubleRateMono( AdapterC Data, int length ) |
471 { | 493 { |
494 Sint16* r; | |
495 RateConverterBuffer rcb; | |
496 initRateConverterBuffer( &rcb, &Data, length, Half ); | |
497 r = 1 + doRateConversion( &rcb, doubleRate1 ); | |
498 clearSint16Buffer( Data.buffer, r ); | |
499 return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 2 ); | |
500 } | |
501 | |
502 static int doubleRateStereo( AdapterC Data, int length ) | |
503 { | |
504 Sint16* r; | |
505 fprintf( stderr, "\n Buffer: %8x length: %8x\n", Data.buffer, length ); | |
506 RateConverterBuffer rcb; | |
507 initRateConverterBuffer( &rcb, &Data, length, Half ); | |
508 doRateConversion( &rcb, doubleRate2 ); | |
509 nextRateConverterBuffer( &rcb ); | |
510 r = 2 + doRateConversion( &rcb, doubleRate2 ); | |
511 clearSint16Buffer( Data.buffer, r ); | |
512 return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 3 ); | |
513 } | |
514 | |
515 /*-------------------------------------------------------------------------*/ | |
516 static int halfRateMono( AdapterC Data, int length ) | |
517 { | |
518 Sint16* r; | |
472 RateConverterBuffer rcb; | 519 RateConverterBuffer rcb; |
473 initRateConverterBuffer( &rcb, &Data, length, Double ); | 520 initRateConverterBuffer( &rcb, &Data, length, Double ); |
474 return doRateConversion( &rcb, doubleRate1 ); | 521 r = doRateConversion( &rcb, halfRate1 ); |
475 } | 522 return 2 * ( r - (Sint16*)Data.buffer ); |
476 | 523 } |
477 static int doubleRateStereo( AdapterC Data, int length ) | 524 |
478 { | 525 static int halfRateStereo( AdapterC Data, int length ) |
526 { | |
527 Sint16* r; | |
479 RateConverterBuffer rcb; | 528 RateConverterBuffer rcb; |
480 initRateConverterBuffer( &rcb, &Data, length, Double ); | 529 initRateConverterBuffer( &rcb, &Data, length, Double ); |
481 doRateConversion( &rcb, doubleRate2 ); | |
482 nextRateConverterBuffer( &rcb ); | |
483 return 2 + doRateConversion( &rcb, doubleRate2 ); | |
484 } | |
485 | |
486 /*-------------------------------------------------------------------------*/ | |
487 static int halfRateMono( AdapterC Data, int length ) | |
488 { | |
489 RateConverterBuffer rcb; | |
490 initRateConverterBuffer( &rcb, &Data, length, Half ); | |
491 return doRateConversion( &rcb, halfRate1 ); | |
492 } | |
493 | |
494 static int halfRateStereo( AdapterC Data, int length ) | |
495 { | |
496 RateConverterBuffer rcb; | |
497 initRateConverterBuffer( &rcb, &Data, length, Half ); | |
498 doRateConversion( &rcb, halfRate2 ); | 530 doRateConversion( &rcb, halfRate2 ); |
499 nextRateConverterBuffer( &rcb ); | 531 nextRateConverterBuffer( &rcb ); |
500 return 2 + doRateConversion( &rcb, halfRate2 ); | 532 r = doRateConversion( &rcb, halfRate2 ); |
533 return 2 * ( r - (Sint16*)Data.buffer ); | |
501 } | 534 } |
502 | 535 |
503 /*-------------------------------------------------------------------------*/ | 536 /*-------------------------------------------------------------------------*/ |
504 static int increaseRateMono( AdapterC Data, int length ) | 537 static int increaseRateMono( AdapterC Data, int length ) |
505 { | 538 { |
539 Sint16* r; | |
506 RateConverterBuffer rcb; | 540 RateConverterBuffer rcb; |
507 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); | 541 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); |
508 return doRateConversion( &rcb, increaseRate1 ); | 542 r = doRateConversion( &rcb, increaseRate1 ); |
543 clearSint16Buffer( Data.buffer, r ); | |
544 return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 1 ); | |
509 } | 545 } |
510 | 546 |
511 static int increaseRateStereo( AdapterC Data, int length ) | 547 static int increaseRateStereo( AdapterC Data, int length ) |
512 { | 548 { |
549 Sint16* r; | |
550 fprintf( stderr, "\n Buffer: %8x length: %8x\n", Data.buffer, length ); | |
513 RateConverterBuffer rcb; | 551 RateConverterBuffer rcb; |
514 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); | 552 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); |
515 doRateConversion( &rcb, increaseRate2 ); | 553 doRateConversion( &rcb, increaseRate2 ); |
516 nextRateConverterBuffer( &rcb ); | 554 nextRateConverterBuffer( &rcb ); |
517 return 2 + doRateConversion( &rcb, increaseRate2 ); | 555 r = doRateConversion( &rcb, increaseRate2 ); |
556 clearSint16Buffer( Data.buffer, r ); | |
557 return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 1 ); | |
518 } | 558 } |
519 | 559 |
520 /*-------------------------------------------------------------------------*/ | 560 /*-------------------------------------------------------------------------*/ |
521 static int decreaseRateMono( AdapterC Data, int length ) | 561 static int decreaseRateMono( AdapterC Data, int length ) |
522 { | 562 { |
563 Sint16* r; | |
523 RateConverterBuffer rcb; | 564 RateConverterBuffer rcb; |
524 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); | 565 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); |
525 return doRateConversion( &rcb, decreaseRate1 ); | 566 r = doRateConversion( &rcb, decreaseRate1 ); |
567 return 2 * ( r - (Sint16*)Data.buffer ); | |
526 } | 568 } |
527 | 569 |
528 static int decreaseRateStereo( AdapterC Data, int length ) | 570 static int decreaseRateStereo( AdapterC Data, int length ) |
529 { | 571 { |
572 Sint16* r; | |
530 RateConverterBuffer rcb; | 573 RateConverterBuffer rcb; |
531 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); | 574 initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio ); |
532 doRateConversion( &rcb, decreaseRate2 ); | 575 doRateConversion( &rcb, decreaseRate2 ); |
533 nextRateConverterBuffer( &rcb ); | 576 nextRateConverterBuffer( &rcb ); |
534 return 2 + doRateConversion( &rcb, decreaseRate2 ); | 577 r = doRateConversion( &rcb, decreaseRate2 ); |
535 } | 578 return 2 * ( r - (Sint16*)Data.buffer ); |
536 | |
537 /*-------------------------------------------------------------------------*/ | |
538 static int padSilence( AdapterC Data, int length ) | |
539 { | |
540 Uint32 zero, *buffer; | |
541 int i, mask = 0; | |
542 | |
543 buffer = (Uint32*) ( Data.buffer + length ); | |
544 if( Data.mode != SDL_SOUND_Loop ) | |
545 mask = Data.filter->mask; | |
546 length = mask - ( ( length - 1 ) & mask ); | |
547 | |
548 for( i = 0; i < length>>2; i++ ) | |
549 buffer[i] = zero; | |
550 for( ; i < length; i++ ) | |
551 ((Uint8*)buffer)[i] = ((Uint8*)&zero)[i&3]; | |
552 | |
553 return length + ((Uint8*)buffer - Data.buffer); | |
554 } | 579 } |
555 | 580 |
556 /*-------------------------------------------------------------------------*/ | 581 /*-------------------------------------------------------------------------*/ |
557 /* gives a maximal error of 3% and typical less than 0.2% */ | 582 /* gives a maximal error of 3% and typical less than 0.2% */ |
558 static Fraction findFraction( float Value ) | 583 static Fraction findFraction( float Value ) |
631 } | 656 } |
632 fprintf( stderr, " center: %6d %6d \n", dst[63], dst[64] ); | 657 fprintf( stderr, " center: %6d %6d \n", dst[63], dst[64] ); |
633 return fg; | 658 return fg; |
634 } | 659 } |
635 | 660 |
636 static Fraction setupVarFilter( VarFilter* filter, float Ratio ) | 661 static Fraction setupVarFilter( Sound_AudioCVT *Data, float Ratio ) |
637 { | 662 { |
638 int pos,n,d, incr, phase = 0; | 663 int pos,n,d, incr, phase = 0; |
639 float Scale, rd, fg; | 664 float Scale, rd, fg; |
640 Fraction IRatio; | 665 Fraction IRatio; |
666 VarFilter* filter = &Data->filter; | |
641 | 667 |
642 IRatio = findFraction( Ratio ); | 668 IRatio = findFraction( Ratio ); |
643 // Scale = Ratio < 1. ? 0.0364733 : 0.0211952; | 669 // Scale = Ratio < 1. ? 0.0364733 : 0.0211952; |
644 Scale = 0.0084778; | 670 Scale = 0.0084778; |
645 Ratio = min( Ratio, 0.97 ); | 671 Ratio = min( Ratio, 0.97 ); |
663 IRatio.numerator = d; | 689 IRatio.numerator = d; |
664 IRatio.denominator = n; | 690 IRatio.denominator = n; |
665 return IRatio; | 691 return IRatio; |
666 } | 692 } |
667 /*-------------------------------------------------------------------------*/ | 693 /*-------------------------------------------------------------------------*/ |
694 static void initAudioCVT( Sound_AudioCVT *Data ) | |
695 { | |
696 Data->len_ratio = 1.; | |
697 Data->len_mult = 1; | |
698 Data->add = 0; | |
699 Data->len_add = 0; | |
700 Data->filter_index = 0; | |
701 } | |
702 | |
668 static void adjustSize( Sound_AudioCVT *Data, int add, Fraction f ) | 703 static void adjustSize( Sound_AudioCVT *Data, int add, Fraction f ) |
669 { | 704 { |
670 | |
671 double ratio = f.numerator / (double) f.denominator; | 705 double ratio = f.numerator / (double) f.denominator; |
672 Data->len_ratio *= ratio; | 706 Data->len_ratio *= ratio; |
673 Data->len_mult = max( Data->len_mult, ceil(Data->len_ratio) ); | 707 Data->len_mult = max( Data->len_mult, ceil(Data->len_ratio) ); |
674 Data->add = ratio * (Data->add + add); | 708 Data->add = ratio * (Data->add + add); |
675 Data->len_add = max( Data->len_add, ceil(Data->add) ); | 709 Data->len_add = max( Data->len_add, ceil(Data->add) ); |
676 } | 710 } |
677 | 711 |
678 static void initSize( Sound_AudioCVT *Data ) | 712 static Adapter* addAdapter( Sound_AudioCVT *Data, Adapter a ) |
679 { | 713 { |
680 Data->len_ratio = 1.; | 714 Data->adapter[Data->filter_index] = a; |
681 Data->len_mult = 1; | 715 return &Data->adapter[Data->filter_index++]; |
682 Data->add = 0; | 716 } |
683 Data->len_add = 0; | 717 |
684 } | 718 static void addHAdapter( Sound_AudioCVT *Data, Adapter a ) |
719 { | |
720 adjustSize( Data, 0, Half ); | |
721 addAdapter( Data, a ); | |
722 } | |
723 | |
724 static void addDAdapter( Sound_AudioCVT *Data, Adapter a ) | |
725 { | |
726 adjustSize( Data, 0, Double ); | |
727 addAdapter( Data, a ); | |
728 } | |
729 | |
685 | 730 |
686 /*-------------------------------------------------------------------------*/ | 731 /*-------------------------------------------------------------------------*/ |
687 const Adapter doubleRate[2] = { doubleRateMono, doubleRateStereo }; | 732 const Adapter doubleRate[2] = { doubleRateMono, doubleRateStereo }; |
688 const Adapter halfRate[2] = { halfRateMono, halfRateStereo }; | 733 const Adapter halfRate[2] = { halfRateMono, halfRateStereo }; |
689 const Adapter increaseRate[2] = { increaseRateMono, increaseRateStereo }; | 734 const Adapter increaseRate[2] = { increaseRateMono, increaseRateStereo }; |
690 const Adapter decreaseRate[2] = { decreaseRateMono, decreaseRateStereo }; | 735 const Adapter decreaseRate[2] = { decreaseRateMono, decreaseRateStereo }; |
691 | 736 |
692 static void createRateConverter( Sound_AudioCVT *Data, int* fip, | 737 static int createRateConverter( Sound_AudioCVT *Data, |
693 int SrcRate, int DestRate, int channel ) | 738 int SrcRate, int DestRate, int channel ) |
694 { | 739 { |
695 const int c = channel - 1; | 740 const int c = channel - 1; |
696 const int size = 16 * channel * _fsize; | 741 const int size = 16 * channel * _fsize; |
697 int filter_index = *fip; | 742 Adapter* AdapterPos; |
698 int VarPos = 0; | |
699 float Ratio = DestRate; | 743 float Ratio = DestRate; |
700 Fraction f; | 744 Fraction f; |
701 *fip = -1; | |
702 | |
703 | 745 |
704 if( SrcRate < 1 || SrcRate > 1<<18 || | 746 if( SrcRate < 1 || SrcRate > 1<<18 || |
705 DestRate < 1 || DestRate > 1<<18 ) return; | 747 DestRate < 1 || DestRate > 1<<18 ) return -1; |
706 Ratio /= SrcRate; | 748 Ratio /= SrcRate; |
707 | 749 |
708 if( Ratio > 1.) | 750 AdapterPos = addAdapter( Data, minus5dB ); |
709 VarPos = filter_index++; | 751 |
752 while( Ratio > 64./31.) | |
753 { | |
754 Ratio /= 2.; | |
755 addAdapter( Data, doubleRate[c] ); | |
756 adjustSize( Data, size, Double ); | |
757 } | |
758 | |
759 while( Ratio < 31./64. ) | |
760 { | |
761 Ratio *= 2; | |
762 addAdapter( Data, halfRate[c] ); | |
763 adjustSize( Data, size, Half ); | |
764 } | |
765 | |
766 if( Ratio > 1. ) | |
767 { | |
768 *AdapterPos = increaseRate[c]; | |
769 f = setupVarFilter( Data, Ratio ); | |
770 adjustSize( Data, size, f ); | |
771 } | |
710 else | 772 else |
711 Data->adapter[filter_index++] = minus5dB; | 773 { |
712 | 774 f = setupVarFilter( Data, Ratio ); |
713 while( Ratio > 64./31.) | 775 addAdapter( Data, decreaseRate[c]); |
714 { | |
715 Ratio /= 2.; | |
716 Data->adapter[filter_index++] = doubleRate[c]; | |
717 adjustSize( Data, size, Double ); | |
718 } | |
719 | |
720 while( Ratio < 31./64. ) | |
721 { | |
722 Ratio *= 2; | |
723 Data->adapter[filter_index++] = halfRate[c]; | |
724 adjustSize( Data, size, Half ); | |
725 } | |
726 | |
727 if( Ratio > 1. ) | |
728 { | |
729 Data->adapter[VarPos] = increaseRate[c]; | |
730 f = setupVarFilter( &Data->filter, Ratio ); | |
731 adjustSize( Data, size, f ); | 776 adjustSize( Data, size, f ); |
732 } | 777 } |
778 | |
779 return 0; | |
780 } | |
781 | |
782 /*-------------------------------------------------------------------------*/ | |
783 static void createFormatConverter16Bit(Sound_AudioCVT *Data, | |
784 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
785 { | |
786 if( src.channels == 2 && dst.channels == 1 ) | |
787 { | |
788 if( !IS_SYSENDIAN(src) ) | |
789 addAdapter( Data, swapBytes ); | |
790 | |
791 if( IS_SIGNED(src) ) | |
792 addHAdapter( Data, convertStereoToMonoS16Bit ); | |
793 else | |
794 addHAdapter( Data, convertStereoToMonoU16Bit ); | |
795 | |
796 if( !IS_SYSENDIAN(dst) ) | |
797 addAdapter( Data, swapBytes ); | |
798 } | |
799 else if( IS_SYSENDIAN(src) != IS_SYSENDIAN(dst) ) | |
800 addAdapter( Data, swapBytes ); | |
801 | |
802 if( IS_SIGNED(src) != IS_SIGNED(dst) ) | |
803 { | |
804 if( IS_SYSENDIAN(dst) ) | |
805 addAdapter( Data, changeSigned16BitSys ); | |
806 else | |
807 addAdapter( Data, changeSigned16BitWrong ); | |
808 } | |
809 | |
810 if( src.channels == 1 && dst.channels == 2 ) | |
811 addDAdapter( Data, convertMonoToStereo16Bit ); | |
812 } | |
813 | |
814 /*-------------------------------------------------------------------------*/ | |
815 static void createFormatConverter8Bit(Sound_AudioCVT *Data, | |
816 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
817 { | |
818 if( IS_16BIT(src) ) | |
819 { | |
820 if( IS_SYSENDIAN(src) ) | |
821 addHAdapter( Data, cut16BitSysTo8Bit ); | |
822 else | |
823 addHAdapter( Data, cut16BitWrongTo8Bit ); | |
824 } | |
825 | |
826 if( src.channels == 2 && dst.channels == 1 ) | |
827 { | |
828 if( IS_SIGNED(src) ) | |
829 addHAdapter( Data, convertStereoToMonoS8Bit ); | |
830 else | |
831 addHAdapter( Data, convertStereoToMonoU8Bit ); | |
832 } | |
833 | |
834 if( IS_SIGNED(src) != IS_SIGNED(dst) ) | |
835 addDAdapter( Data, changeSigned8Bit ); | |
836 | |
837 if( src.channels == 1 && dst.channels == 2 ) | |
838 addDAdapter( Data, convertMonoToStereo8Bit ); | |
839 | |
840 if( !IS_8BIT(dst) ) | |
841 { | |
842 if( IS_SYSENDIAN(dst) ) | |
843 addDAdapter( Data, expand8BitTo16BitSys ); | |
844 else | |
845 addDAdapter( Data, expand8BitTo16BitWrong ); | |
846 } | |
847 } | |
848 | |
849 /*-------------------------------------------------------------------------*/ | |
850 static void createFormatConverter(Sound_AudioCVT *Data, | |
851 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
852 { | |
853 if( IS_FLOAT(src) ) | |
854 addHAdapter( Data, cutFloatTo16Bit ); | |
855 | |
856 if( IS_8BIT(src) || IS_8BIT(dst) ) | |
857 createFormatConverter8Bit( Data, src, dst); | |
733 else | 858 else |
734 { | 859 createFormatConverter16Bit( Data, src, dst); |
735 Data->adapter[filter_index++] = decreaseRate[c]; | |
736 f = setupVarFilter( &Data->filter, Ratio ); | |
737 adjustSize( Data, size, f ); | |
738 } | |
739 *fip = filter_index; | |
740 } | |
741 | |
742 /*-------------------------------------------------------------------------*/ | |
743 static void createFormatConverter16Bit(Sound_AudioCVT *Data, int* fip, | |
744 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
745 { | |
746 int filter_index = *fip; | |
747 | |
748 if( src.channels == 2 && dst.channels == 1 ) | |
749 { | |
750 adjustSize( Data, 0, Half ); | |
751 | |
752 if( !IS_SYSENDIAN(src) ) | |
753 Data->adapter[filter_index++] = swapBytes; | |
754 | |
755 if( IS_SIGNED(src) ) | |
756 Data->adapter[filter_index++] = convertStereoToMonoS16Bit; | |
757 else | |
758 Data->adapter[filter_index++] = convertStereoToMonoU16Bit; | |
759 | |
760 if( !IS_SYSENDIAN(dst) ) | |
761 Data->adapter[filter_index++] = swapBytes; | |
762 } | |
763 else if( IS_SYSENDIAN(src) != IS_SYSENDIAN(dst) ) | |
764 Data->adapter[filter_index++] = swapBytes; | |
765 | |
766 if( IS_SIGNED(src) != IS_SIGNED(dst) ) | |
767 { | |
768 if( IS_SYSENDIAN(dst) ) | |
769 Data->adapter[filter_index++] = changeSigned16BitSys; | |
770 else | |
771 Data->adapter[filter_index++] = changeSigned16BitWrong; | |
772 } | |
773 | |
774 if( src.channels == 1 && dst.channels == 2 ) | |
775 { | |
776 adjustSize( Data, 0, Double ); | |
777 Data->adapter[filter_index++] = convertMonoToStereo16Bit; | |
778 } | |
779 | |
780 *fip = filter_index; | |
781 } | |
782 | |
783 /*-------------------------------------------------------------------------*/ | |
784 static void createFormatConverter8Bit(Sound_AudioCVT *Data, int *fip, | |
785 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
786 { | |
787 int filter_index = *fip; | |
788 if( IS_16BIT(src) ) | |
789 { | |
790 adjustSize( Data, 0, Half ); | |
791 | |
792 if( IS_SYSENDIAN(src) ) | |
793 Data->adapter[filter_index++] = cut16BitSysTo8Bit; | |
794 else | |
795 Data->adapter[filter_index++] = cut16BitWrongTo8Bit; | |
796 } | |
797 | |
798 if( src.channels == 2 && dst.channels == 1 ) | |
799 { | |
800 adjustSize( Data, 0, Half ); | |
801 | |
802 if( IS_SIGNED(src) ) | |
803 Data->adapter[filter_index++] = convertStereoToMonoS8Bit; | |
804 else | |
805 Data->adapter[filter_index++] = convertStereoToMonoU8Bit; | |
806 } | |
807 | |
808 if( IS_SIGNED(src) != IS_SIGNED(dst) ) | |
809 Data->adapter[filter_index++] = changeSigned8Bit; | |
810 | |
811 if( src.channels == 1 && dst.channels == 2 ) | |
812 { | |
813 adjustSize( Data, 0, Double ); | |
814 Data->adapter[filter_index++] = convertMonoToStereo8Bit; | |
815 } | |
816 | |
817 if( !IS_8BIT(dst) ) | |
818 { | |
819 adjustSize( Data, 0, Double ); | |
820 if( IS_SYSENDIAN(dst) ) | |
821 Data->adapter[filter_index++] = expand8BitTo16BitSys; | |
822 else | |
823 Data->adapter[filter_index++] = expand8BitTo16BitWrong; | |
824 } | |
825 | |
826 *fip = filter_index; | |
827 } | |
828 | |
829 /*-------------------------------------------------------------------------*/ | |
830 static void createFormatConverter(Sound_AudioCVT *Data, int *fip, | |
831 SDL_AudioSpec src, SDL_AudioSpec dst ) | |
832 { | |
833 int filter_index = *fip; | |
834 | |
835 if( IS_FLOAT(src) ) | |
836 { | |
837 Data->adapter[filter_index++] = cutFloatTo16Bit; | |
838 adjustSize( Data, 0, Half ); | |
839 } | |
840 | |
841 if( IS_8BIT(src) || IS_8BIT(dst) ) | |
842 createFormatConverter8Bit( Data, &filter_index, src, dst); | |
843 else | |
844 createFormatConverter16Bit( Data, &filter_index, src, dst); | |
845 | 860 |
846 if( IS_FLOAT(dst) ) | 861 if( IS_FLOAT(dst) ) |
847 { | 862 addDAdapter( Data, expand16BitToFloat ); |
848 Data->adapter[filter_index++] = expand16BitToFloat; | 863 } |
849 adjustSize( Data, 0, Double ); | 864 |
850 } | 865 /*-------------------------------------------------------------------------*/ |
851 | 866 int Sound_AltBuildAudioCVT( Sound_AudioCVT *Data, |
852 *fip = filter_index; | |
853 } | |
854 | |
855 /*-------------------------------------------------------------------------*/ | |
856 Uint32 getSilenceValue( Uint16 format ) | |
857 { | |
858 const static float fzero[] = {0.0000001}; | |
859 switch( format ) | |
860 { | |
861 case 0x0020: return *(Uint32*) fzero; | |
862 default: ; | |
863 } | |
864 return 0; | |
865 } | |
866 | |
867 /*-------------------------------------------------------------------------*/ | |
868 int BuildAudioCVT( Sound_AudioCVT *Data, | |
869 SDL_AudioSpec src, SDL_AudioSpec dst ) | 867 SDL_AudioSpec src, SDL_AudioSpec dst ) |
870 { | 868 { |
871 SDL_AudioSpec intrm; | 869 SDL_AudioSpec im; |
872 int filter_index = 0; | |
873 | 870 |
874 if( Data == NULL ) return -1; | 871 if( Data == NULL ) return -1; |
875 if( dst.size < 8 ) return -1; | 872 |
876 | 873 initAudioCVT( Data ); |
877 initSize( Data ); | |
878 Data->filter.ratio.denominator = 0; | 874 Data->filter.ratio.denominator = 0; |
879 Data->filter.zero = getSilenceValue( dst.format ); | |
880 Data->filter.mask = dst.size - 1; | 875 Data->filter.mask = dst.size - 1; |
881 | |
882 | |
883 | 876 |
884 /* Check channels */ | 877 /* Check channels */ |
885 if( src.channels < 1 || src.channels > 2 || | 878 if( src.channels < 1 || src.channels > 2 || |
886 dst.channels < 1 || dst.channels > 2 ) goto error_exit; | 879 dst.channels < 1 || dst.channels > 2 ) goto error_exit; |
887 | 880 |
888 /* If no frequency conversion is needed, go straight to dst format */ | 881 if( src.freq != dst.freq ) |
889 if( src.freq == dst.freq ) | 882 { |
890 { | 883 /* Convert to intermidiate format: signed 16Bit System-Endian */ |
891 createFormatConverter( Data, &filter_index, src, dst ); | 884 im.format = AUDIO_S16SYS; |
892 goto sucess_exit; | 885 im.channels = min( src.channels, dst.channels ); |
893 } | 886 createFormatConverter( Data, src, im ); |
894 | |
895 /* Convert to signed 16Bit System-Endian */ | |
896 intrm.format = AUDIO_S16SYS; | |
897 intrm.channels = min( src.channels, dst.channels ); | |
898 createFormatConverter( Data, &filter_index, src, intrm ); | |
899 | 887 |
900 /* Do rate conversion */ | 888 /* Do rate conversion */ |
901 if( src.channels == 2 && dst.channels == 2 ) | 889 if( createRateConverter( Data, src.freq, dst.freq, im.channels ) ) |
902 createRateConverter( Data, &filter_index, src.freq, dst.freq, 2 ); | 890 goto error_exit; |
903 else | 891 |
904 createRateConverter( Data, &filter_index, src.freq, dst.freq, 1 ); | 892 src = im; |
905 /* propagate error */ | 893 } |
906 if( filter_index < 0 ) goto error_exit; | |
907 | 894 |
908 /* Convert to final format */ | 895 /* Convert to final format */ |
909 createFormatConverter( Data, &filter_index, intrm, dst ); | 896 createFormatConverter( Data, src, dst ); |
910 | 897 |
911 /* Set up the filter information */ | 898 /* Finalize adapter list */ |
912 sucess_exit: | 899 addAdapter( Data, NULL ); |
913 Data->adapter[filter_index++] = padSilence; | |
914 Data->adapter[filter_index] = NULL; | |
915 /* !!! FIXME: Is it okay to assign NULL to a function pointer? | 900 /* !!! FIXME: Is it okay to assign NULL to a function pointer? |
916 Borland says no. -frank */ | 901 Borland says no. -frank */ |
917 return 0; | 902 return 0; |
918 | 903 |
919 error_exit: | 904 error_exit: |
968 AdapterDesc(halfRateStereo), | 953 AdapterDesc(halfRateStereo), |
969 AdapterDesc(increaseRateMono), | 954 AdapterDesc(increaseRateMono), |
970 AdapterDesc(increaseRateStereo), | 955 AdapterDesc(increaseRateStereo), |
971 AdapterDesc(decreaseRateMono), | 956 AdapterDesc(decreaseRateMono), |
972 AdapterDesc(decreaseRateStereo), | 957 AdapterDesc(decreaseRateStereo), |
973 AdapterDesc(padSilence), | |
974 { NULL, "----------NULL-----------\n" } | 958 { NULL, "----------NULL-----------\n" } |
975 }; | 959 }; |
976 | 960 |
977 fprintf( stderr, "Sound_AudioCVT:\n" ); | 961 fprintf( stderr, "Sound_AudioCVT:\n" ); |
978 fprintf( stderr, " needed: %8d\n", Data->needed ); | 962 fprintf( stderr, " needed: %8d\n", Data->needed ); |
1023 } | 1007 } |
1024 | 1008 |
1025 | 1009 |
1026 int Sound_BuildAudioCVT(Sound_AudioCVT *Data, | 1010 int Sound_BuildAudioCVT(Sound_AudioCVT *Data, |
1027 Uint16 src_format, Uint8 src_channels, int src_rate, | 1011 Uint16 src_format, Uint8 src_channels, int src_rate, |
1028 Uint16 dst_format, Uint8 dst_channels, int dst_rate, Uint32 dst_size ) | 1012 Uint16 dst_format, Uint8 dst_channels, int dst_rate ) |
1029 { | 1013 { |
1030 SDL_AudioSpec src, dst; | 1014 SDL_AudioSpec src, dst; |
1031 int ret; | 1015 int ret; |
1032 | 1016 |
1033 fprintf (stderr, | 1017 fprintf (stderr, |
1037 "channels: %6d -> %6d\n" | 1021 "channels: %6d -> %6d\n" |
1038 "rate: %6d -> %6d\n" | 1022 "rate: %6d -> %6d\n" |
1039 "size: don't care -> %#7x\n\n", | 1023 "size: don't care -> %#7x\n\n", |
1040 fmt_to_str (src_format), fmt_to_str (dst_format), | 1024 fmt_to_str (src_format), fmt_to_str (dst_format), |
1041 src_channels, dst_channels, | 1025 src_channels, dst_channels, |
1042 src_rate, dst_rate, | 1026 src_rate, dst_rate ); |
1043 dst_size ); | |
1044 | 1027 |
1045 src.format = src_format; | 1028 src.format = src_format; |
1046 src.channels = src_channels; | 1029 src.channels = src_channels; |
1047 src.freq = src_rate; | 1030 src.freq = src_rate; |
1048 | 1031 |
1049 dst.format = dst_format; | 1032 dst.format = dst_format; |
1050 dst.channels = dst_channels; | 1033 dst.channels = dst_channels; |
1051 dst.freq = dst_rate; | 1034 dst.freq = dst_rate; |
1052 dst.size = dst_size; | 1035 |
1053 | 1036 ret = Sound_AltBuildAudioCVT( Data, src, dst ); |
1054 ret = BuildAudioCVT( Data, src, dst ); | |
1055 Data->needed = 1; | 1037 Data->needed = 1; |
1056 | 1038 |
1057 show_AudioCVT( Data ); | 1039 show_AudioCVT( Data ); |
1058 fprintf (stderr, "\n" | 1040 fprintf (stderr, "\n" |
1059 "return value: %d \n\n\n", ret ); | 1041 "return value: %d \n\n\n", ret ); |