FFmpeg
af_dynaudnorm.c
Go to the documentation of this file.
1 /*
2  * Dynamic Audio Normalizer
3  * Copyright (c) 2015 LoRd_MuldeR <mulder2@gmx.de>. Some rights reserved.
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * Dynamic Audio Normalizer
25  */
26 
27 #include <float.h>
28 
29 #include "libavutil/avassert.h"
31 #include "libavutil/opt.h"
32 
33 #define MIN_FILTER_SIZE 3
34 #define MAX_FILTER_SIZE 301
35 
36 #define FF_BUFQUEUE_SIZE (MAX_FILTER_SIZE + 1)
38 
39 #include "audio.h"
40 #include "avfilter.h"
41 #include "filters.h"
42 #include "internal.h"
43 
44 typedef struct local_gain {
45  double max_gain;
46  double threshold;
47 } local_gain;
48 
49 typedef struct cqueue {
50  double *elements;
51  int size;
52  int max_size;
54 } cqueue;
55 
57  const AVClass *class;
58 
59  struct FFBufQueue queue;
60 
61  int frame_len;
67  double overlap;
68 
69  double peak_value;
71  double target_rms;
73  double threshold;
77  double *weights;
78 
79  int channels;
81  int eof;
84  int64_t pts;
85 
90 
92 
95 
96 #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x)
97 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
98 
99 static const AVOption dynaudnorm_options[] = {
100  { "framelen", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
101  { "f", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
102  { "gausssize", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
103  { "g", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
104  { "peak", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
105  { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
106  { "maxgain", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
107  { "m", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
108  { "targetrms", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
109  { "r", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
110  { "coupling", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
111  { "n", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
112  { "correctdc", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
113  { "c", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
114  { "altboundary", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
115  { "b", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
116  { "compress", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
117  { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
118  { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
119  { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
120  { "channels", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS },
121  { "h", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS },
122  { "overlap", "set the frame overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=.0}, 0.0, 1.0, FLAGS },
123  { "o", "set the frame overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=.0}, 0.0, 1.0, FLAGS },
124  { NULL }
125 };
126 
127 AVFILTER_DEFINE_CLASS(dynaudnorm);
128 
130 {
132 
133  if (!(s->filter_size & 1)) {
134  av_log(ctx, AV_LOG_WARNING, "filter size %d is invalid. Changing to an odd value.\n", s->filter_size);
135  s->filter_size |= 1;
136  }
137 
138  return 0;
139 }
140 
141 static inline int frame_size(int sample_rate, int frame_len_msec)
142 {
143  const int frame_size = lrint((double)sample_rate * (frame_len_msec / 1000.0));
144  return frame_size + (frame_size % 2);
145 }
146 
147 static cqueue *cqueue_create(int size, int max_size)
148 {
149  cqueue *q;
150 
151  if (max_size < size)
152  return NULL;
153 
154  q = av_malloc(sizeof(cqueue));
155  if (!q)
156  return NULL;
157 
158  q->max_size = max_size;
159  q->size = size;
160  q->nb_elements = 0;
161 
162  q->elements = av_malloc_array(max_size, sizeof(double));
163  if (!q->elements) {
164  av_free(q);
165  return NULL;
166  }
167 
168  return q;
169 }
170 
171 static void cqueue_free(cqueue *q)
172 {
173  if (q)
174  av_free(q->elements);
175  av_free(q);
176 }
177 
178 static int cqueue_size(cqueue *q)
179 {
180  return q->nb_elements;
181 }
182 
183 static int cqueue_empty(cqueue *q)
184 {
185  return q->nb_elements <= 0;
186 }
187 
188 static int cqueue_enqueue(cqueue *q, double element)
189 {
191 
192  q->elements[q->nb_elements] = element;
193  q->nb_elements++;
194 
195  return 0;
196 }
197 
198 static double cqueue_peek(cqueue *q, int index)
199 {
200  av_assert2(index < q->nb_elements);
201  return q->elements[index];
202 }
203 
204 static int cqueue_dequeue(cqueue *q, double *element)
205 {
207 
208  *element = q->elements[0];
209  memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double));
210  q->nb_elements--;
211 
212  return 0;
213 }
214 
215 static int cqueue_pop(cqueue *q)
216 {
218 
219  memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double));
220  q->nb_elements--;
221 
222  return 0;
223 }
224 
225 static void cqueue_resize(cqueue *q, int new_size)
226 {
227  av_assert2(q->max_size >= new_size);
228  av_assert2(MIN_FILTER_SIZE <= new_size);
229 
230  if (new_size > q->nb_elements) {
231  const int side = (new_size - q->nb_elements) / 2;
232 
233  memmove(q->elements + side, q->elements, sizeof(double) * q->nb_elements);
234  for (int i = 0; i < side; i++)
235  q->elements[i] = q->elements[side];
236  q->nb_elements = new_size - 1 - side;
237  } else {
238  int count = (q->size - new_size + 1) / 2;
239 
240  while (count-- > 0)
241  cqueue_pop(q);
242  }
243 
244  q->size = new_size;
245 }
246 
248 {
249  double total_weight = 0.0;
250  const double sigma = (((s->filter_size / 2.0) - 1.0) / 3.0) + (1.0 / 3.0);
251  double adjust;
252 
253  // Pre-compute constants
254  const int offset = s->filter_size / 2;
255  const double c1 = 1.0 / (sigma * sqrt(2.0 * M_PI));
256  const double c2 = 2.0 * sigma * sigma;
257 
258  // Compute weights
259  for (int i = 0; i < s->filter_size; i++) {
260  const int x = i - offset;
261 
262  s->weights[i] = c1 * exp(-x * x / c2);
263  total_weight += s->weights[i];
264  }
265 
266  // Adjust weights
267  adjust = 1.0 / total_weight;
268  for (int i = 0; i < s->filter_size; i++) {
269  s->weights[i] *= adjust;
270  }
271 }
272 
274 {
276 
277  av_freep(&s->prev_amplification_factor);
278  av_freep(&s->dc_correction_value);
279  av_freep(&s->compress_threshold);
280 
281  for (int c = 0; c < s->channels; c++) {
282  if (s->gain_history_original)
283  cqueue_free(s->gain_history_original[c]);
284  if (s->gain_history_minimum)
285  cqueue_free(s->gain_history_minimum[c]);
286  if (s->gain_history_smoothed)
287  cqueue_free(s->gain_history_smoothed[c]);
288  if (s->threshold_history)
289  cqueue_free(s->threshold_history[c]);
290  }
291 
292  av_freep(&s->gain_history_original);
293  av_freep(&s->gain_history_minimum);
294  av_freep(&s->gain_history_smoothed);
295  av_freep(&s->threshold_history);
296 
297  cqueue_free(s->is_enabled);
298  s->is_enabled = NULL;
299 
300  av_freep(&s->weights);
301 
302  av_channel_layout_uninit(&s->ch_layout);
303 
304  ff_bufqueue_discard_all(&s->queue);
305 
306  av_frame_free(&s->window);
307 }
308 
310 {
311  AVFilterContext *ctx = inlink->dst;
313 
314  uninit(ctx);
315 
316  s->channels = inlink->ch_layout.nb_channels;
317  s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec);
318  av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len);
319 
320  s->prev_amplification_factor = av_malloc_array(inlink->ch_layout.nb_channels, sizeof(*s->prev_amplification_factor));
321  s->dc_correction_value = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->dc_correction_value));
322  s->compress_threshold = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->compress_threshold));
323  s->gain_history_original = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_original));
324  s->gain_history_minimum = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_minimum));
325  s->gain_history_smoothed = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_smoothed));
326  s->threshold_history = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->threshold_history));
327  s->weights = av_malloc_array(MAX_FILTER_SIZE, sizeof(*s->weights));
328  s->is_enabled = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
329  if (!s->prev_amplification_factor || !s->dc_correction_value ||
330  !s->compress_threshold ||
331  !s->gain_history_original || !s->gain_history_minimum ||
332  !s->gain_history_smoothed || !s->threshold_history ||
333  !s->is_enabled || !s->weights)
334  return AVERROR(ENOMEM);
335 
336  for (int c = 0; c < inlink->ch_layout.nb_channels; c++) {
337  s->prev_amplification_factor[c] = 1.0;
338 
339  s->gain_history_original[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
340  s->gain_history_minimum[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
341  s->gain_history_smoothed[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
342  s->threshold_history[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
343 
344  if (!s->gain_history_original[c] || !s->gain_history_minimum[c] ||
345  !s->gain_history_smoothed[c] || !s->threshold_history[c])
346  return AVERROR(ENOMEM);
347  }
348 
350 
351  s->window = ff_get_audio_buffer(ctx->outputs[0], s->frame_len * 2);
352  if (!s->window)
353  return AVERROR(ENOMEM);
354  s->sample_advance = FFMAX(1, lrint(s->frame_len * (1. - s->overlap)));
355 
356  return 0;
357 }
358 
359 static inline double fade(double prev, double next, int pos, int length)
360 {
361  const double step_size = 1.0 / length;
362  const double f0 = 1.0 - (step_size * (pos + 1.0));
363  const double f1 = 1.0 - f0;
364  return f0 * prev + f1 * next;
365 }
366 
367 static inline double pow_2(const double value)
368 {
369  return value * value;
370 }
371 
372 static inline double bound(const double threshold, const double val)
373 {
374  const double CONST = 0.8862269254527580136490837416705725913987747280611935; //sqrt(PI) / 2.0
375  return erf(CONST * (val / threshold)) * threshold;
376 }
377 
379 {
380  double max = DBL_EPSILON;
381 
382  if (channel == -1) {
383  for (int c = 0; c < frame->ch_layout.nb_channels; c++) {
384  double *data_ptr = (double *)frame->extended_data[c];
385 
386  for (int i = 0; i < frame->nb_samples; i++)
387  max = fmax(max, fabs(data_ptr[i]));
388  }
389  } else {
390  double *data_ptr = (double *)frame->extended_data[channel];
391 
392  for (int i = 0; i < frame->nb_samples; i++)
393  max = fmax(max, fabs(data_ptr[i]));
394  }
395 
396  return max;
397 }
398 
400 {
401  double rms_value = 0.0;
402 
403  if (channel == -1) {
404  for (int c = 0; c < frame->ch_layout.nb_channels; c++) {
405  const double *data_ptr = (double *)frame->extended_data[c];
406 
407  for (int i = 0; i < frame->nb_samples; i++) {
408  rms_value += pow_2(data_ptr[i]);
409  }
410  }
411 
412  rms_value /= frame->nb_samples * frame->ch_layout.nb_channels;
413  } else {
414  const double *data_ptr = (double *)frame->extended_data[channel];
415  for (int i = 0; i < frame->nb_samples; i++) {
416  rms_value += pow_2(data_ptr[i]);
417  }
418 
419  rms_value /= frame->nb_samples;
420  }
421 
422  return fmax(sqrt(rms_value), DBL_EPSILON);
423 }
424 
426  int channel)
427 {
428  const double peak_magnitude = find_peak_magnitude(frame, channel);
429  const double maximum_gain = s->peak_value / peak_magnitude;
430  const double rms_gain = s->target_rms > DBL_EPSILON ? (s->target_rms / compute_frame_rms(frame, channel)) : DBL_MAX;
431  local_gain gain;
432 
433  gain.threshold = peak_magnitude > s->threshold;
434  gain.max_gain = bound(s->max_amplification, fmin(maximum_gain, rms_gain));
435 
436  return gain;
437 }
438 
439 static double minimum_filter(cqueue *q)
440 {
441  double min = DBL_MAX;
442 
443  for (int i = 0; i < cqueue_size(q); i++) {
444  min = fmin(min, cqueue_peek(q, i));
445  }
446 
447  return min;
448 }
449 
451 {
452  const double *weights = s->weights;
453  double result = 0.0, tsum = 0.0;
454 
455  for (int i = 0; i < cqueue_size(q); i++) {
456  double tq_item = cqueue_peek(tq, i);
457  double q_item = cqueue_peek(q, i);
458 
459  tsum += tq_item * weights[i];
460  result += tq_item * weights[i] * q_item;
461  }
462 
463  if (tsum == 0.0)
464  result = 1.0;
465 
466  return result;
467 }
468 
470  local_gain gain)
471 {
472  if (cqueue_empty(s->gain_history_original[channel])) {
473  const int pre_fill_size = s->filter_size / 2;
474  const double initial_value = s->alt_boundary_mode ? gain.max_gain : fmin(1.0, gain.max_gain);
475 
476  s->prev_amplification_factor[channel] = initial_value;
477 
478  while (cqueue_size(s->gain_history_original[channel]) < pre_fill_size) {
479  cqueue_enqueue(s->gain_history_original[channel], initial_value);
480  cqueue_enqueue(s->threshold_history[channel], gain.threshold);
481  }
482  }
483 
484  cqueue_enqueue(s->gain_history_original[channel], gain.max_gain);
485 
486  while (cqueue_size(s->gain_history_original[channel]) >= s->filter_size) {
487  double minimum;
488 
489  if (cqueue_empty(s->gain_history_minimum[channel])) {
490  const int pre_fill_size = s->filter_size / 2;
491  double initial_value = s->alt_boundary_mode ? cqueue_peek(s->gain_history_original[channel], 0) : 1.0;
492  int input = pre_fill_size;
493 
494  while (cqueue_size(s->gain_history_minimum[channel]) < pre_fill_size) {
495  input++;
496  initial_value = fmin(initial_value, cqueue_peek(s->gain_history_original[channel], input));
497  cqueue_enqueue(s->gain_history_minimum[channel], initial_value);
498  }
499  }
500 
501  minimum = minimum_filter(s->gain_history_original[channel]);
502 
503  cqueue_enqueue(s->gain_history_minimum[channel], minimum);
504 
505  cqueue_enqueue(s->threshold_history[channel], gain.threshold);
506 
507  cqueue_pop(s->gain_history_original[channel]);
508  }
509 
510  while (cqueue_size(s->gain_history_minimum[channel]) >= s->filter_size) {
511  double smoothed, limit;
512 
513  smoothed = gaussian_filter(s, s->gain_history_minimum[channel], s->threshold_history[channel]);
514  limit = cqueue_peek(s->gain_history_original[channel], 0);
515  smoothed = fmin(smoothed, limit);
516 
517  cqueue_enqueue(s->gain_history_smoothed[channel], smoothed);
518 
519  cqueue_pop(s->gain_history_minimum[channel]);
520  cqueue_pop(s->threshold_history[channel]);
521  }
522 }
523 
524 static inline double update_value(double new, double old, double aggressiveness)
525 {
526  av_assert0((aggressiveness >= 0.0) && (aggressiveness <= 1.0));
527  return aggressiveness * new + (1.0 - aggressiveness) * old;
528 }
529 
531 {
533 
534  return av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0;
535 }
536 
538 {
539  const double diff = 1.0 / frame->nb_samples;
540  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
541 
542  for (int c = 0; c < s->channels; c++) {
543  const int bypass = bypass_channel(s, frame, c);
544  double *dst_ptr = (double *)frame->extended_data[c];
545  double current_average_value = 0.0;
546  double prev_value;
547 
548  for (int i = 0; i < frame->nb_samples; i++)
549  current_average_value += dst_ptr[i] * diff;
550 
551  prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c];
552  s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1);
553 
554  for (int i = 0; i < frame->nb_samples && !bypass; i++) {
555  dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples);
556  }
557  }
558 }
559 
560 static double setup_compress_thresh(double threshold)
561 {
562  if ((threshold > DBL_EPSILON) && (threshold < (1.0 - DBL_EPSILON))) {
563  double current_threshold = threshold;
564  double step_size = 1.0;
565 
566  while (step_size > DBL_EPSILON) {
567  while ((llrint((current_threshold + step_size) * (UINT64_C(1) << 63)) >
568  llrint(current_threshold * (UINT64_C(1) << 63))) &&
569  (bound(current_threshold + step_size, 1.0) <= threshold)) {
570  current_threshold += step_size;
571  }
572 
573  step_size /= 2.0;
574  }
575 
576  return current_threshold;
577  } else {
578  return threshold;
579  }
580 }
581 
583  AVFrame *frame, int channel)
584 {
585  double variance = 0.0;
586 
587  if (channel == -1) {
588  for (int c = 0; c < s->channels; c++) {
589  const double *data_ptr = (double *)frame->extended_data[c];
590 
591  for (int i = 0; i < frame->nb_samples; i++) {
592  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
593  }
594  }
595  variance /= (s->channels * frame->nb_samples) - 1;
596  } else {
597  const double *data_ptr = (double *)frame->extended_data[channel];
598 
599  for (int i = 0; i < frame->nb_samples; i++) {
600  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
601  }
602  variance /= frame->nb_samples - 1;
603  }
604 
605  return fmax(sqrt(variance), DBL_EPSILON);
606 }
607 
609 {
610  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
611 
612  if (s->channels_coupled) {
613  const double standard_deviation = compute_frame_std_dev(s, frame, -1);
614  const double current_threshold = fmin(1.0, s->compress_factor * standard_deviation);
615 
616  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[0];
617  double prev_actual_thresh, curr_actual_thresh;
618  s->compress_threshold[0] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[0], (1.0/3.0));
619 
620  prev_actual_thresh = setup_compress_thresh(prev_value);
621  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[0]);
622 
623  for (int c = 0; c < s->channels; c++) {
624  double *const dst_ptr = (double *)frame->extended_data[c];
625  const int bypass = bypass_channel(s, frame, c);
626 
627  if (bypass)
628  continue;
629 
630  for (int i = 0; i < frame->nb_samples; i++) {
631  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
632  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
633  }
634  }
635  } else {
636  for (int c = 0; c < s->channels; c++) {
637  const int bypass = bypass_channel(s, frame, c);
638  const double standard_deviation = compute_frame_std_dev(s, frame, c);
639  const double current_threshold = setup_compress_thresh(fmin(1.0, s->compress_factor * standard_deviation));
640  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c];
641  double prev_actual_thresh, curr_actual_thresh;
642  double *dst_ptr;
643 
644  s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0);
645 
646  prev_actual_thresh = setup_compress_thresh(prev_value);
647  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]);
648 
649  dst_ptr = (double *)frame->extended_data[c];
650  for (int i = 0; i < frame->nb_samples && !bypass; i++) {
651  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
652  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
653  }
654  }
655  }
656 }
657 
659 {
661 
662  if (s->dc_correction || s->compress_factor > DBL_EPSILON) {
663  int ret;
664 
665  if (!av_frame_is_writable(*frame)) {
666  AVFrame *out = ff_get_audio_buffer(outlink, (*frame)->nb_samples);
667 
668  if (!out) {
670  return AVERROR(ENOMEM);
671  }
673  if (ret < 0) {
675  av_frame_free(&out);
676  return ret;
677  }
678  ret = av_frame_copy(out, *frame);
679  if (ret < 0) {
681  av_frame_free(&out);
682  return ret;
683  }
684 
686  *frame = out;
687  }
688  }
689 
690  if (s->dc_correction)
692 
693  if (s->compress_factor > DBL_EPSILON)
695 
696  if (s->frame_len != s->sample_advance) {
697  const int offset = s->frame_len - s->sample_advance;
698 
699  for (int c = 0; c < s->channels; c++) {
700  double *src = (double *)s->window->extended_data[c];
701 
702  memmove(src, &src[s->sample_advance], offset * sizeof(double));
703  memcpy(&src[offset], (*frame)->extended_data[c], (*frame)->nb_samples * sizeof(double));
704  memset(&src[offset + (*frame)->nb_samples], 0, (s->sample_advance - (*frame)->nb_samples) * sizeof(double));
705  }
706 
707  analyze_frame = s->window;
708  } else {
709  av_samples_copy(s->window->extended_data, (*frame)->extended_data, 0, 0,
710  s->frame_len, (*frame)->ch_layout.nb_channels, (*frame)->format);
711  analyze_frame = *frame;
712  }
713 
714  if (s->channels_coupled) {
715  const local_gain gain = get_max_local_gain(s, analyze_frame, -1);
716  for (int c = 0; c < s->channels; c++)
717  update_gain_history(s, c, gain);
718  } else {
719  for (int c = 0; c < s->channels; c++)
721  }
722 
723  return 0;
724 }
725 
727  AVFrame *frame, int enabled)
728 {
729  for (int c = 0; c < s->channels; c++) {
730  const int bypass = bypass_channel(s, frame, c);
731  const double *src_ptr = (const double *)in->extended_data[c];
732  double *dst_ptr = (double *)frame->extended_data[c];
733  double current_amplification_factor;
734 
735  cqueue_dequeue(s->gain_history_smoothed[c], &current_amplification_factor);
736 
737  for (int i = 0; i < frame->nb_samples && enabled && !bypass; i++) {
738  const double amplification_factor = fade(s->prev_amplification_factor[c],
739  current_amplification_factor, i,
740  frame->nb_samples);
741 
742  dst_ptr[i] = src_ptr[i] * amplification_factor;
743  }
744 
745  s->prev_amplification_factor[c] = current_amplification_factor;
746  }
747 }
748 
750 {
751  AVFilterContext *ctx = inlink->dst;
753  AVFilterLink *outlink = ctx->outputs[0];
754  int ret;
755 
756  while (((s->queue.available >= s->filter_size) ||
757  (s->eof && s->queue.available)) &&
758  !cqueue_empty(s->gain_history_smoothed[0])) {
759  AVFrame *in = ff_bufqueue_get(&s->queue);
760  AVFrame *out;
761  double is_enabled;
762 
763  cqueue_dequeue(s->is_enabled, &is_enabled);
764 
765  if (av_frame_is_writable(in)) {
766  out = in;
767  } else {
768  out = ff_get_audio_buffer(outlink, in->nb_samples);
769  if (!out) {
770  av_frame_free(&in);
771  return AVERROR(ENOMEM);
772  }
774  }
775 
776  amplify_frame(s, in, out, is_enabled > 0.);
777  s->pts = out->pts + av_rescale_q(out->nb_samples, av_make_q(1, outlink->sample_rate),
778  outlink->time_base);
779  if (out != in)
780  av_frame_free(&in);
781  ret = ff_filter_frame(outlink, out);
782  if (ret < 0)
783  return ret;
784  }
785 
786  ret = analyze_frame(s, outlink, &in);
787  if (ret < 0)
788  return ret;
789  if (!s->eof) {
790  ff_bufqueue_add(ctx, &s->queue, in);
791  cqueue_enqueue(s->is_enabled, !ctx->is_disabled);
792  } else {
793  av_frame_free(&in);
794  }
795 
796  return 1;
797 }
798 
800  AVFilterLink *outlink)
801 {
802  AVFrame *out = ff_get_audio_buffer(outlink, s->sample_advance);
803 
804  if (!out)
805  return AVERROR(ENOMEM);
806 
807  for (int c = 0; c < s->channels; c++) {
808  double *dst_ptr = (double *)out->extended_data[c];
809 
810  for (int i = 0; i < out->nb_samples; i++) {
811  dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? fmin(s->peak_value, s->target_rms) : s->peak_value);
812  if (s->dc_correction) {
813  dst_ptr[i] *= ((i % 2) == 1) ? -1 : 1;
814  dst_ptr[i] += s->dc_correction_value[c];
815  }
816  }
817  }
818 
819  return filter_frame(inlink, out);
820 }
821 
822 static int flush(AVFilterLink *outlink)
823 {
824  AVFilterContext *ctx = outlink->src;
825  AVFilterLink *inlink = ctx->inputs[0];
827  int ret = 0;
828 
829  if (!cqueue_empty(s->gain_history_smoothed[0])) {
830  ret = flush_buffer(s, inlink, outlink);
831  } else if (s->queue.available) {
832  AVFrame *out = ff_bufqueue_get(&s->queue);
833 
834  s->pts = out->pts + av_rescale_q(out->nb_samples, av_make_q(1, outlink->sample_rate),
835  outlink->time_base);
836  ret = ff_filter_frame(outlink, out);
837  }
838 
839  return ret;
840 }
841 
843 {
844  AVFilterLink *inlink = ctx->inputs[0];
845  AVFilterLink *outlink = ctx->outputs[0];
847  AVFrame *in = NULL;
848  int ret = 0, status;
849  int64_t pts;
850 
851  ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout);
852  if (ret < 0)
853  return ret;
854  if (strcmp(s->channels_to_filter, "all"))
855  av_channel_layout_from_string(&s->ch_layout, s->channels_to_filter);
856 
858 
859  if (!s->eof) {
860  ret = ff_inlink_consume_samples(inlink, s->sample_advance, s->sample_advance, &in);
861  if (ret < 0)
862  return ret;
863  if (ret > 0) {
864  ret = filter_frame(inlink, in);
865  if (ret <= 0)
866  return ret;
867  }
868 
869  if (ff_inlink_check_available_samples(inlink, s->sample_advance) > 0) {
871  return 0;
872  }
873  }
874 
875  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
876  if (status == AVERROR_EOF)
877  s->eof = 1;
878  }
879 
880  if (s->eof && s->queue.available)
881  return flush(outlink);
882 
883  if (s->eof && !s->queue.available) {
884  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
885  return 0;
886  }
887 
888  if (!s->eof)
890 
891  return FFERROR_NOT_READY;
892 }
893 
894 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
895  char *res, int res_len, int flags)
896 {
898  AVFilterLink *inlink = ctx->inputs[0];
899  int prev_filter_size = s->filter_size;
900  int ret;
901 
902  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
903  if (ret < 0)
904  return ret;
905 
906  s->filter_size |= 1;
907  if (prev_filter_size != s->filter_size) {
909 
910  for (int c = 0; c < s->channels; c++) {
911  cqueue_resize(s->gain_history_original[c], s->filter_size);
912  cqueue_resize(s->gain_history_minimum[c], s->filter_size);
913  cqueue_resize(s->threshold_history[c], s->filter_size);
914  }
915  }
916 
917  s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec);
918  s->sample_advance = FFMAX(1, lrint(s->frame_len * (1. - s->overlap)));
919 
920  return 0;
921 }
922 
924  {
925  .name = "default",
926  .type = AVMEDIA_TYPE_AUDIO,
927  .config_props = config_input,
928  },
929 };
930 
932  {
933  .name = "default",
934  .type = AVMEDIA_TYPE_AUDIO,
935  },
936 };
937 
939  .name = "dynaudnorm",
940  .description = NULL_IF_CONFIG_SMALL("Dynamic Audio Normalizer."),
941  .priv_size = sizeof(DynamicAudioNormalizerContext),
942  .init = init,
943  .uninit = uninit,
944  .activate = activate,
948  .priv_class = &dynaudnorm_class,
950  .process_command = process_command,
951 };
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_dynaudnorm.c:309
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:100
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
flush_buffer
static int flush_buffer(DynamicAudioNormalizerContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
Definition: af_dynaudnorm.c:799
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
OFFSET
#define OFFSET(x)
Definition: af_dynaudnorm.c:96
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
out
FILE * out
Definition: movenc.c:54
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:999
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
DynamicAudioNormalizerContext::overlap
double overlap
Definition: af_dynaudnorm.c:67
FILTER_SINGLE_SAMPLEFMT
#define FILTER_SINGLE_SAMPLEFMT(sample_fmt_)
Definition: internal.h:183
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(dynaudnorm)
amplify_frame
static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *in, AVFrame *frame, int enabled)
Definition: af_dynaudnorm.c:726
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
MAX_FILTER_SIZE
#define MAX_FILTER_SIZE
Definition: af_dynaudnorm.c:34
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:129
AVOption
AVOption.
Definition: opt.h:251
DynamicAudioNormalizerContext::dc_correction_value
double * dc_correction_value
Definition: af_dynaudnorm.c:75
float.h
cqueue_resize
static void cqueue_resize(cqueue *q, int new_size)
Definition: af_dynaudnorm.c:225
max
#define max(a, b)
Definition: cuda_runtime.h:33
DynamicAudioNormalizerContext::window
AVFrame * window
Definition: af_dynaudnorm.c:93
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:175
c1
static const uint64_t c1
Definition: murmur3.c:51
cqueue::max_size
int max_size
Definition: af_dynaudnorm.c:52
avfilter_af_dynaudnorm_inputs
static const AVFilterPad avfilter_af_dynaudnorm_inputs[]
Definition: af_dynaudnorm.c:923
FF_FILTER_FORWARD_STATUS_BACK
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
sample_rate
sample_rate
Definition: ffmpeg_filter.c:155
find_peak_magnitude
static double find_peak_magnitude(AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:378
ff_bufqueue_get
static AVFrame * ff_bufqueue_get(struct FFBufQueue *queue)
Get the first buffer from the queue and remove it.
Definition: bufferqueue.h:98
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
av_channel_layout_copy
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
Definition: channel_layout.c:637
AVChannel
AVChannel
Definition: channel_layout.h:41
DynamicAudioNormalizerContext
Definition: af_dynaudnorm.c:56
local_gain
Definition: af_dynaudnorm.c:44
analyze_frame
static int analyze_frame(DynamicAudioNormalizerContext *s, AVFilterLink *outlink, AVFrame **frame)
Definition: af_dynaudnorm.c:658
cqueue::size
int size
Definition: af_dynaudnorm.c:51
val
static double val(void *priv, double ch)
Definition: aeval.c:77
DynamicAudioNormalizerContext::channels_to_filter
char * channels_to_filter
Definition: af_dynaudnorm.c:82
cqueue_create
static cqueue * cqueue_create(int size, int max_size)
Definition: af_dynaudnorm.c:147
pts
static int64_t pts
Definition: transcode_aac.c:654
activate
static int activate(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:842
update_value
static double update_value(double new, double old, double aggressiveness)
Definition: af_dynaudnorm.c:524
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
avfilter_af_dynaudnorm_outputs
static const AVFilterPad avfilter_af_dynaudnorm_outputs[]
Definition: af_dynaudnorm.c:931
DynamicAudioNormalizerContext::is_enabled
cqueue * is_enabled
Definition: af_dynaudnorm.c:91
DynamicAudioNormalizerContext::queue
struct FFBufQueue queue
Definition: af_dynaudnorm.c:59
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
cqueue::nb_elements
int nb_elements
Definition: af_dynaudnorm.c:53
ff_inlink_check_available_samples
int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min)
Test if enough samples are available on the link.
Definition: avfilter.c:1378
av_cold
#define av_cold
Definition: attributes.h:90
frame_size
static int frame_size(int sample_rate, int frame_len_msec)
Definition: af_dynaudnorm.c:141
minimum_filter
static double minimum_filter(cqueue *q)
Definition: af_dynaudnorm.c:439
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
s
#define s(width, name)
Definition: cbs_vp9.c:256
DynamicAudioNormalizerContext::ch_layout
AVChannelLayout ch_layout
Definition: af_dynaudnorm.c:83
cqueue_empty
static int cqueue_empty(cqueue *q)
Definition: af_dynaudnorm.c:183
adjust
static int adjust(int x, int size)
Definition: mobiclip.c:515
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:227
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
filters.h
DynamicAudioNormalizerContext::channels
int channels
Definition: af_dynaudnorm.c:79
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
copysign
static av_always_inline double copysign(double x, double y)
Definition: libm.h:68
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
cqueue_size
static int cqueue_size(cqueue *q)
Definition: af_dynaudnorm.c:178
DynamicAudioNormalizerContext::weights
double * weights
Definition: af_dynaudnorm.c:77
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:273
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:190
FLAGS
#define FLAGS
Definition: af_dynaudnorm.c:97
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
DynamicAudioNormalizerContext::peak_value
double peak_value
Definition: af_dynaudnorm.c:69
ff_inlink_consume_samples
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition: avfilter.c:1413
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:603
get_max_local_gain
static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:425
pow_2
static double pow_2(const double value)
Definition: af_dynaudnorm.c:367
perform_dc_correction
static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame)
Definition: af_dynaudnorm.c:537
ff_bufqueue_discard_all
static void ff_bufqueue_discard_all(struct FFBufQueue *queue)
Unref and remove all buffers from the queue.
Definition: bufferqueue.h:111
flush
static int flush(AVFilterLink *outlink)
Definition: af_dynaudnorm.c:822
DynamicAudioNormalizerContext::frame_len_msec
int frame_len_msec
Definition: af_dynaudnorm.c:62
exp
int8_t exp
Definition: eval.c:72
ff_inlink_acknowledge_status
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1348
DynamicAudioNormalizerContext::threshold_history
cqueue ** threshold_history
Definition: af_dynaudnorm.c:89
index
int index
Definition: gxfenc.c:89
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
cqueue_enqueue
static int cqueue_enqueue(cqueue *q, double element)
Definition: af_dynaudnorm.c:188
av_channel_layout_uninit
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
Definition: channel_layout.c:630
bufferqueue.h
minimum
static float minimum(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:47
compute_frame_std_dev
static double compute_frame_std_dev(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:582
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
DynamicAudioNormalizerContext::target_rms
double target_rms
Definition: af_dynaudnorm.c:71
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:290
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:771
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
DynamicAudioNormalizerContext::prev_amplification_factor
double * prev_amplification_factor
Definition: af_dynaudnorm.c:74
fmin
double fmin(double, double)
size
int size
Definition: twinvq_data.h:10344
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:533
cqueue_pop
static int cqueue_pop(cqueue *q)
Definition: af_dynaudnorm.c:215
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:863
cqueue_free
static void cqueue_free(cqueue *q)
Definition: af_dynaudnorm.c:171
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_dynaudnorm.c:894
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_dynaudnorm.c:749
ff_af_dynaudnorm
const AVFilter ff_af_dynaudnorm
Definition: af_dynaudnorm.c:938
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
FF_FILTER_FORWARD_WANTED
FF_FILTER_FORWARD_WANTED(outlink, inlink)
ff_bufqueue_add
static void ff_bufqueue_add(void *log, struct FFBufQueue *queue, AVFrame *buf)
Add a buffer to the queue.
Definition: bufferqueue.h:71
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
M_PI
#define M_PI
Definition: mathematics.h:52
internal.h
DynamicAudioNormalizerContext::compress_threshold
double * compress_threshold
Definition: af_dynaudnorm.c:76
update_gain_history
static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, local_gain gain)
Definition: af_dynaudnorm.c:469
DynamicAudioNormalizerContext::filter_size
int filter_size
Definition: af_dynaudnorm.c:63
av_samples_copy
int av_samples_copy(uint8_t **dst, uint8_t *const *src, int dst_offset, int src_offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Copy samples from src to dst.
Definition: samplefmt.c:222
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
DynamicAudioNormalizerContext::pts
int64_t pts
Definition: af_dynaudnorm.c:84
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:405
DynamicAudioNormalizerContext::threshold
double threshold
Definition: af_dynaudnorm.c:73
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
FFBufQueue
Structure holding the queue.
Definition: bufferqueue.h:49
DynamicAudioNormalizerContext::dc_correction
int dc_correction
Definition: af_dynaudnorm.c:64
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:386
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
weights
static const int weights[]
Definition: hevc_pel.c:32
DynamicAudioNormalizerContext::gain_history_minimum
cqueue ** gain_history_minimum
Definition: af_dynaudnorm.c:87
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
gaussian_filter
static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q, cqueue *tq)
Definition: af_dynaudnorm.c:450
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
av_channel_layout_index_from_channel
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
Definition: channel_layout.c:834
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
erf
static double erf(double z)
erf function Algorithm taken from the Boost project, source: http://www.boost.org/doc/libs/1_46_1/boo...
Definition: libm.h:121
av_channel_layout_channel_from_index
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
Definition: channel_layout.c:794
limit
static double limit(double x)
Definition: vf_pseudocolor.c:128
AVFilter
Filter definition.
Definition: avfilter.h:171
bound
static double bound(const double threshold, const double val)
Definition: af_dynaudnorm.c:372
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
cqueue_peek
static double cqueue_peek(cqueue *q, int index)
Definition: af_dynaudnorm.c:198
cqueue::elements
double * elements
Definition: af_dynaudnorm.c:50
pos
unsigned int pos
Definition: spdifenc.c:412
compute_frame_rms
static double compute_frame_rms(AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:399
cqueue
Definition: af_dynaudnorm.c:49
fmax
double fmax(double, double)
init_gaussian_filter
static void init_gaussian_filter(DynamicAudioNormalizerContext *s)
Definition: af_dynaudnorm.c:247
c2
static const uint64_t c2
Definition: murmur3.c:52
DynamicAudioNormalizerContext::sample_advance
int sample_advance
Definition: af_dynaudnorm.c:80
channel_layout.h
dynaudnorm_options
static const AVOption dynaudnorm_options[]
Definition: af_dynaudnorm.c:99
DynamicAudioNormalizerContext::gain_history_original
cqueue ** gain_history_original
Definition: af_dynaudnorm.c:86
av_channel_layout_from_string
int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str)
Initialize a channel layout from a given string description.
Definition: channel_layout.c:402
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
DynamicAudioNormalizerContext::alt_boundary_mode
int alt_boundary_mode
Definition: af_dynaudnorm.c:66
DynamicAudioNormalizerContext::compress_factor
double compress_factor
Definition: af_dynaudnorm.c:72
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
MIN_FILTER_SIZE
#define MIN_FILTER_SIZE
Definition: af_dynaudnorm.c:33
CONST
#define CONST(name, help, val, unit)
Definition: vf_bwdif.c:364
DynamicAudioNormalizerContext::frame_len
int frame_len
Definition: af_dynaudnorm.c:61
AVFilterContext
An instance of a filter.
Definition: avfilter.h:408
DynamicAudioNormalizerContext::eof
int eof
Definition: af_dynaudnorm.c:81
audio.h
local_gain::max_gain
double max_gain
Definition: af_dynaudnorm.c:45
llrint
#define llrint(x)
Definition: libm.h:394
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:139
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
bypass_channel
static int bypass_channel(DynamicAudioNormalizerContext *s, AVFrame *frame, int ch)
Definition: af_dynaudnorm.c:530
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:191
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
DynamicAudioNormalizerContext::channels_coupled
int channels_coupled
Definition: af_dynaudnorm.c:65
fade
static double fade(double prev, double next, int pos, int length)
Definition: af_dynaudnorm.c:359
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition: avfilter.h:160
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
perform_compression
static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame)
Definition: af_dynaudnorm.c:608
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
setup_compress_thresh
static double setup_compress_thresh(double threshold)
Definition: af_dynaudnorm.c:560
DynamicAudioNormalizerContext::max_amplification
double max_amplification
Definition: af_dynaudnorm.c:70
DynamicAudioNormalizerContext::gain_history_smoothed
cqueue ** gain_history_smoothed
Definition: af_dynaudnorm.c:88
cqueue_dequeue
static int cqueue_dequeue(cqueue *q, double *element)
Definition: af_dynaudnorm.c:204
channel
channel
Definition: ebur128.h:39
ff_filter_set_ready
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Definition: avfilter.c:191
local_gain::threshold
double threshold
Definition: af_dynaudnorm.c:46
min
float min
Definition: vorbis_enc_data.h:429