diff options
Diffstat (limited to 'libavfilter/af_compand.c')
-rw-r--r-- | libavfilter/af_compand.c | 138 |
1 files changed, 56 insertions, 82 deletions
diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c index a6692bc37f..deaaf4462c 100644 --- a/libavfilter/af_compand.c +++ b/libavfilter/af_compand.c @@ -5,20 +5,20 @@ * Copyright (c) 2013 Paul B Mahol * Copyright (c) 2014 Andrew Kelley * - * This file is part of libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,39 +27,33 @@ * audio compand filter */ -#include <string.h> - +#include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/channel_layout.h" -#include "libavutil/common.h" -#include "libavutil/mathematics.h" -#include "libavutil/mem.h" #include "libavutil/opt.h" +#include "libavutil/samplefmt.h" #include "audio.h" #include "avfilter.h" -#include "formats.h" #include "internal.h" typedef struct ChanParam { - float attack; - float decay; - float volume; + double attack; + double decay; + double volume; } ChanParam; typedef struct CompandSegment { - float x, y; - float a, b; + double x, y; + double a, b; } CompandSegment; typedef struct CompandContext { const AVClass *class; - int nb_channels; int nb_segments; char *attacks, *decays, *points; CompandSegment *segments; ChanParam *channels; - float in_min_lin; - float out_min_lin; + double in_min_lin; + double out_min_lin; double curve_dB; double gain_dB; double initial_volume; @@ -74,7 +68,7 @@ typedef struct CompandContext { } CompandContext; #define OFFSET(x) offsetof(CompandContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption compand_options[] = { { "attacks", "set time over which increase of volume is determined", OFFSET(attacks), AV_OPT_TYPE_STRING, { .str = "0.3" }, 0, 0, A }, @@ -87,12 +81,7 @@ static const AVOption compand_options[] = { { NULL } }; -static const AVClass compand_class = { - .class_name = "compand filter", - .item_name = av_default_item_name, - .option = compand_options, - .version = LIBAVUTIL_VERSION_INT, -}; +AVFILTER_DEFINE_CLASS(compand); static av_cold int init(AVFilterContext *ctx) { @@ -115,7 +104,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterChannelLayouts *layouts; AVFilterFormats *formats; static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; @@ -143,14 +132,14 @@ static void count_items(char *item_str, int *nb_items) *nb_items = 1; for (p = item_str; *p; p++) { - if (*p == '|') + if (*p == ' ' || *p == '|') (*nb_items)++; } } -static void update_volume(ChanParam *cp, float in) +static void update_volume(ChanParam *cp, double in) { - float delta = in - cp->volume; + double delta = in - cp->volume; if (delta > 0.0) cp->volume += delta * cp->attack; @@ -158,16 +147,16 @@ static void update_volume(ChanParam *cp, float in) cp->volume += delta * cp->decay; } -static float get_volume(CompandContext *s, float in_lin) +static double get_volume(CompandContext *s, double in_lin) { CompandSegment *cs; - float in_log, out_log; + double in_log, out_log; int i; if (in_lin < s->in_min_lin) return s->out_min_lin; - in_log = logf(in_lin); + in_log = log(in_lin); for (i = 1; i < s->nb_segments; i++) if (in_log <= s->segments[i].x) @@ -176,14 +165,14 @@ static float get_volume(CompandContext *s, float in_lin) in_log -= cs->x; out_log = cs->y + in_log * (cs->a * in_log + cs->b); - return expf(out_log); + return exp(out_log); } static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame) { CompandContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const int channels = s->nb_channels; + const int channels = inlink->channels; const int nb_samples = frame->nb_samples; AVFrame *out_frame; int chan, i; @@ -206,14 +195,14 @@ static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame) } for (chan = 0; chan < channels; chan++) { - const float *src = (float *)frame->extended_data[chan]; - float *dst = (float *)out_frame->extended_data[chan]; + const double *src = (double *)frame->extended_data[chan]; + double *dst = (double *)out_frame->extended_data[chan]; ChanParam *cp = &s->channels[chan]; for (i = 0; i < nb_samples; i++) { update_volume(cp, fabs(src[i])); - dst[i] = av_clipf(src[i] * get_volume(s, cp->volume), -1.0f, 1.0f); + dst[i] = av_clipd(src[i] * get_volume(s, cp->volume), -1, 1); } } @@ -229,9 +218,9 @@ static int compand_delay(AVFilterContext *ctx, AVFrame *frame) { CompandContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const int channels = s->nb_channels; + const int channels = inlink->channels; const int nb_samples = frame->nb_samples; - int chan, i, dindex = 0, oindex, count = 0; + int chan, i, av_uninit(dindex), oindex, av_uninit(count); AVFrame *out_frame = NULL; int err; @@ -239,17 +228,19 @@ static int compand_delay(AVFilterContext *ctx, AVFrame *frame) s->pts = (frame->pts == AV_NOPTS_VALUE) ? 0 : frame->pts; } + av_assert1(channels > 0); /* would corrupt delay_count and delay_index */ + for (chan = 0; chan < channels; chan++) { AVFrame *delay_frame = s->delay_frame; - const float *src = (float *)frame->extended_data[chan]; - float *dbuf = (float *)delay_frame->extended_data[chan]; + const double *src = (double *)frame->extended_data[chan]; + double *dbuf = (double *)delay_frame->extended_data[chan]; ChanParam *cp = &s->channels[chan]; - float *dst; + double *dst; count = s->delay_count; dindex = s->delay_index; for (i = 0, oindex = 0; i < nb_samples; i++) { - const float in = src[i]; + const double in = src[i]; update_volume(cp, fabs(in)); if (count >= s->delay_samples) { @@ -271,9 +262,9 @@ static int compand_delay(AVFilterContext *ctx, AVFrame *frame) inlink->time_base); } - dst = (float *)out_frame->extended_data[chan]; - dst[oindex++] = av_clipf(dbuf[dindex] * - get_volume(s, cp->volume), -1.0f, 1.0f); + dst = (double *)out_frame->extended_data[chan]; + dst[oindex++] = av_clipd(dbuf[dindex] * + get_volume(s, cp->volume), -1, 1); } else { count++; } @@ -294,7 +285,7 @@ static int compand_drain(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; CompandContext *s = ctx->priv; - const int channels = s->nb_channels; + const int channels = outlink->channels; AVFrame *frame = NULL; int chan, i, dindex; @@ -308,14 +299,14 @@ static int compand_drain(AVFilterLink *outlink) for (chan = 0; chan < channels; chan++) { AVFrame *delay_frame = s->delay_frame; - float *dbuf = (float *)delay_frame->extended_data[chan]; - float *dst = (float *)frame->extended_data[chan]; + double *dbuf = (double *)delay_frame->extended_data[chan]; + double *dst = (double *)frame->extended_data[chan]; ChanParam *cp = &s->channels[chan]; dindex = s->delay_index; for (i = 0; i < frame->nb_samples; i++) { - dst[i] = av_clipf(dbuf[dindex] * get_volume(s, cp->volume), - -1.0f, 1.0f); + dst[i] = av_clipd(dbuf[dindex] * get_volume(s, cp->volume), + -1, 1); dindex = MOD(dindex + 1, s->delay_samples); } } @@ -331,9 +322,8 @@ static int config_output(AVFilterLink *outlink) CompandContext *s = ctx->priv; const int sample_rate = outlink->sample_rate; double radius = s->curve_dB * M_LN10 / 20.0; - const char *p; - const int channels = - av_get_channel_layout_nb_channels(outlink->channel_layout); + char *p, *saveptr = NULL; + const int channels = outlink->channels; int nb_attacks, nb_decays, nb_points; int new_nb_items, num; int i; @@ -357,7 +347,6 @@ static int config_output(AVFilterLink *outlink) uninit(ctx); - s->nb_channels = channels; s->channels = av_mallocz_array(channels, sizeof(*s->channels)); s->nb_segments = (nb_points + 4) * 2; s->segments = av_mallocz_array(s->nb_segments, sizeof(*s->segments)); @@ -369,34 +358,25 @@ static int config_output(AVFilterLink *outlink) p = s->attacks; for (i = 0, new_nb_items = 0; i < nb_attacks; i++) { - char *tstr = av_get_token(&p, "|"); - if (!tstr) - return AVERROR(ENOMEM); - - new_nb_items += sscanf(tstr, "%f", &s->channels[i].attack) == 1; - av_freep(&tstr); + char *tstr = av_strtok(p, " |", &saveptr); + p = NULL; + new_nb_items += sscanf(tstr, "%lf", &s->channels[i].attack) == 1; if (s->channels[i].attack < 0) { uninit(ctx); return AVERROR(EINVAL); } - if (*p) - p++; } nb_attacks = new_nb_items; p = s->decays; for (i = 0, new_nb_items = 0; i < nb_decays; i++) { - char *tstr = av_get_token(&p, "|"); - if (!tstr) - return AVERROR(ENOMEM); - new_nb_items += sscanf(tstr, "%f", &s->channels[i].decay) == 1; - av_freep(&tstr); + char *tstr = av_strtok(p, " |", &saveptr); + p = NULL; + new_nb_items += sscanf(tstr, "%lf", &s->channels[i].decay) == 1; if (s->channels[i].decay < 0) { uninit(ctx); return AVERROR(EINVAL); } - if (*p) - p++; } nb_decays = new_nb_items; @@ -411,13 +391,9 @@ static int config_output(AVFilterLink *outlink) #define S(x) s->segments[2 * ((x) + 1)] p = s->points; for (i = 0, new_nb_items = 0; i < nb_points; i++) { - char *tstr = av_get_token(&p, "|"); - if (!tstr) - return AVERROR(ENOMEM); - - err = sscanf(tstr, "%f/%f", &S(i).x, &S(i).y); - av_freep(&tstr); - if (err != 2) { + char *tstr = av_strtok(p, " |", &saveptr); + p = NULL; + if (sscanf(tstr, "%lf/%lf", &S(i).x, &S(i).y) != 2) { av_log(ctx, AV_LOG_ERROR, "Invalid and/or missing input/output value.\n"); uninit(ctx); @@ -432,8 +408,6 @@ static int config_output(AVFilterLink *outlink) S(i).y -= S(i).x; av_log(ctx, AV_LOG_DEBUG, "%d: x=%f y=%f\n", i, S(i).x, S(i).y); new_nb_items++; - if (*p) - p++; } num = new_nb_items; @@ -454,7 +428,6 @@ static int config_output(AVFilterLink *outlink) double g2 = (S(i - 0).y - S(i - 1).y) * (S(i - 1).x - S(i - 2).x); int j; - /* here we purposefully lose precision so that we can compare floats */ if (fabs(g1 - g2)) continue; num--; @@ -543,6 +516,7 @@ static int config_output(AVFilterLink *outlink) if (err) return err; + outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP; s->compand = compand_delay; return 0; } @@ -563,7 +537,7 @@ static int request_frame(AVFilterLink *outlink) ret = ff_request_frame(ctx->inputs[0]); - if (ret == AVERROR_EOF && s->delay_count) + if (ret == AVERROR_EOF && !ctx->is_disabled && s->delay_count) ret = compand_drain(outlink); return ret; |