Mercurial > mplayer.hg
comparison libaf/af.c @ 14433:95bb94a930a3
always cancel down fractions (frac_t) to avoid overflows and playback
problems (e.g. when using resample and equalizer filters together, see
http://mplayerhq.hu/pipermail/mplayer-users/2004-December/050058.html)
author | reimar |
---|---|
date | Sat, 08 Jan 2005 21:34:06 +0000 |
parents | 8380694ba14f |
children | 408dfb63ff95 |
comparison
equal
deleted
inserted
replaced
14432:275b2ce30af7 | 14433:95bb94a930a3 |
---|---|
522 int t = s->input.bps*s->input.nch; | 522 int t = s->input.bps*s->input.nch; |
523 af_instance_t* af=s->first; | 523 af_instance_t* af=s->first; |
524 register frac_t mul = {1,1}; | 524 register frac_t mul = {1,1}; |
525 // Iterate through all filters | 525 // Iterate through all filters |
526 do{ | 526 do{ |
527 mul.n *= af->mul.n; | 527 af_frac_mul(&mul, &af->mul); |
528 mul.d *= af->mul.d; | |
529 af=af->next; | 528 af=af->next; |
530 }while(af); | 529 }while(af); |
531 return t * (((len/t)*mul.n + 1)/mul.d); | 530 return t * (((len/t)*mul.n + 1)/mul.d); |
532 } | 531 } |
533 | 532 |
540 int t = s->input.bps*s->input.nch; | 539 int t = s->input.bps*s->input.nch; |
541 af_instance_t* af=s->first; | 540 af_instance_t* af=s->first; |
542 register frac_t mul = {1,1}; | 541 register frac_t mul = {1,1}; |
543 // Iterate through all filters | 542 // Iterate through all filters |
544 do{ | 543 do{ |
545 mul.n *= af->mul.n; | 544 af_frac_mul(&mul, &af->mul); |
546 mul.d *= af->mul.d; | |
547 af=af->next; | 545 af=af->next; |
548 }while(af); | 546 }while(af); |
549 return t * (((len/t) * mul.d - 1)/mul.n); | 547 return t * (((len/t) * mul.d - 1)/mul.n); |
550 } | 548 } |
551 | 549 |
565 int out = 0; | 563 int out = 0; |
566 af_instance_t* af=s->first; | 564 af_instance_t* af=s->first; |
567 register frac_t mul = {1,1}; | 565 register frac_t mul = {1,1}; |
568 // Iterate through all filters and calculate total multiplication factor | 566 // Iterate through all filters and calculate total multiplication factor |
569 do{ | 567 do{ |
570 mul.n *= af->mul.n; | 568 af_frac_mul(&mul, &af->mul); |
571 mul.d *= af->mul.d; | |
572 af=af->next; | 569 af=af->next; |
573 }while(af); | 570 }while(af); |
574 // Sanity check | 571 // Sanity check |
575 if(!mul.n || !mul.d) | 572 if(!mul.n || !mul.d) |
576 return -1; | 573 return -1; |
643 filt = filt->prev; | 640 filt = filt->prev; |
644 } | 641 } |
645 return NULL; | 642 return NULL; |
646 } | 643 } |
647 | 644 |
645 /** | |
646 * \brief calculate greatest common divisior of a and b. | |
647 * Extended for negative and 0 values. If both are 0 the result is 1. | |
648 * The sign of the result will be so that it has the same sign as b. | |
649 */ | |
650 int af_gcd(register int a, register int b) { | |
651 int b_org = b; | |
652 while (b != 0) { | |
653 a %= b; | |
654 if (a == 0) | |
655 break; | |
656 b %= a; | |
657 } | |
658 // the result is either in a or b. As the other one is 0 just add them. | |
659 a += b; | |
660 if (!a) | |
661 return 1; | |
662 if (a * b_org < 0) | |
663 return -a; | |
664 return a; | |
665 } | |
666 | |
667 /** | |
668 * \brief cancel down a fraction f | |
669 */ | |
670 void af_frac_cancel(frac_t *f) { | |
671 int gcd = af_gcd(f->n, f->d); | |
672 f->n /= gcd; | |
673 f->d /= gcd; | |
674 } | |
675 | |
676 /** | |
677 * \brief multiply out by in and store result in out. | |
678 * the resulting fraction wil be cancelled down | |
679 * if in and out were. | |
680 */ | |
681 void af_frac_mul(frac_t *out, const frac_t *in) { | |
682 int gcd1 = af_gcd(out->n, in->d); | |
683 int gcd2 = af_gcd(in->n, out->d); | |
684 out->n = (out->n / gcd1) * (in->n / gcd2); | |
685 out->d = (out->d / gcd2) * (in->d / gcd1); | |
686 } | |
687 | |
648 void af_help (void) { | 688 void af_help (void) { |
649 int i = 0; | 689 int i = 0; |
650 af_msg(AF_MSG_INFO, "Available audio filters:\n"); | 690 af_msg(AF_MSG_INFO, "Available audio filters:\n"); |
651 while (filter_list[i]) { | 691 while (filter_list[i]) { |
652 if (filter_list[i]->comment && filter_list[i]->comment[0]) | 692 if (filter_list[i]->comment && filter_list[i]->comment[0]) |