Mercurial > SDL_sound_CoreAudio
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; |