From 82983970b35ae52236106508e3941d4edc1b5fe8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 4 Dec 2013 23:01:45 +0100 Subject: af_pan: change options, use option parser Similar to af_channels etc... --- DOCS/man/en/af.rst | 22 ++++++++------ audio/filter/af_pan.c | 80 ++++++++++++++++++++++++--------------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/DOCS/man/en/af.rst b/DOCS/man/en/af.rst index 4df4b51ae0..52d2f7b478 100644 --- a/DOCS/man/en/af.rst +++ b/DOCS/man/en/af.rst @@ -296,7 +296,7 @@ Available filters are: Would amplify the sound by 10.1dB and hard-clip if the sound level is too high. -``pan=n[:L00:L01:L02:...L10:L11:L12:...Ln0:Ln1:Ln2:...]`` +``pan=n[:]`` Mixes channels arbitrarily. Basically a combination of the volume and the channels filter that can be used to down-mix many channels to only a few, e.g. stereo to mono, or vary the "width" of the center speaker in a @@ -308,19 +308,23 @@ Available filters are: ```` Number of output channels (1-8). - ```` - How much of input channel i is mixed into output channel j (0-1). So - in principle you first have n numbers saying what to do with the first - input channel, then n numbers that act on the second input channel - etc. If you do not specify any numbers for some input channels, 0 is - assumed. + ```` + A list of values ``[L00,L01,L02,...,L10,L11,L12,...,Ln0,Ln1,Ln2,...]``, + where each element ``Lij`` means how much of input channel i is mixed + into output channel j (range 0-1). So in principle you first have n + numbers saying what to do with the first input channel, then n numbers + that act on the second input channel etc. If you do not specify any + numbers for some input channels, 0 is assumed. + Note that the values are separated by ``,``, which is already used + by the option parser to separate filters. This is why you must quote + the value list with ``[...]`` or similar. .. admonition:: Examples - ``mpv --af=pan=1:0.5:0.5 media.avi`` + ``mpv --af=pan=1:[0.5,0.5] media.avi`` Would downmix from stereo to mono. - ``mpv --af=pan=3:1:0:0.5:0:1:0.5 media.avi`` + ``mpv --af=pan=3:[1,0,0.5,0,1,0.5] media.avi`` Would give 3 channel output leaving channels 0 and 1 intact, and mix channels 0 and 1 into output channel 2 (which could be sent to a subwoofer for example). diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c index f1bc63b73a..56e72ed557 100644 --- a/audio/filter/af_pan.c +++ b/audio/filter/af_pan.c @@ -33,6 +33,7 @@ typedef struct af_pan_s { int nch; // Number of output channels; zero means same as input float level[AF_NCH][AF_NCH]; // Gain level for each channel + char *matrixstr; }af_pan_t; static void set_channels(struct mp_audio *mpa, int num) @@ -47,7 +48,7 @@ static void set_channels(struct mp_audio *mpa, int num) // Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { - af_pan_t* s = af->setup; + af_pan_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT: @@ -64,32 +65,6 @@ static int control(struct af_instance* af, int cmd, void* arg) return AF_FALSE; } return AF_OK; - case AF_CONTROL_COMMAND_LINE:{ - int nch = 0; - int n = 0; - char* cp = NULL; - int j,k; - // Read number of outputs - sscanf((char*)arg,"%i%n", &nch,&n); - if(AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch)) - return AF_ERROR; - - // Read pan values - cp = &((char*)arg)[n]; - j = 0; k = 0; - while((*cp == ':') && (k < AF_NCH)){ - sscanf(cp, ":%f%n" , &s->level[j][k], &n); - mp_msg(MSGT_AFILTER, MSGL_V, "[pan] Pan level from channel %i to" - " channel %i = %f\n",k,j,s->level[j][k]); - cp =&cp[n]; - j++; - if(j>=nch){ - j = 0; - k++; - } - } - return AF_OK; - } case AF_CONTROL_SET_PAN_LEVEL:{ int i; int ch = ((af_control_ext_t*)arg)->ch; @@ -132,18 +107,12 @@ static int control(struct af_instance* af, int cmd, void* arg) return AF_UNKNOWN; } -// Deallocate memory -static void uninit(struct af_instance* af) -{ - free(af->setup); -} - // Filter data through filter static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* c = data; // Current working data struct mp_audio* l = af->data; // Local data - af_pan_t* s = af->setup; // Setup for this instance + af_pan_t* s = af->priv; // Setup for this instance float* in = c->planes[0]; // Input audio data float* out = NULL; // Output audio data float* end = in+c->samples*c->nch; // End of loop @@ -177,18 +146,45 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) // Allocate memory and set function pointers static int af_open(struct af_instance* af){ - af->control=control; - af->uninit=uninit; - af->play=play; - af->setup=calloc(1,sizeof(af_pan_t)); - if(af->setup == NULL) - return AF_ERROR; - return AF_OK; + af->control=control; + af->play=play; + af_pan_t *s = af->priv; + int n = 0; + int j,k; + + int nch = s->nch; + if(AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch)) + return AF_ERROR; + + // Read pan values + char *cp = s->matrixstr; + j = 0; k = 0; + while(k < AF_NCH){ + sscanf(cp, "%f%n" , &s->level[j][k], &n); + mp_msg(MSGT_AFILTER, MSGL_V, "[pan] Pan level from channel %i to" + " channel %i = %f\n",k,j,s->level[j][k]); + cp =&cp[n]; + j++; + if(j>=nch){ + j = 0; + k++; + } + if (*cp != ',') + break; + cp++; + } + return AF_OK; } -// Description of this filter +#define OPT_BASE_STRUCT af_pan_t struct af_info af_info_pan = { .info = "Panning audio filter", .name = "pan", .open = af_open, + .priv_size = sizeof(af_pan_t), + .options = (const struct m_option[]) { + OPT_INTRANGE("channels", nch, 0, 0, AF_NCH), + OPT_STRING("matrix", matrixstr, 0), + {0} + }, }; -- cgit v1.2.3