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"
30 #include "libavutil/opt.h"
31 
32 #define FF_BUFQUEUE_SIZE 302
34 
35 #include "audio.h"
36 #include "avfilter.h"
37 #include "filters.h"
38 #include "internal.h"
39 
40 typedef struct cqueue {
41  double *elements;
42  int size;
44  int first;
45 } cqueue;
46 
48  const AVClass *class;
49 
50  struct FFBufQueue queue;
51 
52  int frame_len;
58 
59  double peak_value;
61  double target_rms;
66  double *fade_factors[2];
67  double *weights;
68 
69  int channels;
70  int delay;
71  int eof;
72  int64_t pts;
73 
77 
80 
81 #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x)
82 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
83 
84 static const AVOption dynaudnorm_options[] = {
85  { "framelen", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
86  { "f", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
87  { "gausssize", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
88  { "g", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
89  { "peak", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
90  { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
91  { "maxgain", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
92  { "m", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
93  { "targetrms", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
94  { "r", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
95  { "coupling", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
96  { "n", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
97  { "correctdc", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
98  { "c", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
99  { "altboundary", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
100  { "b", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
101  { "compress", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
102  { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
103  { NULL }
104 };
105 
106 AVFILTER_DEFINE_CLASS(dynaudnorm);
107 
109 {
111 
112  if (!(s->filter_size & 1)) {
113  av_log(ctx, AV_LOG_ERROR, "filter size %d is invalid. Must be an odd value.\n", s->filter_size);
114  return AVERROR(EINVAL);
115  }
116 
117  return 0;
118 }
119 
121 {
124  static const enum AVSampleFormat sample_fmts[] = {
127  };
128  int ret;
129 
130  layouts = ff_all_channel_counts();
131  if (!layouts)
132  return AVERROR(ENOMEM);
133  ret = ff_set_common_channel_layouts(ctx, layouts);
134  if (ret < 0)
135  return ret;
136 
137  formats = ff_make_format_list(sample_fmts);
138  if (!formats)
139  return AVERROR(ENOMEM);
140  ret = ff_set_common_formats(ctx, formats);
141  if (ret < 0)
142  return ret;
143 
144  formats = ff_all_samplerates();
145  if (!formats)
146  return AVERROR(ENOMEM);
147  return ff_set_common_samplerates(ctx, formats);
148 }
149 
150 static inline int frame_size(int sample_rate, int frame_len_msec)
151 {
152  const int frame_size = lrint((double)sample_rate * (frame_len_msec / 1000.0));
153  return frame_size + (frame_size % 2);
154 }
155 
156 static void precalculate_fade_factors(double *fade_factors[2], int frame_len)
157 {
158  const double step_size = 1.0 / frame_len;
159  int pos;
160 
161  for (pos = 0; pos < frame_len; pos++) {
162  fade_factors[0][pos] = 1.0 - (step_size * (pos + 1.0));
163  fade_factors[1][pos] = 1.0 - fade_factors[0][pos];
164  }
165 }
166 
168 {
169  cqueue *q;
170 
171  q = av_malloc(sizeof(cqueue));
172  if (!q)
173  return NULL;
174 
175  q->size = size;
176  q->nb_elements = 0;
177  q->first = 0;
178 
179  q->elements = av_malloc_array(size, sizeof(double));
180  if (!q->elements) {
181  av_free(q);
182  return NULL;
183  }
184 
185  return q;
186 }
187 
188 static void cqueue_free(cqueue *q)
189 {
190  if (q)
191  av_free(q->elements);
192  av_free(q);
193 }
194 
195 static int cqueue_size(cqueue *q)
196 {
197  return q->nb_elements;
198 }
199 
200 static int cqueue_empty(cqueue *q)
201 {
202  return !q->nb_elements;
203 }
204 
205 static int cqueue_enqueue(cqueue *q, double element)
206 {
207  int i;
208 
209  av_assert2(q->nb_elements != q->size);
210 
211  i = (q->first + q->nb_elements) % q->size;
212  q->elements[i] = element;
213  q->nb_elements++;
214 
215  return 0;
216 }
217 
218 static double cqueue_peek(cqueue *q, int index)
219 {
220  av_assert2(index < q->nb_elements);
221  return q->elements[(q->first + index) % q->size];
222 }
223 
224 static int cqueue_dequeue(cqueue *q, double *element)
225 {
227 
228  *element = q->elements[q->first];
229  q->first = (q->first + 1) % q->size;
230  q->nb_elements--;
231 
232  return 0;
233 }
234 
235 static int cqueue_pop(cqueue *q)
236 {
238 
239  q->first = (q->first + 1) % q->size;
240  q->nb_elements--;
241 
242  return 0;
243 }
244 
246 {
247  double total_weight = 0.0;
248  const double sigma = (((s->filter_size / 2.0) - 1.0) / 3.0) + (1.0 / 3.0);
249  double adjust;
250  int i;
251 
252  // Pre-compute constants
253  const int offset = s->filter_size / 2;
254  const double c1 = 1.0 / (sigma * sqrt(2.0 * M_PI));
255  const double c2 = 2.0 * sigma * sigma;
256 
257  // Compute weights
258  for (i = 0; i < s->filter_size; i++) {
259  const int x = i - offset;
260 
261  s->weights[i] = c1 * exp(-x * x / c2);
262  total_weight += s->weights[i];
263  }
264 
265  // Adjust weights
266  adjust = 1.0 / total_weight;
267  for (i = 0; i < s->filter_size; i++) {
268  s->weights[i] *= adjust;
269  }
270 }
271 
273 {
275  int c;
276 
280  av_freep(&s->fade_factors[0]);
281  av_freep(&s->fade_factors[1]);
282 
283  for (c = 0; c < s->channels; c++) {
284  if (s->gain_history_original)
286  if (s->gain_history_minimum)
288  if (s->gain_history_smoothed)
290  }
291 
295 
297  s->is_enabled = NULL;
298 
299  av_freep(&s->weights);
300 
302 }
303 
305 {
306  AVFilterContext *ctx = inlink->dst;
308  int c;
309 
310  uninit(ctx);
311 
313  av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len);
314 
315  s->fade_factors[0] = av_malloc_array(s->frame_len, sizeof(*s->fade_factors[0]));
316  s->fade_factors[1] = av_malloc_array(s->frame_len, sizeof(*s->fade_factors[1]));
317 
319  s->dc_correction_value = av_calloc(inlink->channels, sizeof(*s->dc_correction_value));
320  s->compress_threshold = av_calloc(inlink->channels, sizeof(*s->compress_threshold));
322  s->gain_history_minimum = av_calloc(inlink->channels, sizeof(*s->gain_history_minimum));
324  s->weights = av_malloc_array(s->filter_size, sizeof(*s->weights));
327  !s->compress_threshold || !s->fade_factors[0] || !s->fade_factors[1] ||
329  !s->gain_history_smoothed || !s->is_enabled || !s->weights)
330  return AVERROR(ENOMEM);
331 
332  for (c = 0; c < inlink->channels; c++) {
333  s->prev_amplification_factor[c] = 1.0;
334 
338 
339  if (!s->gain_history_original[c] || !s->gain_history_minimum[c] ||
340  !s->gain_history_smoothed[c])
341  return AVERROR(ENOMEM);
342  }
343 
346 
347  s->channels = inlink->channels;
348  s->delay = s->filter_size;
349 
350  return 0;
351 }
352 
353 static inline double fade(double prev, double next, int pos,
354  double *fade_factors[2])
355 {
356  return fade_factors[0][pos] * prev + fade_factors[1][pos] * next;
357 }
358 
359 static inline double pow_2(const double value)
360 {
361  return value * value;
362 }
363 
364 static inline double bound(const double threshold, const double val)
365 {
366  const double CONST = 0.8862269254527580136490837416705725913987747280611935; //sqrt(PI) / 2.0
367  return erf(CONST * (val / threshold)) * threshold;
368 }
369 
371 {
372  double max = DBL_EPSILON;
373  int c, i;
374 
375  if (channel == -1) {
376  for (c = 0; c < frame->channels; c++) {
377  double *data_ptr = (double *)frame->extended_data[c];
378 
379  for (i = 0; i < frame->nb_samples; i++)
380  max = FFMAX(max, fabs(data_ptr[i]));
381  }
382  } else {
383  double *data_ptr = (double *)frame->extended_data[channel];
384 
385  for (i = 0; i < frame->nb_samples; i++)
386  max = FFMAX(max, fabs(data_ptr[i]));
387  }
388 
389  return max;
390 }
391 
393 {
394  double rms_value = 0.0;
395  int c, i;
396 
397  if (channel == -1) {
398  for (c = 0; c < frame->channels; c++) {
399  const double *data_ptr = (double *)frame->extended_data[c];
400 
401  for (i = 0; i < frame->nb_samples; i++) {
402  rms_value += pow_2(data_ptr[i]);
403  }
404  }
405 
406  rms_value /= frame->nb_samples * frame->channels;
407  } else {
408  const double *data_ptr = (double *)frame->extended_data[channel];
409  for (i = 0; i < frame->nb_samples; i++) {
410  rms_value += pow_2(data_ptr[i]);
411  }
412 
413  rms_value /= frame->nb_samples;
414  }
415 
416  return FFMAX(sqrt(rms_value), DBL_EPSILON);
417 }
418 
420  int channel)
421 {
422  const double maximum_gain = s->peak_value / find_peak_magnitude(frame, channel);
423  const double rms_gain = s->target_rms > DBL_EPSILON ? (s->target_rms / compute_frame_rms(frame, channel)) : DBL_MAX;
424  return bound(s->max_amplification, FFMIN(maximum_gain, rms_gain));
425 }
426 
427 static double minimum_filter(cqueue *q)
428 {
429  double min = DBL_MAX;
430  int i;
431 
432  for (i = 0; i < cqueue_size(q); i++) {
433  min = FFMIN(min, cqueue_peek(q, i));
434  }
435 
436  return min;
437 }
438 
440 {
441  double result = 0.0;
442  int i;
443 
444  for (i = 0; i < cqueue_size(q); i++) {
445  result += cqueue_peek(q, i) * s->weights[i];
446  }
447 
448  return result;
449 }
450 
452  double current_gain_factor)
453 {
454  if (cqueue_empty(s->gain_history_original[channel]) ||
455  cqueue_empty(s->gain_history_minimum[channel])) {
456  const int pre_fill_size = s->filter_size / 2;
457  const double initial_value = s->alt_boundary_mode ? current_gain_factor : 1.0;
458 
459  s->prev_amplification_factor[channel] = initial_value;
460 
461  while (cqueue_size(s->gain_history_original[channel]) < pre_fill_size) {
462  cqueue_enqueue(s->gain_history_original[channel], initial_value);
463  }
464  }
465 
466  cqueue_enqueue(s->gain_history_original[channel], current_gain_factor);
467 
468  while (cqueue_size(s->gain_history_original[channel]) >= s->filter_size) {
469  double minimum;
471 
472  if (cqueue_empty(s->gain_history_minimum[channel])) {
473  const int pre_fill_size = s->filter_size / 2;
474  double initial_value = s->alt_boundary_mode ? cqueue_peek(s->gain_history_original[channel], 0) : 1.0;
475  int input = pre_fill_size;
476 
477  while (cqueue_size(s->gain_history_minimum[channel]) < pre_fill_size) {
478  input++;
479  initial_value = FFMIN(initial_value, cqueue_peek(s->gain_history_original[channel], input));
480  cqueue_enqueue(s->gain_history_minimum[channel], initial_value);
481  }
482  }
483 
484  minimum = minimum_filter(s->gain_history_original[channel]);
485 
486  cqueue_enqueue(s->gain_history_minimum[channel], minimum);
487 
488  cqueue_pop(s->gain_history_original[channel]);
489  }
490 
491  while (cqueue_size(s->gain_history_minimum[channel]) >= s->filter_size) {
492  double smoothed;
494  smoothed = gaussian_filter(s, s->gain_history_minimum[channel]);
495 
496  cqueue_enqueue(s->gain_history_smoothed[channel], smoothed);
497 
498  cqueue_pop(s->gain_history_minimum[channel]);
499  }
500 }
501 
502 static inline double update_value(double new, double old, double aggressiveness)
503 {
504  av_assert0((aggressiveness >= 0.0) && (aggressiveness <= 1.0));
505  return aggressiveness * new + (1.0 - aggressiveness) * old;
506 }
507 
509 {
510  const double diff = 1.0 / frame->nb_samples;
511  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
512  int c, i;
513 
514  for (c = 0; c < s->channels; c++) {
515  double *dst_ptr = (double *)frame->extended_data[c];
516  double current_average_value = 0.0;
517  double prev_value;
518 
519  for (i = 0; i < frame->nb_samples; i++)
520  current_average_value += dst_ptr[i] * diff;
521 
522  prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c];
523  s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1);
524 
525  for (i = 0; i < frame->nb_samples; i++) {
526  dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, s->fade_factors);
527  }
528  }
529 }
530 
531 static double setup_compress_thresh(double threshold)
532 {
533  if ((threshold > DBL_EPSILON) && (threshold < (1.0 - DBL_EPSILON))) {
534  double current_threshold = threshold;
535  double step_size = 1.0;
536 
537  while (step_size > DBL_EPSILON) {
538  while ((llrint((current_threshold + step_size) * (UINT64_C(1) << 63)) >
539  llrint(current_threshold * (UINT64_C(1) << 63))) &&
540  (bound(current_threshold + step_size, 1.0) <= threshold)) {
541  current_threshold += step_size;
542  }
543 
544  step_size /= 2.0;
545  }
546 
547  return current_threshold;
548  } else {
549  return threshold;
550  }
551 }
552 
554  AVFrame *frame, int channel)
555 {
556  double variance = 0.0;
557  int i, c;
558 
559  if (channel == -1) {
560  for (c = 0; c < s->channels; c++) {
561  const double *data_ptr = (double *)frame->extended_data[c];
562 
563  for (i = 0; i < frame->nb_samples; i++) {
564  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
565  }
566  }
567  variance /= (s->channels * frame->nb_samples) - 1;
568  } else {
569  const double *data_ptr = (double *)frame->extended_data[channel];
570 
571  for (i = 0; i < frame->nb_samples; i++) {
572  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
573  }
574  variance /= frame->nb_samples - 1;
575  }
576 
577  return FFMAX(sqrt(variance), DBL_EPSILON);
578 }
579 
581 {
582  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
583  int c, i;
584 
585  if (s->channels_coupled) {
586  const double standard_deviation = compute_frame_std_dev(s, frame, -1);
587  const double current_threshold = FFMIN(1.0, s->compress_factor * standard_deviation);
588 
589  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[0];
590  double prev_actual_thresh, curr_actual_thresh;
591  s->compress_threshold[0] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[0], (1.0/3.0));
592 
593  prev_actual_thresh = setup_compress_thresh(prev_value);
594  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[0]);
595 
596  for (c = 0; c < s->channels; c++) {
597  double *const dst_ptr = (double *)frame->extended_data[c];
598  for (i = 0; i < frame->nb_samples; i++) {
599  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, s->fade_factors);
600  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
601  }
602  }
603  } else {
604  for (c = 0; c < s->channels; c++) {
605  const double standard_deviation = compute_frame_std_dev(s, frame, c);
606  const double current_threshold = setup_compress_thresh(FFMIN(1.0, s->compress_factor * standard_deviation));
607 
608  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c];
609  double prev_actual_thresh, curr_actual_thresh;
610  double *dst_ptr;
611  s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0);
612 
613  prev_actual_thresh = setup_compress_thresh(prev_value);
614  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]);
615 
616  dst_ptr = (double *)frame->extended_data[c];
617  for (i = 0; i < frame->nb_samples; i++) {
618  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, s->fade_factors);
619  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
620  }
621  }
622  }
623 }
624 
626 {
627  if (s->dc_correction) {
628  perform_dc_correction(s, frame);
629  }
630 
631  if (s->compress_factor > DBL_EPSILON) {
632  perform_compression(s, frame);
633  }
634 
635  if (s->channels_coupled) {
636  const double current_gain_factor = get_max_local_gain(s, frame, -1);
637  int c;
638 
639  for (c = 0; c < s->channels; c++)
640  update_gain_history(s, c, current_gain_factor);
641  } else {
642  int c;
643 
644  for (c = 0; c < s->channels; c++)
645  update_gain_history(s, c, get_max_local_gain(s, frame, c));
646  }
647 }
648 
650 {
651  int c, i;
652 
653  for (c = 0; c < s->channels; c++) {
654  double *dst_ptr = (double *)frame->extended_data[c];
655  double current_amplification_factor;
656 
657  cqueue_dequeue(s->gain_history_smoothed[c], &current_amplification_factor);
658 
659  for (i = 0; i < frame->nb_samples && enabled; i++) {
660  const double amplification_factor = fade(s->prev_amplification_factor[c],
661  current_amplification_factor, i,
662  s->fade_factors);
663 
664  dst_ptr[i] *= amplification_factor;
665 
666  if (fabs(dst_ptr[i]) > s->peak_value)
667  dst_ptr[i] = copysign(s->peak_value, dst_ptr[i]);
668  }
669 
670  s->prev_amplification_factor[c] = current_amplification_factor;
671  }
672 }
673 
675 {
676  AVFilterContext *ctx = inlink->dst;
678  AVFilterLink *outlink = inlink->dst->outputs[0];
679  int ret = 1;
680 
681  if (!cqueue_empty(s->gain_history_smoothed[0])) {
682  double is_enabled;
684 
685  cqueue_dequeue(s->is_enabled, &is_enabled);
686 
687  amplify_frame(s, out, is_enabled > 0.);
688  ret = ff_filter_frame(outlink, out);
689  }
690 
693  analyze_frame(s, in);
694  ff_bufqueue_add(ctx, &s->queue, in);
695 
696  return ret;
697 }
698 
700  AVFilterLink *outlink)
701 {
702  AVFrame *out = ff_get_audio_buffer(outlink, s->frame_len);
703  int c, i;
704 
705  if (!out)
706  return AVERROR(ENOMEM);
707 
708  for (c = 0; c < s->channels; c++) {
709  double *dst_ptr = (double *)out->extended_data[c];
710 
711  for (i = 0; i < out->nb_samples; i++) {
712  dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? FFMIN(s->peak_value, s->target_rms) : s->peak_value);
713  if (s->dc_correction) {
714  dst_ptr[i] *= ((i % 2) == 1) ? -1 : 1;
715  dst_ptr[i] += s->dc_correction_value[c];
716  }
717  }
718  }
719 
720  s->delay--;
721  return filter_frame(inlink, out);
722 }
723 
724 static int flush(AVFilterLink *outlink)
725 {
726  AVFilterContext *ctx = outlink->src;
728  int ret = 0;
729 
730  if (!cqueue_empty(s->gain_history_smoothed[0])) {
731  ret = flush_buffer(s, ctx->inputs[0], outlink);
732  } else if (s->queue.available) {
734 
735  s->pts = out->pts;
736  ret = ff_filter_frame(outlink, out);
737  s->delay = s->queue.available;
738  }
739 
740  return ret;
741 }
742 
744 {
745  AVFilterLink *inlink = ctx->inputs[0];
746  AVFilterLink *outlink = ctx->outputs[0];
748  AVFrame *in = NULL;
749  int ret = 0, status;
750  int64_t pts;
751 
752  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
753 
754  if (!s->eof) {
755  ret = ff_inlink_consume_samples(inlink, s->frame_len, s->frame_len, &in);
756  if (ret < 0)
757  return ret;
758  if (ret > 0) {
759  ret = filter_frame(inlink, in);
760  if (ret <= 0)
761  return ret;
762  }
763 
764  if (ff_inlink_queued_samples(inlink) >= s->frame_len) {
765  ff_filter_set_ready(ctx, 10);
766  return 0;
767  }
768  }
769 
770  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
771  if (status == AVERROR_EOF)
772  s->eof = 1;
773  }
774 
775  if (s->eof && s->delay > 0)
776  return flush(outlink);
777 
778  if (s->eof && s->delay <= 0) {
779  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
780  return 0;
781  }
782 
783  if (!s->eof)
784  FF_FILTER_FORWARD_WANTED(outlink, inlink);
785 
786  return FFERROR_NOT_READY;
787 }
788 
790  {
791  .name = "default",
792  .type = AVMEDIA_TYPE_AUDIO,
793  .config_props = config_input,
794  },
795  { NULL }
796 };
797 
799  {
800  .name = "default",
801  .type = AVMEDIA_TYPE_AUDIO,
802  },
803  { NULL }
804 };
805 
807  .name = "dynaudnorm",
808  .description = NULL_IF_CONFIG_SMALL("Dynamic Audio Normalizer."),
809  .query_formats = query_formats,
810  .priv_size = sizeof(DynamicAudioNormalizerContext),
811  .init = init,
812  .uninit = uninit,
813  .activate = activate,
814  .inputs = avfilter_af_dynaudnorm_inputs,
815  .outputs = avfilter_af_dynaudnorm_outputs,
816  .priv_class = &dynaudnorm_class,
818 };
static AVFrame * ff_bufqueue_get(struct FFBufQueue *queue)
Get the first buffer from the queue and remove it.
Definition: bufferqueue.h:98
static const AVFilterPad avfilter_af_dynaudnorm_inputs[]
#define FLAGS
Definition: af_dynaudnorm.c:82
static double bound(const double threshold, const double val)
#define NULL
Definition: coverity.c:32
int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:550
const char const char void * val
Definition: avisynth_c.h:863
static double compute_frame_rms(AVFrame *frame, int channel)
static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *frame, int enabled)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
#define CONST(name, help, val, unit)
Definition: vf_bwdif.c:373
static int cqueue_empty(cqueue *q)
static const AVFilterPad avfilter_af_dynaudnorm_outputs[]
static double pow_2(const double value)
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
Main libavfilter public API header.
static int cqueue_size(cqueue *q)
int first
Definition: af_dynaudnorm.c:44
double, planar
Definition: samplefmt.h:70
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static double get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
return FFERROR_NOT_READY
static void analyze_frame(DynamicAudioNormalizerContext *s, AVFrame *frame)
static void precalculate_fade_factors(double *fade_factors[2], int frame_len)
int is_disabled
the enabled state from the last expression evaluation
Definition: avfilter.h:385
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
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
static int config_input(AVFilterLink *inlink)
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
Structure holding the queue.
Definition: bufferqueue.h:49
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1093
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
AVOptions.
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
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
static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q)
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
double * elements
Definition: af_dynaudnorm.c:41
static const uint64_t c1
Definition: murmur3.c:49
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define max(a, b)
Definition: cuda_runtime.h:33
ptrdiff_t size
Definition: opengl_enc.c:100
static av_cold void uninit(AVFilterContext *ctx)
static void cqueue_free(cqueue *q)
#define av_log(a,...)
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
A filter pad used for either input or output.
Definition: internal.h:54
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:1449
static int flush_buffer(DynamicAudioNormalizerContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
static int query_formats(AVFilterContext *ctx)
static double cqueue_peek(cqueue *q, int index)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:569
static void init_gaussian_filter(DynamicAudioNormalizerContext *s)
AVFILTER_DEFINE_CLASS(dynaudnorm)
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:86
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
simple assert() macros that are a bit more flexible than ISO C assert().
#define OFFSET(x)
Definition: af_dynaudnorm.c:81
#define FFMAX(a, b)
Definition: common.h:94
int8_t exp
Definition: eval.c:72
AVFrame * queue[FF_BUFQUEUE_SIZE]
Definition: bufferqueue.h:50
int channels
number of audio channels, only used for audio.
Definition: frame.h:601
#define FFMIN(a, b)
Definition: common.h:96
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1474
static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame)
static int flush(AVFilterLink *outlink)
AVFormatContext * ctx
Definition: movenc.c:48
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
#define s(width, name)
Definition: cbs_vp9.c:257
int size
Definition: af_dynaudnorm.c:42
static void ff_bufqueue_discard_all(struct FFBufQueue *queue)
Unref and remove all buffers from the queue.
Definition: bufferqueue.h:111
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
A list of supported channel layouts.
Definition: formats.h:85
sample_rate
int nb_elements
Definition: af_dynaudnorm.c:43
AVFilter ff_af_dynaudnorm
static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, double current_gain_factor)
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
unsigned short available
number of available buffers
Definition: bufferqueue.h:52
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1513
static double compute_frame_std_dev(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
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 inputs
#define llrint(x)
Definition: libm.h:394
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
static av_cold int init(AVFilterContext *ctx)
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
int index
Definition: gxfenc.c:89
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
const char * name
Filter name.
Definition: avfilter.h:148
static av_always_inline double copysign(double x, double y)
Definition: libm.h:68
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
static double setup_compress_thresh(double threshold)
#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:133
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:394
static int64_t pts
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:611
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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
static double find_peak_magnitude(AVFrame *frame, int channel)
static int cqueue_pop(cqueue *q)
static double minimum_filter(cqueue *q)
channel
Use these values when setting the channel map with ebur128_set_channel().
Definition: ebur128.h:39
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Definition: avfilter.c:193
static const uint64_t c2
Definition: murmur3.c:50
FF_FILTER_FORWARD_WANTED(outlink, inlink)
static int cqueue_enqueue(cqueue *q, double element)
static double fade(double prev, double next, int pos, double *fade_factors[2])
static av_always_inline int diff(const uint32_t a, const uint32_t b)
#define av_free(p)
static double update_value(double new, double old, double aggressiveness)
static int activate(AVFilterContext *ctx)
A list of supported formats for one end of a filter link.
Definition: formats.h:64
#define lrint
Definition: tablegen.h:53
An instance of a filter.
Definition: avfilter.h:338
and forward the result(frame or status change) to the corresponding input.If nothing is possible
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define M_PI
Definition: mathematics.h:52
static void ff_bufqueue_add(void *log, struct FFBufQueue *queue, AVFrame *buf)
Add a buffer to the queue.
Definition: bufferqueue.h:71
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
static cqueue * cqueue_create(int size)
static const AVOption dynaudnorm_options[]
Definition: af_dynaudnorm.c:84
internal API functions
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
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition...
Definition: formats.c:409
static int cqueue_dequeue(cqueue *q, double *element)
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
float min
static int frame_size(int sample_rate, int frame_len_msec)
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:361
for(j=16;j >0;--j)
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:557
static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame)