diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/filter/af.c | 9 | ||||
-rw-r--r-- | audio/filter/af.h | 5 | ||||
-rw-r--r-- | audio/filter/af_channels.c | 255 | ||||
-rw-r--r-- | audio/filter/af_equalizer.c | 215 | ||||
-rw-r--r-- | audio/filter/af_pan.c | 206 | ||||
-rw-r--r-- | audio/filter/af_volume.c | 188 |
6 files changed, 0 insertions, 878 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c index a76945feea..dd78bb0cb5 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -31,25 +31,16 @@ #include "af.h" // Static list of filters -extern const struct af_info af_info_channels; extern const struct af_info af_info_format; -extern const struct af_info af_info_volume; -extern const struct af_info af_info_equalizer; -extern const struct af_info af_info_pan; extern const struct af_info af_info_lavcac3enc; extern const struct af_info af_info_lavrresample; extern const struct af_info af_info_scaletempo; -extern const struct af_info af_info_bs2b; extern const struct af_info af_info_lavfi; extern const struct af_info af_info_lavfi_bridge; extern const struct af_info af_info_rubberband; static const struct af_info *const filter_list[] = { - &af_info_channels, &af_info_format, - &af_info_volume, - &af_info_equalizer, - &af_info_pan, &af_info_lavcac3enc, &af_info_lavrresample, #if HAVE_RUBBERBAND diff --git a/audio/filter/af.h b/audio/filter/af.h index f66b189f14..58f67727a2 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -120,11 +120,6 @@ struct af_stream { enum af_control { AF_CONTROL_REINIT = 1, AF_CONTROL_RESET, - AF_CONTROL_SET_VOLUME, - AF_CONTROL_SET_PAN_LEVEL, - AF_CONTROL_SET_PAN_NOUT, - AF_CONTROL_SET_PAN_BALANCE, - AF_CONTROL_GET_PAN_BALANCE, AF_CONTROL_SET_PLAYBACK_SPEED, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, AF_CONTROL_GET_METADATA, diff --git a/audio/filter/af_channels.c b/audio/filter/af_channels.c deleted file mode 100644 index 7cd7810d08..0000000000 --- a/audio/filter/af_channels.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Audio filter that adds and removes channels, according to the - * command line parameter channels. It is stupid and can only add - * silence or copy channels, not mix or filter. - * - * Original author: Anders - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> - -#include "common/common.h" -#include "af.h" - -#define FR 0 -#define TO 1 - -typedef struct af_channels_s{ - int route[AF_NCH][2]; - int nch, nr; - int router; - char *routes; -}af_channels_t; - -// Local function for copying data -static void copy(struct af_instance *af, void* in, void* out, - int ins, int inos,int outs, int outos, int len, int bps) -{ - switch(bps){ - case 1:{ - int8_t* tin = (int8_t*)in; - int8_t* tout = (int8_t*)out; - tin += inos; - tout += outos; - len = len/ins; - while(len--){ - *tout=*tin; - tin +=ins; - tout+=outs; - } - break; - } - case 2:{ - int16_t* tin = (int16_t*)in; - int16_t* tout = (int16_t*)out; - tin += inos; - tout += outos; - len = len/(2*ins); - while(len--){ - *tout=*tin; - tin +=ins; - tout+=outs; - } - break; - } - case 3:{ - int8_t* tin = (int8_t*)in; - int8_t* tout = (int8_t*)out; - tin += 3 * inos; - tout += 3 * outos; - len = len / ( 3 * ins); - while (len--) { - tout[0] = tin[0]; - tout[1] = tin[1]; - tout[2] = tin[2]; - tin += 3 * ins; - tout += 3 * outs; - } - break; - } - case 4:{ - int32_t* tin = (int32_t*)in; - int32_t* tout = (int32_t*)out; - tin += inos; - tout += outos; - len = len/(4*ins); - while(len--){ - *tout=*tin; - tin +=ins; - tout+=outs; - } - break; - } - case 8:{ - int64_t* tin = (int64_t*)in; - int64_t* tout = (int64_t*)out; - tin += inos; - tout += outos; - len = len/(8*ins); - while(len--){ - *tout=*tin; - tin +=ins; - tout+=outs; - } - break; - } - default: - MP_ERR(af, "Unsupported number of bytes/sample: %i" - " please report this error on the MPlayer mailing list. \n",bps); - } -} - -// Make sure the routes are sane -static int check_routes(struct af_instance *af, int nin, int nout) -{ - af_channels_t* s = af->priv; - int i; - if((s->nr < 1) || (s->nr > AF_NCH)){ - MP_ERR(af, "The number of routing pairs must be" - " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); - return AF_ERROR; - } - - for(i=0;i<s->nr;i++){ - if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){ - MP_ERR(af, "Invalid routing in pair nr. %i.\n", i); - return AF_ERROR; - } - } - return AF_OK; -} - -// Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) -{ - af_channels_t* s = af->priv; - switch(cmd){ - case AF_CONTROL_REINIT: ; - - struct mp_chmap chmap; - mp_chmap_set_unknown(&chmap, s->nch); - mp_audio_set_channels(af->data, &chmap); - - // Set default channel assignment - if(!s->router){ - int i; - // Make sure this filter isn't redundant - if(af->data->nch == ((struct mp_audio*)arg)->nch) - return AF_DETACH; - - // If mono: fake stereo - if(((struct mp_audio*)arg)->nch == 1){ - s->nr = MPMIN(af->data->nch,2); - for(i=0;i<s->nr;i++){ - s->route[i][FR] = 0; - s->route[i][TO] = i; - } - } - else{ - s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch); - for(i=0;i<s->nr;i++){ - s->route[i][FR] = i; - s->route[i][TO] = i; - } - } - } - - af->data->rate = ((struct mp_audio*)arg)->rate; - mp_audio_force_interleaved_format((struct mp_audio*)arg); - mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format); - return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch); - } - return AF_UNKNOWN; -} - -static int filter_frame(struct af_instance *af, struct mp_audio *c) -{ - af_channels_t* s = af->priv; - int i; - - if (!c) - return 0; - - struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples); - if (!l) { - talloc_free(c); - return -1; - } - mp_audio_copy_attributes(l, c); - - // Reset unused channels - memset(l->planes[0],0,mp_audio_psize(c) / c->nch * l->nch); - - if(AF_OK == check_routes(af,c->nch,l->nch)) - for(i=0;i<s->nr;i++) - copy(af, c->planes[0],l->planes[0],c->nch,s->route[i][FR], - l->nch,s->route[i][TO],mp_audio_psize(c),c->bps); - - talloc_free(c); - af_add_output_frame(af, l); - return 0; -} - -// Allocate memory and set function pointers -static int af_open(struct af_instance* af){ - af->control=control; - af->filter_frame = filter_frame; - af_channels_t *s = af->priv; - - MP_WARN(af, "This filter is deprecated (no replacement).\n"); - - // If router scan commandline for routing pairs - if(s->routes && s->routes[0]){ - char* cp = s->routes; - int ch = 0; - // Scan for pairs on commandline - do { - int n = 0; - if (ch >= AF_NCH) { - MP_FATAL(af, "Can't have more than %d routes.\n", AF_NCH); - return AF_ERROR; - } - sscanf(cp, "%i-%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); - MP_VERBOSE(af, "Routing from channel %i to" - " channel %i\n",s->route[ch][FR],s->route[ch][TO]); - cp = &cp[n]; - ch++; - } while(*cp == ',' && *(cp++)); - s->nr = ch; - if (s->nr > 0) - s->router = 1; - } - - return AF_OK; -} - -#define OPT_BASE_STRUCT af_channels_t -const struct af_info af_info_channels = { - .info = "Insert or remove channels", - .name = "channels", - .open = af_open, - .priv_size = sizeof(af_channels_t), - .options = (const struct m_option[]) { - OPT_INTRANGE("nch", nch, 0, 1, AF_NCH, OPTDEF_INT(2)), - OPT_STRING("routes", routes, 0), - {0} - }, -}; diff --git a/audio/filter/af_equalizer.c b/audio/filter/af_equalizer.c deleted file mode 100644 index 3f132fdc0c..0000000000 --- a/audio/filter/af_equalizer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Equalizer filter, implementation of a 10 band time domain graphic - * equalizer using IIR filters. The IIR filters are implemented using a - * Direct Form II approach, but has been modified (b1 == 0 always) to - * save computation. - * - * Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <inttypes.h> -#include <math.h> - -#include "common/common.h" -#include "af.h" - -#define L 2 // Storage for filter taps -#define KM 10 // Max number of bands - -#define Q 1.2247449 /* Q value for band-pass filters 1.2247=(3/2)^(1/2) - gives 4dB suppression @ Fc*2 and Fc/2 */ - -/* Center frequencies for band-pass filters - The different frequency bands are: - nr. center frequency - 0 31.25 Hz - 1 62.50 Hz - 2 125.0 Hz - 3 250.0 Hz - 4 500.0 Hz - 5 1.000 kHz - 6 2.000 kHz - 7 4.000 kHz - 8 8.000 kHz - 9 16.00 kHz -*/ -#define CF {31.25,62.5,125,250,500,1000,2000,4000,8000,16000} - -// Maximum and minimum gain for the bands -#define G_MAX +12.0 -#define G_MIN -12.0 - -// Data for specific instances of this filter -typedef struct af_equalizer_s -{ - float a[KM][L]; // A weights - float b[KM][L]; // B weights - float wq[AF_NCH][KM][L]; // Circular buffer for W data - float g[AF_NCH][KM]; // Gain factor for each channel and band - int K; // Number of used eq bands - int channels; // Number of channels - float gain_factor; // applied at output to avoid clipping - double p[KM]; -} af_equalizer_t; - -// 2nd order Band-pass Filter design -static void bp2(float* a, float* b, float fc, float q){ - double th= 2.0 * M_PI * fc; - double C = (1.0 - tan(th*q/2.0))/(1.0 + tan(th*q/2.0)); - - a[0] = (1.0 + C) * cos(th); - a[1] = -1 * C; - - b[0] = (1.0 - C)/2.0; - b[1] = -1.0050; -} - -// Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) -{ - af_equalizer_t* s = (af_equalizer_t*)af->priv; - - switch(cmd){ - case AF_CONTROL_REINIT:{ - int k =0, i =0; - float F[KM] = CF; - - s->gain_factor=0.0; - - // Sanity check - if(!arg) return AF_ERROR; - - mp_audio_copy_config(af->data, (struct mp_audio*)arg); - mp_audio_set_format(af->data, AF_FORMAT_FLOAT); - - // Calculate number of active filters - s->K=KM; - while(F[s->K-1] > (float)af->data->rate/2.2) - s->K--; - - if(s->K != KM) - MP_INFO(af, "Limiting the number of filters to" - " %i due to low sample rate.\n",s->K); - - // Generate filter taps - for(k=0;k<s->K;k++) - bp2(s->a[k],s->b[k],F[k]/((float)af->data->rate),Q); - - // Calculate how much this plugin adds to the overall time delay - af->delay = 2.0 / (double)af->data->rate; - - // Calculate gain factor to prevent clipping at output - for(k=0;k<AF_NCH;k++) - { - for(i=0;i<KM;i++) - { - if(s->gain_factor < s->g[k][i]) s->gain_factor=s->g[k][i]; - } - } - - s->gain_factor=log10(s->gain_factor + 1.0) * 20.0; - - if(s->gain_factor > 0.0) - { - s->gain_factor=0.1+(s->gain_factor/12.0); - }else{ - s->gain_factor=1; - } - - return af_test_output(af,arg); - } - } - return AF_UNKNOWN; -} - -static int filter(struct af_instance* af, struct mp_audio* data) -{ - struct mp_audio* c = data; // Current working data - if (!c) - return 0; - af_equalizer_t* s = (af_equalizer_t*)af->priv; // Setup - uint32_t ci = af->data->nch; // Index for channels - uint32_t nch = af->data->nch; // Number of channels - - if (af_make_writeable(af, data) < 0) { - talloc_free(data); - return -1; - } - - while(ci--){ - float* g = s->g[ci]; // Gain factor - float* in = ((float*)c->planes[0])+ci; - float* out = ((float*)c->planes[0])+ci; - float* end = in + c->samples*c->nch; // Block loop end - - while(in < end){ - register int k = 0; // Frequency band index - register float yt = *in; // Current input sample - in+=nch; - - // Run the filters - for(;k<s->K;k++){ - // Pointer to circular buffer wq - register float* wq = s->wq[ci][k]; - // Calculate output from AR part of current filter - register float w=yt*s->b[k][0] + wq[0]*s->a[k][0] + wq[1]*s->a[k][1]; - // Calculate output form MA part of current filter - yt+=(w + wq[1]*s->b[k][1])*g[k]; - // Update circular buffer - wq[1] = wq[0]; - wq[0] = w; - } - // Calculate output - *out=yt*s->gain_factor; - out+=nch; - } - } - af_add_output_frame(af, data); - return 0; -} - -// Allocate memory and set function pointers -static int af_open(struct af_instance* af){ - MP_WARN(af, "This filter is deprecated. Use 'anequalizer' or 'firequalizer' instead.\n"); - af->control=control; - af->filter_frame = filter; - af_equalizer_t *priv = af->priv; - for(int i=0;i<AF_NCH;i++){ - for(int j=0;j<KM;j++){ - priv->g[i][j] = pow(10.0,MPCLAMP(priv->p[j],G_MIN,G_MAX)/20.0)-1.0; - } - } - return AF_OK; -} - -#define OPT_BASE_STRUCT af_equalizer_t -const struct af_info af_info_equalizer = { - .info = "Equalizer audio filter", - .name = "equalizer", - .open = af_open, - .priv_size = sizeof(af_equalizer_t), - .options = (const struct m_option[]) { -#define BAND(n) OPT_DOUBLE("e" #n, p[n], 0) - BAND(0), BAND(1), BAND(2), BAND(3), BAND(4), - BAND(5), BAND(6), BAND(7), BAND(8), BAND(9), - {0} - }, -}; diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c deleted file mode 100644 index b2233a7191..0000000000 --- a/audio/filter/af_pan.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <inttypes.h> -#include <math.h> -#include <limits.h> - -#include "common/common.h" -#include "af.h" - -// Data for specific instances of this filter -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) -{ - struct mp_chmap map; - // "unknown" channel layouts make it easier to pass through audio data, - // without triggering remixing. - mp_chmap_set_unknown(&map, num); - mp_audio_set_channels(mpa, &map); -} - -static void parse_matrix(struct af_instance *af, const char *cp) -{ - af_pan_t *s = af->priv; - int j = 0, k = 0, n; - while (*cp && k < AF_NCH) { - sscanf(cp, "%f%n" , &s->level[j][k], &n); - MP_VERBOSE(af, "Pan level from channel %i to" - " channel %i = %f\n", k, j, s->level[j][k]); - cp = &cp[n]; - j++; - if (j >= s->nch) { - j = 0; - k++; - } - if (*cp != ',') - break; - cp++; - } - -} - -// Initialization and runtime control -static int control(struct af_instance *af, int cmd, void *arg) -{ - af_pan_t* s = af->priv; - - switch(cmd){ - case AF_CONTROL_REINIT: - // Sanity check - if (!arg) - return AF_ERROR; - - af->data->rate = ((struct mp_audio*)arg)->rate; - mp_audio_set_format(af->data, AF_FORMAT_FLOAT); - set_channels(af->data, s->nch ? s->nch : ((struct mp_audio*)arg)->nch); - - if ((af->data->format != ((struct mp_audio*)arg)->format) || - (af->data->bps != ((struct mp_audio*)arg)->bps)) { - mp_audio_set_format((struct mp_audio*)arg, af->data->format); - return AF_FALSE; - } - return AF_OK; - case AF_CONTROL_SET_PAN_LEVEL: { - int i; - int ch = ((af_control_ext_t*)arg)->ch; - float *level = ((af_control_ext_t*)arg)->arg; - if (ch >= AF_NCH) - return AF_FALSE; - for (i = 0; i < AF_NCH; i++) - s->level[ch][i] = level[i]; - return AF_OK; - } - case AF_CONTROL_SET_PAN_NOUT: - // Reinit must be called after this function has been called - // Sanity check - if (((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH) { - MP_ERR(af, "The number of output channels must be" - " between 1 and %i. Current value is %i\n", - AF_NCH, ((int*)arg)[0]); - return AF_ERROR; - } - s->nch = ((int*)arg)[0]; - return AF_OK; - case AF_CONTROL_SET_PAN_BALANCE: { - float val = *(float*)arg; - if (s->nch) - return AF_ERROR; - if (af->data->nch >= 2) { - s->level[0][0] = MPMIN(1.f, 1.f - val); - s->level[0][1] = MPMAX(0.f, val); - s->level[1][0] = MPMAX(0.f, -val); - s->level[1][1] = MPMIN(1.f, 1.f + val); - } - return AF_OK; - } - case AF_CONTROL_GET_PAN_BALANCE: - if (s->nch) - return AF_ERROR; - *(float*)arg = s->level[0][1] - s->level[1][0]; - return AF_OK; - case AF_CONTROL_COMMAND: { - char **args = arg; - if (!strcmp(args[0], "set-matrix")) { - parse_matrix(af, args[1]); - return CONTROL_OK; - } else { - return CONTROL_ERROR; - } - } - } - return AF_UNKNOWN; -} - -static int filter_frame(struct af_instance *af, struct mp_audio *c) -{ - if (!c) - return 0; - struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples); - if (!l) { - talloc_free(c); - return -1; - } - mp_audio_copy_attributes(l, c); - - 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 - int nchi = c->nch; // Number of input channels - int ncho = l->nch; // Number of output channels - register int j, k; - - out = l->planes[0]; - // Execute panning - // FIXME: Too slow - while (in < end) { - for (j = 0; j < ncho; j++) { - register float x = 0.0; - register float *tin = in; - for (k = 0; k < nchi; k++) - x += tin[k] * s->level[j][k]; - out[j] = x; - } - out += ncho; - in += nchi; - } - - talloc_free(c); - af_add_output_frame(af, l); - return 0; -} - -// Allocate memory and set function pointers -static int af_open(struct af_instance *af) -{ - af->control = control; - af->filter_frame = filter_frame; - MP_WARN(af, "This filter is deprecated. Use lavfi pan instead.\n"); - af_pan_t *s = af->priv; - int nch = s->nch; - if (nch && AF_OK != control(af, AF_CONTROL_SET_PAN_NOUT, &nch)) - return AF_ERROR; - - // Read pan values - if (s->matrixstr) - parse_matrix(af, s->matrixstr); - return AF_OK; -} - -#define OPT_BASE_STRUCT af_pan_t -const 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} - }, -}; diff --git a/audio/filter/af_volume.c b/audio/filter/af_volume.c deleted file mode 100644 index 8fffc08853..0000000000 --- a/audio/filter/af_volume.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C)2002 Anders Johansson ajh@atri.curtin.edu.au - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <inttypes.h> -#include <math.h> -#include <limits.h> - -#include "common/common.h" -#include "af.h" -#include "demux/demux.h" - -struct priv { - float level; // User-specified gain level for each channel - float rgain; // Replaygain level - int rgain_track; // Enable/disable track based replaygain - int rgain_album; // Enable/disable album based replaygain - float rgain_preamp; // Set replaygain pre-amplification - int rgain_clip; // Enable/disable clipping prevention - float replaygain_fallback; - int soft; // Enable/disable soft clipping - int fast; // Use fix-point volume control - int detach; // Detach if gain volume is neutral - float cfg_volume; - int warn; -}; - -// Convert to gain value from dB. input <= -200dB will become 0 gain. -static float from_dB(float in, float k, float mi, float ma) -{ - if (in <= -200) - return 0.0; - return pow(10.0, MPCLAMP(in, mi, ma) / k); -} - -static int control(struct af_instance *af, int cmd, void *arg) -{ - struct priv *s = af->priv; - - switch (cmd) { - case AF_CONTROL_REINIT: { - struct mp_audio *in = arg; - - mp_audio_copy_config(af->data, in); - mp_audio_force_interleaved_format(af->data); - - if (s->fast && af_fmt_from_planar(in->format) != AF_FORMAT_FLOAT) { - mp_audio_set_format(af->data, AF_FORMAT_S16); - } else { - mp_audio_set_format(af->data, AF_FORMAT_FLOAT); - } - if (af_fmt_is_planar(in->format)) - mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format)); - s->rgain = 1.0; - struct replaygain_data *rg = af->replaygain_data; - if ((s->rgain_track || s->rgain_album) && rg) { - MP_VERBOSE(af, "Replaygain: Track=%f/%f Album=%f/%f\n", - rg->track_gain, rg->track_peak, - rg->album_gain, rg->album_peak); - - float gain, peak; - if (s->rgain_track) { - gain = rg->track_gain; - peak = rg->track_peak; - } else { - gain = rg->album_gain; - peak = rg->album_peak; - } - - gain += s->rgain_preamp; - s->rgain = from_dB(gain, 20.0, -200.0, 60.0); - - MP_VERBOSE(af, "Applying replay-gain: %f\n", s->rgain); - - if (!s->rgain_clip) { // clipping prevention - s->rgain = MPMIN(s->rgain, 1.0 / peak); - MP_VERBOSE(af, "...with clipping prevention: %f\n", s->rgain); - } - } else if (s->replaygain_fallback) { - s->rgain = from_dB(s->replaygain_fallback, 20.0, -200.0, 60.0); - MP_VERBOSE(af, "Applying fallback gain: %f\n", s->rgain); - } - if (s->detach && fabs(s->level * s->rgain - 1.0) < 0.00001) - return AF_DETACH; - return af_test_output(af, in); - } - case AF_CONTROL_SET_VOLUME: - s->level = *(float *)arg; - MP_VERBOSE(af, "volume gain: %f\n", s->level); - return AF_OK; - } - return AF_UNKNOWN; -} - -static void filter_plane(struct af_instance *af, struct mp_audio *data, int p) -{ - struct priv *s = af->priv; - - float level = s->level * s->rgain * from_dB(s->cfg_volume, 20.0, -200.0, 60.0); - int num_samples = data->samples * data->spf; - - if (af_fmt_from_planar(af->data->format) == AF_FORMAT_S16) { - int vol = 256.0 * level; - if (vol != 256) { - if (af_make_writeable(af, data) < 0) - return; // oom - int16_t *a = data->planes[p]; - for (int i = 0; i < num_samples; i++) { - int x = (a[i] * vol) >> 8; - a[i] = MPCLAMP(x, SHRT_MIN, SHRT_MAX); - } - } - } else if (af_fmt_from_planar(af->data->format) == AF_FORMAT_FLOAT) { - float vol = level; - if (vol != 1.0) { - if (af_make_writeable(af, data) < 0) - return; // oom - float *a = data->planes[p]; - for (int i = 0; i < num_samples; i++) { - float x = a[i] * vol; - a[i] = s->soft ? af_softclip(x) : MPCLAMP(x, -1.0, 1.0); - } - } - } -} - -static int filter(struct af_instance *af, struct mp_audio *data) -{ - if (data) { - for (int n = 0; n < data->num_planes; n++) - filter_plane(af, data, n); - af_add_output_frame(af, data); - } - return 0; -} - -static int af_open(struct af_instance *af) -{ - struct priv *s = af->priv; - if (s->warn) - MP_WARN(af, "This filter is deprecated. Use --volume directly.\n"); - af->control = control; - af->filter_frame = filter; - s->level = 1.0; - return AF_OK; -} - -#define OPT_BASE_STRUCT struct priv - -// Description of this filter -const struct af_info af_info_volume = { - .info = "Volume control audio filter", - .name = "volume", - .open = af_open, - .priv_size = sizeof(struct priv), - .options = (const struct m_option[]) { - OPT_FLOATRANGE("volumedb", cfg_volume, 0, -200, 60), - OPT_FLAG("replaygain-track", rgain_track, 0), - OPT_FLAG("replaygain-album", rgain_album, 0), - OPT_FLOATRANGE("replaygain-preamp", rgain_preamp, 0, -15, 15), - OPT_FLAG("replaygain-clip", rgain_clip, 0), - OPT_FLOATRANGE("replaygain-fallback", replaygain_fallback, 0, -200, 60), - OPT_FLAG("softclip", soft, 0), - OPT_FLAG("s16", fast, 0), - OPT_FLAG("detach", detach, 0), - OPT_FLAG("warn", warn, 0, OPTDEF_INT(1)), - {0} - }, -}; |