mirror of
https://github.com/mpv-player/mpv
synced 2025-01-18 13:14:36 +00:00
New auto config for volume and resample and added support for float flag in configuration
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8868 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
61a46b242b
commit
e1718bed19
@ -69,6 +69,10 @@ extern int* af_cpu_speed;
|
||||
#define AF_INIT_FORCE 0x00000003
|
||||
#define AF_INIT_TYPE_MASK 0x00000003
|
||||
|
||||
#define AF_INIT_INT 0x00000000
|
||||
#define AF_INIT_FLOAT 0x00000010
|
||||
#define AF_INIT_FORMAT_MASK 0x00000010
|
||||
|
||||
// Default init type
|
||||
#ifndef AF_INIT_TYPE
|
||||
#if defined(HAVE_SSE) || defined(HAVE_3DNOW)
|
||||
|
@ -34,9 +34,15 @@
|
||||
#include "af_resample.h"
|
||||
|
||||
// Filtering types
|
||||
#define TYPE_LIN 0 // Linear interpolation
|
||||
#define TYPE_INT 1 // 16 bit integer
|
||||
#define TYPE_FLOAT 2 // 32 bit floating point
|
||||
#define RSMP_LIN (0<<0) // Linear interpolation
|
||||
#define RSMP_INT (1<<0) // 16 bit integer
|
||||
#define RSMP_FLOAT (2<<0) // 32 bit floating point
|
||||
#define RSMP_MASK (3<<0)
|
||||
|
||||
// Defines for sloppy or exact resampling
|
||||
#define FREQ_SLOPPY (0<<2)
|
||||
#define FREQ_EXACT (1<<2)
|
||||
#define FREQ_MASK (1<<2)
|
||||
|
||||
// Accuracy for linear interpolation
|
||||
#define STEPACCURACY 32
|
||||
@ -53,8 +59,7 @@ typedef struct af_resample_s
|
||||
uint32_t up; // Up sampling factor
|
||||
uint64_t step; // Step size for linear interpolation
|
||||
uint64_t pt; // Pointer remainder for linear interpolation
|
||||
int sloppy; // Enable sloppy resampling to reduce memory usage
|
||||
int type; // Filter type
|
||||
int setup; // Setup parameters cmdline or through postcreate
|
||||
} af_resample_t;
|
||||
|
||||
// Euclids algorithm for calculating Greatest Common Divisor GCD(a,b)
|
||||
@ -120,6 +125,55 @@ static int linint(af_data_t* c,af_data_t* l, af_resample_t* s)
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Determine resampling type and format */
|
||||
static int set_types(struct af_instance_s* af, af_data_t* data)
|
||||
{
|
||||
af_resample_t* s = af->setup;
|
||||
int rv = AF_OK;
|
||||
float rd = 0;
|
||||
|
||||
// Make sure this filter isn't redundant
|
||||
if((af->data->rate == data->rate) || (af->data->rate == 0))
|
||||
return AF_DETACH;
|
||||
|
||||
/* If sloppy and small resampling difference (2%) */
|
||||
rd = abs((float)af->data->rate - (float)data->rate)/(float)data->rate;
|
||||
if((((s->setup & FREQ_MASK) == FREQ_SLOPPY) && (rd < 0.02) &&
|
||||
(data->format != (AF_FORMAT_NE | AF_FORMAT_F))) ||
|
||||
((s->setup & RSMP_MASK) == RSMP_LIN)){
|
||||
s->setup = (s->setup & ~RSMP_MASK) | RSMP_LIN;
|
||||
af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
|
||||
af->data->bps = 2;
|
||||
af_msg(AF_MSG_VERBOSE,"[resample] Using linear interpolation. \n");
|
||||
}
|
||||
else{
|
||||
/* If the input format is float or if float is explicitly selected
|
||||
use float, otherwise use int */
|
||||
if((data->format == (AF_FORMAT_NE | AF_FORMAT_F)) ||
|
||||
((s->setup & RSMP_MASK) == RSMP_FLOAT)){
|
||||
s->setup = (s->setup & ~RSMP_MASK) | RSMP_FLOAT;
|
||||
af->data->format = AF_FORMAT_NE | AF_FORMAT_F;
|
||||
af->data->bps = 4;
|
||||
}
|
||||
else{
|
||||
s->setup = (s->setup & ~RSMP_MASK) | RSMP_INT;
|
||||
af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
|
||||
af->data->bps = 2;
|
||||
}
|
||||
af_msg(AF_MSG_VERBOSE,"[resample] Using %s processing and %s frequecy"
|
||||
" conversion.\n",
|
||||
((s->setup & RSMP_MASK) == RSMP_FLOAT)?"floating point":"integer",
|
||||
((s->setup & FREQ_MASK) == FREQ_SLOPPY)?"inexact":"exact");
|
||||
}
|
||||
|
||||
if(af->data->format != data->format || af->data->bps != data->bps)
|
||||
rv = AF_FALSE;
|
||||
data->format = af->data->format;
|
||||
data->bps = af->data->bps;
|
||||
af->data->nch = data->nch;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Initialization and runtime control
|
||||
static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
{
|
||||
@ -129,62 +183,34 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
af_data_t* n = (af_data_t*)arg; // New configureation
|
||||
int i,d = 0;
|
||||
int rv = AF_OK;
|
||||
size_t tsz = (s->type==TYPE_INT) ? sizeof(int16_t) : sizeof(float);
|
||||
|
||||
// Make sure this filter isn't redundant
|
||||
if((af->data->rate == n->rate) || (af->data->rate == 0))
|
||||
// Free space for circular bufers
|
||||
if(s->xq){
|
||||
for(i=1;i<af->data->nch;i++)
|
||||
if(s->xq[i])
|
||||
free(s->xq[i]);
|
||||
free(s->xq);
|
||||
}
|
||||
|
||||
if(AF_DETACH == (rv = set_types(af,n)))
|
||||
return AF_DETACH;
|
||||
|
||||
|
||||
// If linear interpolation
|
||||
if(s->type == TYPE_LIN){
|
||||
if((s->setup & RSMP_MASK) == RSMP_LIN){
|
||||
s->pt=0LL;
|
||||
s->step=((uint64_t)n->rate<<STEPACCURACY)/(uint64_t)af->data->rate+1LL;
|
||||
af_msg(AF_MSG_VERBOSE,"[resample] Linear interpolation step: 0x%016X.\n",
|
||||
af_msg(AF_MSG_DEBUG0,"[resample] Linear interpolation step: 0x%016X.\n",
|
||||
s->step);
|
||||
af->mul.n = af->data->rate;
|
||||
af->mul.d = n->rate;
|
||||
return AF_OK;
|
||||
}
|
||||
|
||||
// Create space for circular bufers (if nesessary)
|
||||
if((af->data->nch != n->nch) && (s->type != TYPE_LIN)){
|
||||
// First free the old ones
|
||||
if(s->xq){
|
||||
for(i=1;i<af->data->nch;i++)
|
||||
if(s->xq[i])
|
||||
free(s->xq[i]);
|
||||
free(s->xq);
|
||||
}
|
||||
// ... then create new
|
||||
s->xq = malloc(n->nch*sizeof(void*));
|
||||
for(i=0;i<n->nch;i++)
|
||||
s->xq[i] = malloc(2*L*tsz);
|
||||
s->xi = 0;
|
||||
}
|
||||
|
||||
// Set parameters
|
||||
af->data->nch = n->nch;
|
||||
if(s->type == TYPE_INT || s->type == TYPE_LIN){
|
||||
af->data->format = AF_FORMAT_NE | AF_FORMAT_SI;
|
||||
af->data->bps = 2;
|
||||
}
|
||||
else{
|
||||
af->data->format = AF_FORMAT_NE | AF_FORMAT_F;
|
||||
af->data->bps = 4;
|
||||
}
|
||||
if(af->data->format != n->format || af->data->bps != n->bps)
|
||||
rv = AF_FALSE;
|
||||
n->format = af->data->format;
|
||||
n->bps = af->data->bps;
|
||||
|
||||
// If linear interpolation is used the setup is done.
|
||||
if(s->type == TYPE_LIN)
|
||||
return rv;
|
||||
|
||||
// Calculate up and down sampling factors
|
||||
d=gcd(af->data->rate,n->rate);
|
||||
|
||||
// If sloppy resampling is enabled limit the upsampling factor
|
||||
if(s->sloppy && (af->data->rate/d > 5000)){
|
||||
if(((s->setup & FREQ_MASK) == FREQ_SLOPPY) && (af->data->rate/d > 5000)){
|
||||
int up=af->data->rate/2;
|
||||
int dn=n->rate/2;
|
||||
int m=2;
|
||||
@ -195,6 +221,12 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
d*=m;
|
||||
}
|
||||
|
||||
// Create space for circular bufers
|
||||
s->xq = malloc(n->nch*sizeof(void*));
|
||||
for(i=0;i<n->nch;i++)
|
||||
s->xq[i] = malloc(2*L*af->data->bps);
|
||||
s->xi = 0;
|
||||
|
||||
// Check if the the design needs to be redone
|
||||
if(s->up != af->data->rate/d || s->dn != n->rate/d){
|
||||
float* w;
|
||||
@ -210,7 +242,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
w = malloc(sizeof(float) * s->up *L);
|
||||
if(NULL != s->w)
|
||||
free(s->w);
|
||||
s->w = malloc(L*s->up*tsz);
|
||||
s->w = malloc(L*s->up*af->data->bps);
|
||||
|
||||
// Design prototype filter type using Kaiser window with beta = 10
|
||||
if(NULL == w || NULL == s->w ||
|
||||
@ -222,7 +254,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
wt=w;
|
||||
for(j=0;j<L;j++){//Columns
|
||||
for(i=0;i<s->up;i++){//Rows
|
||||
if(s->type == TYPE_INT){
|
||||
if((s->setup & RSMP_MASK) == RSMP_INT){
|
||||
float t=(float)s->up*32767.0*(*wt);
|
||||
((int16_t*)s->w)[i*L+j] = (int16_t)((t>=0.0)?(t+0.5):(t-0.5));
|
||||
}
|
||||
@ -245,15 +277,16 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
case AF_CONTROL_COMMAND_LINE:{
|
||||
af_resample_t* s = (af_resample_t*)af->setup;
|
||||
int rate=0;
|
||||
int lin=0;
|
||||
sscanf((char*)arg,"%i:%i:%i", &rate, &(s->sloppy), &lin);
|
||||
if(lin)
|
||||
s->type = TYPE_LIN;
|
||||
int type=RSMP_INT;
|
||||
int sloppy=1;
|
||||
sscanf((char*)arg,"%i:%i:%i", &rate, &type, &sloppy);
|
||||
s->setup = (sloppy?FREQ_SLOPPY:FREQ_EXACT) |
|
||||
(clamp(type,RSMP_LIN,RSMP_FLOAT));
|
||||
return af->control(af,AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &rate);
|
||||
}
|
||||
case AF_CONTROL_POST_CREATE:
|
||||
((af_resample_t*)af->setup)->type =
|
||||
((af_cfg_t*)arg)->force == AF_INIT_SLOW ? TYPE_INT : TYPE_FLOAT;
|
||||
if((((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT)
|
||||
((af_resample_t*)af->setup)->setup |= RSMP_FLOAT;
|
||||
return AF_OK;
|
||||
case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET:
|
||||
// Reinit must be called after this function has been called
|
||||
@ -293,8 +326,8 @@ static af_data_t* play(struct af_instance_s* af, af_data_t* data)
|
||||
return NULL;
|
||||
|
||||
// Run resampling
|
||||
switch(s->type){
|
||||
case(TYPE_INT):
|
||||
switch(s->setup & RSMP_MASK){
|
||||
case(RSMP_INT):
|
||||
# define FORMAT_I 1
|
||||
if(s->up>s->dn){
|
||||
# define UP
|
||||
@ -307,7 +340,7 @@ static af_data_t* play(struct af_instance_s* af, af_data_t* data)
|
||||
# undef DN
|
||||
}
|
||||
break;
|
||||
case(TYPE_FLOAT):
|
||||
case(RSMP_FLOAT):
|
||||
# undef FORMAT_I
|
||||
# define FORMAT_F 1
|
||||
if(s->up>s->dn){
|
||||
@ -321,7 +354,7 @@ static af_data_t* play(struct af_instance_s* af, af_data_t* data)
|
||||
# undef DN
|
||||
}
|
||||
break;
|
||||
case(TYPE_LIN):
|
||||
case(RSMP_LIN):
|
||||
len = linint(c, l, s);
|
||||
break;
|
||||
}
|
||||
@ -345,6 +378,7 @@ static int open(af_instance_t* af){
|
||||
af->setup=calloc(1,sizeof(af_resample_t));
|
||||
if(af->data == NULL || af->setup == NULL)
|
||||
return AF_ERROR;
|
||||
((af_resample_t*)af->setup)->setup = RSMP_INT | FREQ_SLOPPY;
|
||||
return AF_OK;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
af->data->rate = ((af_data_t*)arg)->rate;
|
||||
af->data->nch = ((af_data_t*)arg)->nch;
|
||||
|
||||
if(s->fast){
|
||||
if(s->fast && (((af_data_t*)arg)->format != (AF_FORMAT_F | AF_FORMAT_NE))){
|
||||
af->data->format = AF_FORMAT_SI | AF_FORMAT_NE;
|
||||
af->data->bps = 2;
|
||||
}
|
||||
@ -83,7 +83,8 @@ static int control(struct af_instance_s* af, int cmd, void* arg)
|
||||
return control(af,AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, vol);
|
||||
}
|
||||
case AF_CONTROL_POST_CREATE:
|
||||
s->fast = ((af_cfg_t*)arg)->force == AF_INIT_SLOW ? 1 : 0;
|
||||
s->fast = (((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) ==
|
||||
AF_INIT_FLOAT ? 1 : 0;
|
||||
return AF_OK;
|
||||
case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_SET:
|
||||
memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int));
|
||||
|
Loading…
Reference in New Issue
Block a user