summaryrefslogtreecommitdiffstats
path: root/libaf/af.c
diff options
context:
space:
mode:
authorreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-01-08 21:34:06 +0000
committerreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-01-08 21:34:06 +0000
commit8ee78e87ce7961a5b02762fd71c6e348198307fe (patch)
tree757423509666fb2bb9afd8b94674e001fac3ac6f /libaf/af.c
parentaae5663175bf24ff9a8a8ee5b01e46420f3f7357 (diff)
downloadmpv-8ee78e87ce7961a5b02762fd71c6e348198307fe.tar.bz2
mpv-8ee78e87ce7961a5b02762fd71c6e348198307fe.tar.xz
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) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@14434 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libaf/af.c')
-rw-r--r--libaf/af.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/libaf/af.c b/libaf/af.c
index 2165eb3baf..fa5963144f 100644
--- a/libaf/af.c
+++ b/libaf/af.c
@@ -524,8 +524,7 @@ int af_outputlen(af_stream_t* s, int len)
register frac_t mul = {1,1};
// Iterate through all filters
do{
- mul.n *= af->mul.n;
- mul.d *= af->mul.d;
+ af_frac_mul(&mul, &af->mul);
af=af->next;
}while(af);
return t * (((len/t)*mul.n + 1)/mul.d);
@@ -542,8 +541,7 @@ int af_inputlen(af_stream_t* s, int len)
register frac_t mul = {1,1};
// Iterate through all filters
do{
- mul.n *= af->mul.n;
- mul.d *= af->mul.d;
+ af_frac_mul(&mul, &af->mul);
af=af->next;
}while(af);
return t * (((len/t) * mul.d - 1)/mul.n);
@@ -567,8 +565,7 @@ int af_calc_insize_constrained(af_stream_t* s, int len,
register frac_t mul = {1,1};
// Iterate through all filters and calculate total multiplication factor
do{
- mul.n *= af->mul.n;
- mul.d *= af->mul.d;
+ af_frac_mul(&mul, &af->mul);
af=af->next;
}while(af);
// Sanity check
@@ -645,6 +642,49 @@ af_instance_t *af_control_any_rev (af_stream_t* s, int cmd, void* arg) {
return NULL;
}
+/**
+ * \brief calculate greatest common divisior of a and b.
+ * Extended for negative and 0 values. If both are 0 the result is 1.
+ * The sign of the result will be so that it has the same sign as b.
+ */
+int af_gcd(register int a, register int b) {
+ int b_org = b;
+ while (b != 0) {
+ a %= b;
+ if (a == 0)
+ break;
+ b %= a;
+ }
+ // the result is either in a or b. As the other one is 0 just add them.
+ a += b;
+ if (!a)
+ return 1;
+ if (a * b_org < 0)
+ return -a;
+ return a;
+}
+
+/**
+ * \brief cancel down a fraction f
+ */
+void af_frac_cancel(frac_t *f) {
+ int gcd = af_gcd(f->n, f->d);
+ f->n /= gcd;
+ f->d /= gcd;
+}
+
+/**
+ * \brief multiply out by in and store result in out.
+ * the resulting fraction wil be cancelled down
+ * if in and out were.
+ */
+void af_frac_mul(frac_t *out, const frac_t *in) {
+ int gcd1 = af_gcd(out->n, in->d);
+ int gcd2 = af_gcd(in->n, out->d);
+ out->n = (out->n / gcd1) * (in->n / gcd2);
+ out->d = (out->d / gcd2) * (in->d / gcd1);
+}
+
void af_help (void) {
int i = 0;
af_msg(AF_MSG_INFO, "Available audio filters:\n");