72#define OFFSET(x) offsetof(CompandContext, x)
73#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
76 {
"attacks",
"set time over which increase of volume is determined",
OFFSET(attacks),
AV_OPT_TYPE_STRING, { .str =
"0" }, 0, 0,
A },
77 {
"decays",
"set time over which decrease of volume is determined",
OFFSET(decays),
AV_OPT_TYPE_STRING, { .str =
"0.8" }, 0, 0,
A },
78 {
"points",
"set points of transfer function",
OFFSET(points),
AV_OPT_TYPE_STRING, { .str =
"-70/-70|-60/-20|1/0" }, 0, 0,
A },
82 {
"delay",
"set delay for samples before sending them to volume adjuster",
OFFSET(delay),
AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, 0, 20,
A },
109 for (p = item_str; *p; p++) {
110 if (*p ==
' ' || *p ==
'|')
128 double in_log, out_log;
131 if (in_lin < s->in_min_lin)
132 return s->out_min_lin;
134 in_log = log(in_lin);
136 for (
i = 1;
i <
s->nb_segments;
i++)
137 if (in_log <= s->segments[
i].x)
139 cs = &
s->segments[
i - 1];
141 out_log = cs->
y + in_log * (cs->
a * in_log + cs->
b);
151 const int nb_samples =
frame->nb_samples;
172 for (chan = 0; chan <
channels; chan++) {
173 const double *
src = (
double *)
frame->extended_data[chan];
177 for (
i = 0;
i < nb_samples;
i++) {
184 if (
frame != out_frame)
190#define MOD(a, b) (((a) >= (b)) ? (a) - (b) : (a))
197 const int nb_samples =
frame->nb_samples;
208 for (chan = 0; chan <
channels; chan++) {
209 AVFrame *delay_frame =
s->delay_frame;
210 const double *
src = (
double *)
frame->extended_data[chan];
215 count =
s->delay_count;
216 dindex =
s->delay_index;
217 for (
i = 0, oindex = 0;
i < nb_samples;
i++) {
218 const double in =
src[
i];
221 if (count >=
s->delay_samples) {
234 out_frame->
pts =
s->pts;
247 dindex =
MOD(dindex + 1,
s->delay_samples);
251 s->delay_count = count;
252 s->delay_index = dindex;
281 for (chan = 0; chan <
channels; chan++) {
282 AVFrame *delay_frame =
s->delay_frame;
284 double *
dst = (
double *)
frame->extended_data[chan];
287 dindex =
s->delay_index;
288 for (
i = 0;
i <
frame->nb_samples;
i++) {
290 dindex =
MOD(dindex + 1,
s->delay_samples);
293 s->delay_count -=
frame->nb_samples;
294 s->delay_index = dindex;
304 double radius =
s->curve_dB *
M_LN10 / 20.0;
305 char *p, *saveptr =
NULL;
307 int nb_attacks, nb_decays, nb_points;
308 int new_nb_items, num;
322 "Number of attacks/decays bigger than number of channels. Ignoring rest of entries.\n");
330 s->nb_segments = (nb_points + 4) * 2;
331 s->segments =
av_calloc(
s->nb_segments,
sizeof(*
s->segments));
333 if (!
s->channels || !
s->segments) {
339 for (
i = 0, new_nb_items = 0;
i < nb_attacks;
i++) {
340 char *tstr =
av_strtok(p,
" |", &saveptr);
346 new_nb_items += sscanf(tstr,
"%lf", &
s->channels[
i].attack) == 1;
347 if (
s->channels[
i].attack < 0) {
352 nb_attacks = new_nb_items;
355 for (
i = 0, new_nb_items = 0;
i < nb_decays;
i++) {
356 char *tstr =
av_strtok(p,
" |", &saveptr);
362 new_nb_items += sscanf(tstr,
"%lf", &
s->channels[
i].decay) == 1;
363 if (
s->channels[
i].decay < 0) {
368 nb_decays = new_nb_items;
370 if (nb_attacks != nb_decays) {
372 "Number of attacks %d differs from number of decays %d.\n",
373 nb_attacks, nb_decays);
379 s->channels[
i].attack =
s->channels[nb_decays - 1].attack;
380 s->channels[
i].decay =
s->channels[nb_decays - 1].decay;
383#define S(x) s->segments[2 * ((x) + 1)]
385 for (
i = 0, new_nb_items = 0;
i < nb_points;
i++) {
386 char *tstr =
av_strtok(p,
" |", &saveptr);
388 if (!tstr || sscanf(tstr,
"%lf/%lf", &
S(
i).x, &
S(
i).y) != 2) {
390 "Invalid and/or missing input/output value.\n");
394 if (
i &&
S(
i - 1).x >
S(
i).x) {
396 "Transfer function input values must be increasing.\n");
407 if (num == 0 ||
S(num - 1).x)
411#define S(x) s->segments[2 * (x)]
413 S(0).x =
S(1).x - 2 *
s->curve_dB;
418 for (
i = 2;
i < num;
i++) {
419 double g1 = (
S(
i - 1).y -
S(
i - 2).y) * (
S(
i - 0).x -
S(
i - 1).x);
420 double g2 = (
S(
i - 0).y -
S(
i - 1).y) * (
S(
i - 1).x -
S(
i - 2).x);
426 for (j = --
i; j < num; j++)
430 for (
i = 0;
i <
s->nb_segments;
i += 2) {
431 s->segments[
i].y +=
s->gain_dB;
436#define L(x) s->segments[i - (x)]
437 for (
i = 4;
i <
s->nb_segments;
i += 2) {
438 double x, y, cx, cy, in1, in2, out1, out2, theta,
len,
r;
441 L(4).b = (
L(2).y -
L(4).y) / (
L(2).x -
L(4).x);
444 L(2).b = (
L(0).y -
L(2).y) / (
L(0).x -
L(2).x);
446 theta = atan2(
L(2).y -
L(4).y,
L(2).x -
L(4).x);
449 L(3).x =
L(2).x -
r * cos(theta);
450 L(3).y =
L(2).y -
r * sin(theta);
452 theta = atan2(
L(0).y -
L(2).y,
L(0).x -
L(2).x);
455 x =
L(2).x +
r * cos(theta);
456 y =
L(2).y +
r * sin(theta);
458 cx = (
L(3).x +
L(2).x + x) / 3;
459 cy = (
L(3).y +
L(2).y + y) / 3;
466 in2 =
L(2).x -
L(3).x;
467 out2 =
L(2).y -
L(3).y;
468 L(3).a = (out2 / in2 - out1 / in1) / (in2 - in1);
469 L(3).b = out1 / in1 -
L(3).a * in1;
474 s->in_min_lin =
exp(
s->segments[1].x);
475 s->out_min_lin =
exp(
s->segments[1].y);
480 if (cp->
attack > 1.0 / sample_rate)
484 if (cp->
decay > 1.0 / sample_rate)
491 s->delay_samples =
s->delay * sample_rate;
492 if (
s->delay_samples <= 0) {
548 "Compress or expand audio dynamic range."),
549 .p.priv_class = &compand_class,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static int request_frame(AVFilterLink *outlink)
static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame)
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
static int request_frame(AVFilterLink *outlink)
static const AVOption compand_options[]
static int compand_drain(AVFilterLink *outlink)
const FFFilter ff_af_compand
static void update_volume(ChanParam *cp, double in)
static av_cold void uninit(AVFilterContext *ctx)
static double get_volume(CompandContext *s, double in_lin)
static const AVFilterPad compand_inputs[]
static int config_output(AVFilterLink *outlink)
static const AVFilterPad compand_outputs[]
static int compand_delay(AVFilterContext *ctx, AVFrame *frame)
static void count_items(char *item_str, int *nb_items)
static AVFormatContext * ctx
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
static __device__ float fabs(float a)
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
int(* init)(AVBSFContext *ctx)
internal math functions header
static av_always_inline double ff_exp10(double x)
Compute 10^x for floating point values.
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AVERROR_EOF
End of file.
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AV_SAMPLE_FMT_DBLP
double, planar
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
#define AV_NOPTS_VALUE
Undefined timestamp value.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define FILTER_SINGLE_SAMPLEFMT(sample_fmt_)
#define AVFILTER_DEFINE_CLASS(fname)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static av_const double hypot(double x, double y)
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
A link between two filters.
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
int sample_rate
samples per second
AVChannelLayout ch_layout
channel layout of current buffer (see libavutil/channel_layout.h)
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t ** extended_data
pointers to the data planes/channels.
Rational number (pair of numerator and denominator).
int(* compand)(AVFilterContext *ctx, AVFrame *frame)
CompandSegment * segments