comparison alt_audio_convert.c @ 366:eda146d666d1

More patches from Frank.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 21 Jun 2002 20:03:46 +0000
parents f61eadea1f44
children 84d6c604eaa9
comparison
equal deleted inserted replaced
365:f61eadea1f44 366:eda146d666d1
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>
30 #include <math.h> 29 #include <math.h>
31 30
32 /* just to make sure this is defined... */ 31 /* just to make sure this is defined... */
33 32
34 #ifndef min 33 #ifndef min
35 #define min(x, y) ( ((x) < (y)) ? (x) : (y) ) 34 #define min(x, y) ( ((x) < (y)) ? (x) : (y) )
36 #endif 35 #endif
37 36
38 #ifndef max 37 #ifndef abs
39 #define max(x, y) ( ((x) > (y)) ? (x) : (y) ) 38 #define abs(x) ( ((x) > (0)) ? (x) : -(x) )
40 #endif 39 #endif
41 40
42 41
43 /* some macros for "parsing" format */ 42 /* some macros for "parsing" format */
44 43
45 #define IS_8BIT(x) ((x).format & 0x0008) 44 #define IS_8BIT(x) ((x).format & 0x0008)
46 #define IS_16BIT(x) ((x).format & 0x0010) 45 #define IS_16BIT(x) ((x).format & 0x0010)
47 #define IS_FLOAT(x) ((x).format & 0x0020) 46 #define IS_FLOAT(x) ((x).format & 0x0020)
48 #define IS_SIGNED(x) ((x).format & 0x8000) 47 #define IS_SIGNED(x) ((x).format & 0x8000)
49 #define IS_SYSENDIAN(x) ((~AUDIO_U16SYS ^ (x).format) & 0x1000) 48 #define IS_SYSENDIAN(x) ((~AUDIO_U16SYS ^ (x).format) & 0x1000)
50
51
52 /*-------------------------------------------------------------------------*/
53 /* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation */
54 static const int filter[_fsize / 2] =
55 {
56 0, 20798, 0, -6764, 0, 3863, 0, -2560,
57 0, 1800, 0, -1295, 0, 936, 0, -671,
58 0, 474, 0, -326, 0, 217, 0, -138,
59 0, 83, 0, -46, 0, 23, 0, -9
60 };
61 49
62 50
63 /*-------------------------------------------------------------------------*/ 51 /*-------------------------------------------------------------------------*/
64 /* the purpose of the RateConverterBuffer is to provide a continous storage 52 /* 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 53 for head and tail of the (sample)-buffer. This allows a simple and
85 filter is nearly complete in the zero region, only one input value is 73 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 74 used. After the calculation of the first output value, the pointer are
87 incremented or decremented depending on down or up conversion and the 75 incremented or decremented depending on down or up conversion and the
88 first two input value are taken into account. This procedure repeats 76 first two input value are taken into account. This procedure repeats
89 until the filter has processed all zeroes. The distance of the pointer 77 until the filter has processed all zeroes. The distance of the pointer
90 movement is stored in flength. 78 movement is stored in flength, always positive.
91 79
92 Further a pointer cinp to the sample buffer itself is stored. The pointer 80 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 81 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 82 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 83 over the sample buffer until it reaches the other end. The distance of
96 the movement is stored in clength. 84 the movement is stored in clength.
97 85
98 Finally the decay of the filter is done by linp, llength like finp, 86 Finally the decay of the filter is done by linp and llength like finp,
99 flength, but in reverse order. 87 flength, but in reverse order.
100 88
101 buffer denotes the start or the end of the output buffer, depending 89 buffer denotes the start or the end of the output buffer, depending
102 on direction of the rate conversion. 90 on direction of the rate conversion.
103 91
104 All pointer and length referring the buffer as Sint16. All length 92 All pointer and length referring the buffer as Sint16. All length
105 are refering to the input buffer */ 93 are refering to the input buffer */
106 94
107 typedef struct 95 typedef struct
108 { 96 {
109 Sint16 inbuffer[6*_fsize]; 97 Sint16 inbuffer[24*_fsize];
110 Sint16 *finp, *cinp, *linp; 98 Sint16 *finp, *cinp, *linp;
111 Sint16 *buffer; 99 Sint16 *buffer;
112 int flength, clength, llength; 100 int flength, clength, llength;
113 } RateConverterBuffer; 101 } RateConverterBuffer;
114 102
359 buffer[i]= 38084 * buffer[i] >> 16; 347 buffer[i]= 38084 * buffer[i] >> 16;
360 return length; 348 return length;
361 } 349 }
362 350
363 /*-------------------------------------------------------------------------*/ 351 /*-------------------------------------------------------------------------*/
352 enum RateConverterType { varRate = 0, hlfRate = 1, dblRate = 2 };
364 static void initRateConverterBuffer( RateConverterBuffer *rcb, 353 static void initRateConverterBuffer( RateConverterBuffer *rcb,
365 AdapterC* Data, int length, int rel_size ) 354 AdapterC* Data, int length, RateConverterType r, int rel_size )
366 { 355 {
367 int size, slength; 356 int size, dir;
368 int den, num; 357 int den[] = { 0, 1, 2};
369 int i; 358 int num[] = { 0, 2, 1};
370 359 int i;
371 den = Data->filter->denominator; 360
372 num = Data->filter->numerator; 361 den[0] = Data->filter->denominator;
373 size = _fsize * rel_size; 362 num[0] = Data->filter->numerator;
363
364 size = 2 * _fsize * abs(rel_size);
365 dir = rel_size > 0 ? 1 : 0;
374 length >>= 1; 366 length >>= 1;
375 slength = rel_size > 0 ? length : -length;
376 367
377 rcb->buffer = (Sint16*)( Data->buffer ); 368 rcb->buffer = (Sint16*)( Data->buffer );
378 369
379 if( Data->mode & SDL_AI_Loop ) 370 if( Data->mode & SDL_AI_Loop )
380 { 371 {
381 // !!!FIXME: modulo length, take scale into account 372 // !!!FIXME: modulo length, take scale into account,
373 // check against the 'else' part
382 for( i = 0; i < size; i++ ) 374 for( i = 0; i < size; i++ )
383 { 375 {
384 rcb->inbuffer[i] = rcb->buffer[length-size+i]; 376 rcb->inbuffer[i] = rcb->buffer[length-size+i];
385 rcb->inbuffer[i+size] = rcb->buffer[i]; 377 rcb->inbuffer[i+size] = rcb->buffer[i];
386 } 378 }
387 rcb->finp = rcb->linp = rcb->inbuffer + size; 379 rcb->finp = rcb->linp = rcb->inbuffer + size;
388 if( size < 0 ) 380 if( size < 0 )
389 rcb->buffer += num * ( length + 2 * size ) / den; 381 rcb->buffer += num[r] * ( length + 2 * size ) / den[r];
390 } 382 }
391 else 383 else
392 { 384 {
393 for( i = 0; i < size; i++ ) 385 for( i = 0; i < size; i++ )
394 { 386 {
395 int j; 387 int k;
396 j = length-size+i; 388 k = length-size+i;
397 rcb->inbuffer[i] = j < 0 ? 0 : rcb->buffer[j]; 389 rcb->inbuffer[i] = k < 0 ? 0 : rcb->buffer[k];
398 rcb->inbuffer[i+size] = 0; 390 rcb->inbuffer[i+size] = 0;
399 rcb->inbuffer[i+2*size] = i < length ? rcb->buffer[i] : 0; 391 rcb->inbuffer[i+2*size] = i < length ? rcb->buffer[i] : 0;
400 } 392 }
401 // !!!FIXME: take lenght < size into account 393 // !!!FIXME: take lenght < size into account
402 rcb->finp = rcb->inbuffer + abs( 3*size/2 ) + size/2; 394 rcb->flength = rcb->llength = size;
403 rcb->linp = rcb->inbuffer + abs( 3*size/2 ) - size/2; 395 rcb->clength = length - size;
404 rcb->flength = rcb->llength = 2*size; 396
405 rcb->clength = slength - 2*size; 397 if( dir )
406 398 {
407 if( size < 0 ) 399 rcb->finp = rcb->inbuffer + 5*size/2;
408 rcb->buffer += num * ( length + 2 * size ) / den; 400 rcb->cinp = rcb->buffer + length - size/2;
401 rcb->linp = rcb->inbuffer + 3*size/2;
402 rcb->buffer += den[r] * ( length + size ) / num[r];
403 }
404 else
405 {
406 rcb->finp = rcb->inbuffer + size/2;
407 rcb->cinp = rcb->buffer + size/2;
408 rcb->linp = rcb->inbuffer + 3*size/2;
409 }
409 } 410 }
410 } 411 }
411 412
412 static void nextRateConverterBuffer( RateConverterBuffer *rcb ) 413 static void nextRateConverterBuffer( RateConverterBuffer *rcb )
413 { 414 {
434 435
435 /*-------------------------------------------------------------------------*/ 436 /*-------------------------------------------------------------------------*/
436 static int doubleRateMono( AdapterC Data, int length ) 437 static int doubleRateMono( AdapterC Data, int length )
437 { 438 {
438 RateConverterBuffer rcb; 439 RateConverterBuffer rcb;
439 initRateConverterBuffer( &rcb, &Data, length, 1 ); 440 initRateConverterBuffer( &rcb, &Data, length, dblRate, 1 );
440 return doRateConversion( &rcb, doubleRate1, NULL ); 441 return doRateConversion( &rcb, doubleRate1, NULL );
441 } 442 }
442 443
443 static int doubleRateStereo( AdapterC Data, int length ) 444 static int doubleRateStereo( AdapterC Data, int length )
444 { 445 {
445 RateConverterBuffer rcb; 446 RateConverterBuffer rcb;
446 initRateConverterBuffer( &rcb, &Data, length, 2 ); 447 initRateConverterBuffer( &rcb, &Data, length, dblRate, 2 );
447 doRateConversion( &rcb, doubleRate2, NULL ); 448 doRateConversion( &rcb, doubleRate2, NULL );
448 nextRateConverterBuffer( &rcb ); 449 nextRateConverterBuffer( &rcb );
449 return 2 + doRateConversion( &rcb, doubleRate2, NULL ); 450 return 2 + doRateConversion( &rcb, doubleRate2, NULL );
450 } 451 }
451 452
452 /*-------------------------------------------------------------------------*/ 453 /*-------------------------------------------------------------------------*/
453 static int halfRateMono( AdapterC Data, int length ) 454 static int halfRateMono( AdapterC Data, int length )
454 { 455 {
455 RateConverterBuffer rcb; 456 RateConverterBuffer rcb;
456 initRateConverterBuffer( &rcb, &Data, length, -1 ); 457 initRateConverterBuffer( &rcb, &Data, length, hlfRate, -1 );
457 return doRateConversion( &rcb, halfRate1, NULL ); 458 return doRateConversion( &rcb, halfRate1, NULL );
458 } 459 }
459 460
460 static int halfRateStereo( AdapterC Data, int length ) 461 static int halfRateStereo( AdapterC Data, int length )
461 { 462 {
462 RateConverterBuffer rcb; 463 RateConverterBuffer rcb;
463 initRateConverterBuffer( &rcb, &Data, length, -2 ); 464 initRateConverterBuffer( &rcb, &Data, length, hlfRate, -2 );
464 doRateConversion( &rcb, halfRate2, NULL ); 465 doRateConversion( &rcb, halfRate2, NULL );
465 nextRateConverterBuffer( &rcb ); 466 nextRateConverterBuffer( &rcb );
466 return 2 + doRateConversion( &rcb, halfRate2, NULL ); 467 return 2 + doRateConversion( &rcb, halfRate2, NULL );
467 } 468 }
468 469
469 /*-------------------------------------------------------------------------*/ 470 /*-------------------------------------------------------------------------*/
470 static int increaseRateMono( AdapterC Data, int length ) 471 static int increaseRateMono( AdapterC Data, int length )
471 { 472 {
472 RateConverterBuffer rcb; 473 RateConverterBuffer rcb;
473 initRateConverterBuffer( &rcb, &Data, length, 2 ); 474 initRateConverterBuffer( &rcb, &Data, length, varRate, 2 );
474 return doRateConversion( &rcb, increaseRate1, Data.filter ); 475 return doRateConversion( &rcb, increaseRate1, Data.filter );
475 } 476 }
476 477
477 static int increaseRateStereo( AdapterC Data, int length ) 478 static int increaseRateStereo( AdapterC Data, int length )
478 { 479 {
479 RateConverterBuffer rcb; 480 RateConverterBuffer rcb;
480 initRateConverterBuffer( &rcb, &Data, length, 4 ); 481 initRateConverterBuffer( &rcb, &Data, length, varRate, 4 );
481 doRateConversion( &rcb, increaseRate2, Data.filter ); 482 doRateConversion( &rcb, increaseRate2, Data.filter );
482 nextRateConverterBuffer( &rcb ); 483 nextRateConverterBuffer( &rcb );
483 return 2 + doRateConversion( &rcb, increaseRate2, Data.filter ); 484 return 2 + doRateConversion( &rcb, increaseRate2, Data.filter );
484 } 485 }
485 486
486 /*-------------------------------------------------------------------------*/ 487 /*-------------------------------------------------------------------------*/
487 static int decreaseRateMono( AdapterC Data, int length ) 488 static int decreaseRateMono( AdapterC Data, int length )
488 { 489 {
489 RateConverterBuffer rcb; 490 RateConverterBuffer rcb;
490 initRateConverterBuffer( &rcb, &Data, length, -2 ); 491 initRateConverterBuffer( &rcb, &Data, length, varRate, -2 );
491 return doRateConversion( &rcb, decreaseRate1, Data.filter ); 492 return doRateConversion( &rcb, decreaseRate1, Data.filter );
492 } 493 }
493 494
494 static int decreaseRateStereo( AdapterC Data, int length ) 495 static int decreaseRateStereo( AdapterC Data, int length )
495 { 496 {
496 RateConverterBuffer rcb; 497 RateConverterBuffer rcb;
497 initRateConverterBuffer( &rcb, &Data, length, -4 ); 498 initRateConverterBuffer( &rcb, &Data, length, varRate, -4 );
498 doRateConversion( &rcb, decreaseRate2, Data.filter ); 499 doRateConversion( &rcb, decreaseRate2, Data.filter );
499 nextRateConverterBuffer( &rcb ); 500 nextRateConverterBuffer( &rcb );
500 return doRateConversion( &rcb, decreaseRate2, Data.filter ); 501 return doRateConversion( &rcb, decreaseRate2, Data.filter );
501 } 502 }
502 503
533 int n,num=1,den=1; 534 int n,num=1,den=1;
534 535
535 float RelErr, BestErr = 0; 536 float RelErr, BestErr = 0;
536 if( Value < 31/64. || Value > 64/31. ) return Result; 537 if( Value < 31/64. || Value > 64/31. ) return Result;
537 538
538 for( n = 0; n < sizeof(frac); num=frac[n++] ) 539 for( n = 0; n < SDL_TABLESIZE(frac); num=frac[n++] )
539 { 540 {
540 if( num < 0 ) den++; 541 if( num < 0 ) den++;
541 RelErr = Value * num / den; 542 RelErr = Value * num / den;
542 RelErr = min( RelErr, 1/RelErr ); 543 RelErr = min( RelErr, 1/RelErr );
543 if( RelErr > BestErr ) 544 if( RelErr > BestErr )
607 for( i = 0; i < d; i++ ) 608 for( i = 0; i < d; i++ )
608 { 609 {
609 if( phase >= n ) 610 if( phase >= n )
610 { 611 {
611 phase -= d; 612 phase -= d;
612 filter->incr[i] = Direction.incr; 613 filter->incr[i] = abs(Direction.incr);
613 } 614 }
614 else 615 else
615 filter->incr[i] = 1+Direction.incr; 616 filter->incr[i] = abs(1+Direction.incr);
616 617
617 calculateVarFilter( filter->c[i], Ratio, phase/(float)n, 618 calculateVarFilter( filter->c[i], Ratio, phase/(float)n,
618 Direction.scale ); 619 Direction.scale );
619 phase += d; 620 phase += d;
620 } 621 }
897 AdapterDesc(increaseRateStereo), 898 AdapterDesc(increaseRateStereo),
898 AdapterDesc(decreaseRateMono), 899 AdapterDesc(decreaseRateMono),
899 AdapterDesc(decreaseRateStereo), 900 AdapterDesc(decreaseRateStereo),
900 { NULL, "----------NULL-----------" } 901 { NULL, "----------NULL-----------" }
901 }; 902 };
902 const int AdapterDescMax = sizeof(AdapterDescription)
903 / sizeof(*AdapterDescription);
904 903
905 fprintf( stderr, "\nAdapter List: \n" ); 904 fprintf( stderr, "\nAdapter List: \n" );
906 for( i = 0; i < 32; i++ ) 905 for( i = 0; i < 32; i++ )
907 { 906 {
908 for( j = 0; j < AdapterDescMax; j++ ) 907 for( j = 0; j < SDL_TABLESIZE(AdapterDescription); j++ )
909 { 908 {
910 if( Data->adapter[i] == AdapterDescription[j].adapter ) 909 if( Data->adapter[i] == AdapterDescription[j].adapter )
911 { 910 {
912 fprintf( stderr, " %s\n", AdapterDescription[j].name ); 911 fprintf( stderr, " %s\n", AdapterDescription[j].name );
913 if( Data->adapter[i] == NULL ) return; 912 if( Data->adapter[i] == NULL ) return;