Created
February 9, 2014 01:25
-
-
Save andrewrk/8892851 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- /home/andy/dev/ffmpeg/libavfilter/af_compand.c 2014-02-02 12:07:39.789987354 -0500 | |
+++ /home/andy/dev/libav/libavfilter/af_compand.c 2014-02-08 16:50:46.428038489 -0500 | |
@@ -3,8 +3,9 @@ | |
* Copyright (c) 1999 Nick Bailey | |
* Copyright (c) 2007 Rob Sykes <robs@users.sourceforge.net> | |
* Copyright (c) 2013 Paul B Mahol | |
+ * Copyright (c) 2014 Andrew Kelley | |
* | |
- * This file is part of FFmpeg. | |
+ * This file is part of libav. | |
* | |
* FFmpeg is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
@@ -22,12 +23,20 @@ | |
* | |
*/ | |
+/** | |
+ * @file | |
+ * audio compand filter | |
+ */ | |
+ | |
+#include "libavutil/mem.h" | |
#include "libavutil/avassert.h" | |
-#include "libavutil/avstring.h" | |
+#include "libavutil/mathematics.h" | |
+#include "libavutil/channel_layout.h" | |
#include "libavutil/opt.h" | |
-#include "libavutil/samplefmt.h" | |
-#include "avfilter.h" | |
+#include "libavutil/common.h" | |
#include "audio.h" | |
+#include "avfilter.h" | |
+#include "formats.h" | |
#include "internal.h" | |
typedef struct ChanParam { | |
@@ -62,7 +71,7 @@ | |
} CompandContext; | |
#define OFFSET(x) offsetof(CompandContext, x) | |
-#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | |
+#define A AV_OPT_FLAG_AUDIO_PARAM | |
static const AVOption compand_options[] = { | |
{ "attacks", "set time over which increase of volume is determined", OFFSET(attacks), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A }, | |
@@ -75,7 +84,12 @@ | |
{ NULL } | |
}; | |
-AVFILTER_DEFINE_CLASS(compand); | |
+static const AVClass compand_class = { | |
+ .class_name = "compand filter", | |
+ .item_name = av_default_item_name, | |
+ .option = compand_options, | |
+ .version = LIBAVUTIL_VERSION_INT, | |
+}; | |
static av_cold int init(AVFilterContext *ctx) | |
{ | |
@@ -171,11 +185,26 @@ | |
return exp(out_log); | |
} | |
+/** | |
+ * Clip a double value into the amin-amax range. | |
+ * @param a value to clip | |
+ * @param amin minimum value of the clip range | |
+ * @param amax maximum value of the clip range | |
+ * @return clipped value | |
+ */ | |
+static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) | |
+{ | |
+ av_assert2(amin <= amax); | |
+ if (a < amin) return amin; | |
+ else if (a > amax) return amax; | |
+ else return a; | |
+} | |
+ | |
static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame) | |
{ | |
CompandContext *s = ctx->priv; | |
AVFilterLink *inlink = ctx->inputs[0]; | |
- const int channels = inlink->channels; | |
+ const int channels = av_get_channel_layout_nb_channels(inlink->channel_layout); | |
const int nb_samples = frame->nb_samples; | |
AVFrame *out_frame; | |
int chan, i; | |
@@ -197,7 +226,7 @@ | |
for (i = 0; i < nb_samples; i++) { | |
update_volume(cp, fabs(src[i])); | |
- dst[i] = av_clipd(src[i] * get_volume(s, cp->volume), -1, 1); | |
+ dst[i] = av_clipd_c(src[i] * get_volume(s, cp->volume), -1, 1); | |
} | |
} | |
@@ -213,12 +242,12 @@ | |
{ | |
CompandContext *s = ctx->priv; | |
AVFilterLink *inlink = ctx->inputs[0]; | |
- const int channels = inlink->channels; | |
+ const int channels = av_get_channel_layout_nb_channels(inlink->channel_layout); | |
const int nb_samples = frame->nb_samples; | |
int chan, i, av_uninit(dindex), oindex, av_uninit(count); | |
AVFrame *out_frame = NULL; | |
- av_assert1(channels > 0); /* would corrupt delay_count and delay_index */ | |
+ av_assert2(channels > 0); /* would corrupt delay_count and delay_index */ | |
for (chan = 0; chan < channels; chan++) { | |
const double *src = (double *)frame->extended_data[chan]; | |
@@ -243,7 +272,7 @@ | |
} | |
dst = (double *)out_frame->extended_data[chan]; | |
- dst[oindex++] = av_clipd(dbuf[dindex] * get_volume(s, cp->volume), -1, 1); | |
+ dst[oindex++] = av_clipd_c(dbuf[dindex] * get_volume(s, cp->volume), -1, 1); | |
} else { | |
count++; | |
} | |
@@ -264,7 +293,7 @@ | |
{ | |
AVFilterContext *ctx = outlink->src; | |
CompandContext *s = ctx->priv; | |
- const int channels = outlink->channels; | |
+ const int channels = av_get_channel_layout_nb_channels(outlink->channel_layout); | |
int chan, i, dindex; | |
AVFrame *frame = NULL; | |
@@ -281,7 +310,7 @@ | |
dindex = s->delay_index; | |
for (i = 0; i < frame->nb_samples; i++) { | |
- dst[i] = av_clipd(dbuf[dindex] * get_volume(s, cp->volume), -1, 1); | |
+ dst[i] = av_clipd_c(dbuf[dindex] * get_volume(s, cp->volume), -1, 1); | |
dindex = MOD(dindex + 1, s->delay_samples); | |
} | |
} | |
@@ -291,10 +320,56 @@ | |
return ff_filter_frame(outlink, frame); | |
} | |
+static char *av_strtok(char *s, const char *delim, char **saveptr) | |
+{ | |
+ char *tok; | |
+ | |
+ if (!s && !(s = *saveptr)) | |
+ return NULL; | |
+ | |
+ /* skip leading delimiters */ | |
+ s += strspn(s, delim); | |
+ | |
+ /* s now points to the first non delimiter char, or to the end of the string */ | |
+ if (!*s) { | |
+ *saveptr = NULL; | |
+ return NULL; | |
+ } | |
+ tok = s++; | |
+ | |
+ /* skip non delimiters */ | |
+ s += strcspn(s, delim); | |
+ if (*s) { | |
+ *s = 0; | |
+ *saveptr = s+1; | |
+ } else { | |
+ *saveptr = NULL; | |
+ } | |
+ | |
+ return tok; | |
+} | |
+ | |
+ | |
+static int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, | |
+ int nb_samples, enum AVSampleFormat sample_fmt, int align) | |
+{ | |
+ int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1; | |
+ | |
+ *audio_data = av_mallocz(nb_planes * sizeof(**audio_data)); | |
+ if (!*audio_data) | |
+ return AVERROR(ENOMEM); | |
+ ret = av_samples_alloc(*audio_data, linesize, nb_channels, | |
+ nb_samples, sample_fmt, align); | |
+ if (ret < 0) | |
+ av_freep(audio_data); | |
+ return ret; | |
+} | |
+ | |
static int config_output(AVFilterLink *outlink) | |
{ | |
AVFilterContext *ctx = outlink->src; | |
CompandContext *s = ctx->priv; | |
+ const int channels = av_get_channel_layout_nb_channels(outlink->channel_layout); | |
const int sample_rate = outlink->sample_rate; | |
double radius = s->curve_dB * M_LN10 / 20; | |
int nb_attacks, nb_decays, nb_points; | |
@@ -306,14 +381,14 @@ | |
count_items(s->decays, &nb_decays); | |
count_items(s->points, &nb_points); | |
- if ((nb_attacks > outlink->channels) || (nb_decays > outlink->channels)) { | |
+ if ((nb_attacks > channels) || (nb_decays > channels)) { | |
av_log(ctx, AV_LOG_ERROR, "Number of attacks/decays bigger than number of channels.\n"); | |
return AVERROR(EINVAL); | |
} | |
uninit(ctx); | |
- s->channels = av_mallocz_array(outlink->channels, sizeof(*s->channels)); | |
+ s->channels = av_mallocz_array(channels, sizeof(*s->channels)); | |
s->segments = av_mallocz_array((nb_points + 4) * 2, sizeof(*s->segments)); | |
if (!s->channels || !s->segments) | |
@@ -434,7 +509,7 @@ | |
s->in_min_lin = exp(s->segments[1].x); | |
s->out_min_lin = exp(s->segments[1].y); | |
- for (i = 0; i < outlink->channels; i++) { | |
+ for (i = 0; i < channels; i++) { | |
ChanParam *cp = &s->channels[i]; | |
if (cp->attack > 1.0 / sample_rate) | |
@@ -452,12 +527,11 @@ | |
if (s->delay_samples > 0) { | |
int ret; | |
if ((ret = av_samples_alloc_array_and_samples(&s->delayptrs, NULL, | |
- outlink->channels, | |
+ channels, | |
s->delay_samples, | |
outlink->format, 0)) < 0) | |
return ret; | |
s->compand = compand_delay; | |
- outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP; | |
} else { | |
s->compand = compand_nodelay; | |
} | |
@@ -480,7 +554,7 @@ | |
ret = ff_request_frame(ctx->inputs[0]); | |
- if (ret == AVERROR_EOF && !ctx->is_disabled && s->delay_count) | |
+ if (ret == AVERROR_EOF && s->delay_count) | |
ret = compand_drain(outlink); | |
return ret; | |
@@ -505,6 +579,7 @@ | |
{ NULL } | |
}; | |
+ | |
AVFilter ff_af_compand = { | |
.name = "compand", | |
.description = NULL_IF_CONFIG_SMALL("Compress or expand audio dynamic range."), | |
@@ -512,7 +587,6 @@ | |
.priv_size = sizeof(CompandContext), | |
.priv_class = &compand_class, | |
.init = init, | |
- .uninit = uninit, | |
.inputs = compand_inputs, | |
.outputs = compand_outputs, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment