mirror of
https://github.com/mpv-player/mpv
synced 2025-01-11 09:29:29 +00:00
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
This commit is contained in:
parent
aae5663175
commit
8ee78e87ce
52
libaf/af.c
52
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");
|
||||
|
@ -28,6 +28,10 @@ typedef struct frac_s
|
||||
int d; // Denominator
|
||||
} frac_t;
|
||||
|
||||
int af_gcd(register int a, register int b);
|
||||
void af_frac_cancel(frac_t *f);
|
||||
void af_frac_mul(frac_t *out, const frac_t *in);
|
||||
|
||||
// Flags used for defining the behavior of an audio filter
|
||||
#define AF_FLAGS_REENTRANT 0x00000000
|
||||
#define AF_FLAGS_NOT_REENTRANT 0x00000001
|
||||
|
@ -151,6 +151,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
af->data->bps = ((af_data_t*)arg)->bps;
|
||||
af->mul.n = af->data->nch;
|
||||
af->mul.d = ((af_data_t*)arg)->nch;
|
||||
af_frac_cancel(&af->mul);
|
||||
return check_routes(s,((af_data_t*)arg)->nch,af->data->nch);
|
||||
case AF_CONTROL_COMMAND_LINE:{
|
||||
int nch = 0;
|
||||
|
@ -306,6 +306,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
af->data->nch = ((af_data_t*)arg)->nch;
|
||||
af->mul.n = af->data->bps;
|
||||
af->mul.d = ((af_data_t*)arg)->bps;
|
||||
af_frac_cancel(&af->mul);
|
||||
|
||||
af->play = play; // set default
|
||||
|
||||
|
@ -40,7 +40,6 @@ typedef struct af_resample_s{
|
||||
// Initialization and runtime control
|
||||
static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
{
|
||||
int g;
|
||||
af_resample_t* s = (af_resample_t*)af->setup;
|
||||
af_data_t *data= (af_data_t*)arg;
|
||||
int out_rate, test_output_res; // helpers for checking input format
|
||||
@ -54,9 +53,9 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
if (af->data->nch > CHANS) af->data->nch = CHANS;
|
||||
af->data->format = AF_FORMAT_S16_NE;
|
||||
af->data->bps = 2;
|
||||
g= ff_gcd(af->data->rate, data->rate);
|
||||
af->mul.n = af->data->rate/g;
|
||||
af->mul.d = data->rate/g;
|
||||
af->mul.n = af->data->rate;
|
||||
af->mul.d = data->rate;
|
||||
af_frac_cancel(&af->mul);
|
||||
af->delay = 500*s->filter_length/(double)min(af->data->rate, data->rate);
|
||||
|
||||
if(s->avrctx) av_resample_close(s->avrctx);
|
||||
|
@ -41,6 +41,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
af->data->bps = 4;
|
||||
af->mul.n = af->data->nch;
|
||||
af->mul.d = ((af_data_t*)arg)->nch;
|
||||
af_frac_cancel(&af->mul);
|
||||
|
||||
if((af->data->format != ((af_data_t*)arg)->format) ||
|
||||
(af->data->bps != ((af_data_t*)arg)->bps)){
|
||||
|
@ -62,22 +62,6 @@ typedef struct af_resample_s
|
||||
int setup; // Setup parameters cmdline or through postcreate
|
||||
} af_resample_t;
|
||||
|
||||
// Euclids algorithm for calculating Greatest Common Divisor GCD(a,b)
|
||||
static inline int gcd(register int a, register int b)
|
||||
{
|
||||
register int r = min(a,b);
|
||||
a=max(a,b);
|
||||
b=r;
|
||||
|
||||
r=a%b;
|
||||
while(r!=0){
|
||||
a=b;
|
||||
b=r;
|
||||
r=a%b;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// Fast linear interpolation resample with modest audio quality
|
||||
static int linint(af_data_t* c,af_data_t* l, af_resample_t* s)
|
||||
{
|
||||
@ -202,11 +186,12 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
s->step);
|
||||
af->mul.n = af->data->rate;
|
||||
af->mul.d = n->rate;
|
||||
af_frac_cancel(&af->mul);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Calculate up and down sampling factors
|
||||
d=gcd(af->data->rate,n->rate);
|
||||
d=af_gcd(af->data->rate,n->rate);
|
||||
|
||||
// If sloppy resampling is enabled limit the upsampling factor
|
||||
if(((s->setup & FREQ_MASK) == FREQ_SLOPPY) && (af->data->rate/d > 5000)){
|
||||
@ -214,7 +199,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
int dn=n->rate/2;
|
||||
int m=2;
|
||||
while(af->data->rate/(d*m) > 5000){
|
||||
d=gcd(up,dn);
|
||||
d=af_gcd(up,dn);
|
||||
up/=2; dn/=2; m*=2;
|
||||
}
|
||||
d*=m;
|
||||
|
Loading…
Reference in New Issue
Block a user