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 MIN_FILTER_SIZE 3
33 #define MAX_FILTER_SIZE 301
34 
35 #define FF_BUFQUEUE_SIZE (MAX_FILTER_SIZE + 1)
37 
38 #include "audio.h"
39 #include "avfilter.h"
40 #include "filters.h"
41 #include "internal.h"
42 
43 typedef struct local_gain {
44  double max_gain;
45  double threshold;
46 } local_gain;
47 
48 typedef struct cqueue {
49  double *elements;
50  int size;
51  int max_size;
53 } cqueue;
54 
56  const AVClass *class;
57 
58  struct FFBufQueue queue;
59 
60  int frame_len;
66 
67  double peak_value;
69  double target_rms;
71  double threshold;
75  double *weights;
76 
77  int channels;
78  int eof;
79  int64_t pts;
80 
85 
88 
89 #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x)
90 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
91 
92 static const AVOption dynaudnorm_options[] = {
93  { "framelen", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
94  { "f", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS },
95  { "gausssize", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
96  { "g", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS },
97  { "peak", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
98  { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS },
99  { "maxgain", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
100  { "m", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS },
101  { "targetrms", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
102  { "r", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
103  { "coupling", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
104  { "n", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
105  { "correctdc", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
106  { "c", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
107  { "altboundary", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
108  { "b", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
109  { "compress", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
110  { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
111  { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
112  { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
113  { NULL }
114 };
115 
116 AVFILTER_DEFINE_CLASS(dynaudnorm);
117 
119 {
121 
122  if (!(s->filter_size & 1)) {
123  av_log(ctx, AV_LOG_WARNING, "filter size %d is invalid. Changing to an odd value.\n", s->filter_size);
124  s->filter_size |= 1;
125  }
126 
127  return 0;
128 }
129 
131 {
134  static const enum AVSampleFormat sample_fmts[] = {
137  };
138  int ret;
139 
140  layouts = ff_all_channel_counts();
141  if (!layouts)
142  return AVERROR(ENOMEM);
143  ret = ff_set_common_channel_layouts(ctx, layouts);
144  if (ret < 0)
145  return ret;
146 
147  formats = ff_make_format_list(sample_fmts);
148  if (!formats)
149  return AVERROR(ENOMEM);
150  ret = ff_set_common_formats(ctx, formats);
151  if (ret < 0)
152  return ret;
153 
154  formats = ff_all_samplerates();
155  if (!formats)
156  return AVERROR(ENOMEM);
157  return ff_set_common_samplerates(ctx, formats);
158 }
159 
160 static inline int frame_size(int sample_rate, int frame_len_msec)
161 {
162  const int frame_size = lrint((double)sample_rate * (frame_len_msec / 1000.0));
163  return frame_size + (frame_size % 2);
164 }
165 
166 static cqueue *cqueue_create(int size, int max_size)
167 {
168  cqueue *q;
169 
170  if (max_size < size)
171  return NULL;
172 
173  q = av_malloc(sizeof(cqueue));
174  if (!q)
175  return NULL;
176 
177  q->max_size = max_size;
178  q->size = size;
179  q->nb_elements = 0;
180 
181  q->elements = av_malloc_array(max_size, sizeof(double));
182  if (!q->elements) {
183  av_free(q);
184  return NULL;
185  }
186 
187  return q;
188 }
189 
190 static void cqueue_free(cqueue *q)
191 {
192  if (q)
193  av_free(q->elements);
194  av_free(q);
195 }
196 
197 static int cqueue_size(cqueue *q)
198 {
199  return q->nb_elements;
200 }
201 
202 static int cqueue_empty(cqueue *q)
203 {
204  return q->nb_elements <= 0;
205 }
206 
207 static int cqueue_enqueue(cqueue *q, double element)
208 {
210 
211  q->elements[q->nb_elements] = element;
212  q->nb_elements++;
213 
214  return 0;
215 }
216 
217 static double cqueue_peek(cqueue *q, int index)
218 {
219  av_assert2(index < q->nb_elements);
220  return q->elements[index];
221 }
222 
223 static int cqueue_dequeue(cqueue *q, double *element)
224 {
226 
227  *element = q->elements[0];
228  memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double));
229  q->nb_elements--;
230 
231  return 0;
232 }
233 
234 static int cqueue_pop(cqueue *q)
235 {
237 
238  memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double));
239  q->nb_elements--;
240 
241  return 0;
242 }
243 
244 static void cqueue_resize(cqueue *q, int new_size)
245 {
246  av_assert2(q->max_size >= new_size);
247  av_assert2(MIN_FILTER_SIZE <= new_size);
248 
249  if (new_size > q->nb_elements) {
250  const int side = (new_size - q->nb_elements) / 2;
251 
252  memmove(q->elements + side, q->elements, sizeof(double) * q->nb_elements);
253  for (int i = 0; i < side; i++)
254  q->elements[i] = q->elements[side];
255  q->nb_elements = new_size - 1 - side;
256  } else {
257  int count = (q->size - new_size + 1) / 2;
258 
259  while (count-- > 0)
260  cqueue_pop(q);
261  }
262 
263  q->size = new_size;
264 }
265 
267 {
268  double total_weight = 0.0;
269  const double sigma = (((s->filter_size / 2.0) - 1.0) / 3.0) + (1.0 / 3.0);
270  double adjust;
271  int i;
272 
273  // Pre-compute constants
274  const int offset = s->filter_size / 2;
275  const double c1 = 1.0 / (sigma * sqrt(2.0 * M_PI));
276  const double c2 = 2.0 * sigma * sigma;
277 
278  // Compute weights
279  for (i = 0; i < s->filter_size; i++) {
280  const int x = i - offset;
281 
282  s->weights[i] = c1 * exp(-x * x / c2);
283  total_weight += s->weights[i];
284  }
285 
286  // Adjust weights
287  adjust = 1.0 / total_weight;
288  for (i = 0; i < s->filter_size; i++) {
289  s->weights[i] *= adjust;
290  }
291 }
292 
294 {
296  int c;
297 
301 
302  for (c = 0; c < s->channels; c++) {
303  if (s->gain_history_original)
305  if (s->gain_history_minimum)
307  if (s->gain_history_smoothed)
309  if (s->threshold_history)
311  }
312 
317 
319  s->is_enabled = NULL;
320 
321  av_freep(&s->weights);
322 
324 }
325 
327 {
328  AVFilterContext *ctx = inlink->dst;
330  int c;
331 
332  uninit(ctx);
333 
334  s->channels = inlink->channels;
336  av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len);
337 
339  s->dc_correction_value = av_calloc(inlink->channels, sizeof(*s->dc_correction_value));
340  s->compress_threshold = av_calloc(inlink->channels, sizeof(*s->compress_threshold));
342  s->gain_history_minimum = av_calloc(inlink->channels, sizeof(*s->gain_history_minimum));
344  s->threshold_history = av_calloc(inlink->channels, sizeof(*s->threshold_history));
345  s->weights = av_malloc_array(MAX_FILTER_SIZE, sizeof(*s->weights));
348  !s->compress_threshold ||
351  !s->is_enabled || !s->weights)
352  return AVERROR(ENOMEM);
353 
354  for (c = 0; c < inlink->channels; c++) {
355  s->prev_amplification_factor[c] = 1.0;
356 
361 
362  if (!s->gain_history_original[c] || !s->gain_history_minimum[c] ||
363  !s->gain_history_smoothed[c] || !s->threshold_history[c])
364  return AVERROR(ENOMEM);
365  }
366 
368 
369  return 0;
370 }
371 
372 static inline double fade(double prev, double next, int pos, int length)
373 {
374  const double step_size = 1.0 / length;
375  const double f0 = 1.0 - (step_size * (pos + 1.0));
376  const double f1 = 1.0 - f0;
377  return f0 * prev + f1 * next;
378 }
379 
380 static inline double pow_2(const double value)
381 {
382  return value * value;
383 }
384 
385 static inline double bound(const double threshold, const double val)
386 {
387  const double CONST = 0.8862269254527580136490837416705725913987747280611935; //sqrt(PI) / 2.0
388  return erf(CONST * (val / threshold)) * threshold;
389 }
390 
392 {
393  double max = DBL_EPSILON;
394  int c, i;
395 
396  if (channel == -1) {
397  for (c = 0; c < frame->channels; c++) {
398  double *data_ptr = (double *)frame->extended_data[c];
399 
400  for (i = 0; i < frame->nb_samples; i++)
401  max = FFMAX(max, fabs(data_ptr[i]));
402  }
403  } else {
404  double *data_ptr = (double *)frame->extended_data[channel];
405 
406  for (i = 0; i < frame->nb_samples; i++)
407  max = FFMAX(max, fabs(data_ptr[i]));
408  }
409 
410  return max;
411 }
412 
414 {
415  double rms_value = 0.0;
416  int c, i;
417 
418  if (channel == -1) {
419  for (c = 0; c < frame->channels; c++) {
420  const double *data_ptr = (double *)frame->extended_data[c];
421 
422  for (i = 0; i < frame->nb_samples; i++) {
423  rms_value += pow_2(data_ptr[i]);
424  }
425  }
426 
427  rms_value /= frame->nb_samples * frame->channels;
428  } else {
429  const double *data_ptr = (double *)frame->extended_data[channel];
430  for (i = 0; i < frame->nb_samples; i++) {
431  rms_value += pow_2(data_ptr[i]);
432  }
433 
434  rms_value /= frame->nb_samples;
435  }
436 
437  return FFMAX(sqrt(rms_value), DBL_EPSILON);
438 }
439 
441  int channel)
442 {
443  const double peak_magnitude = find_peak_magnitude(frame, channel);
444  const double maximum_gain = s->peak_value / peak_magnitude;
445  const double rms_gain = s->target_rms > DBL_EPSILON ? (s->target_rms / compute_frame_rms(frame, channel)) : DBL_MAX;
446  local_gain gain;
447 
448  gain.threshold = peak_magnitude > s->threshold;
449  gain.max_gain = bound(s->max_amplification, FFMIN(maximum_gain, rms_gain));
450 
451  return gain;
452 }
453 
454 static double minimum_filter(cqueue *q)
455 {
456  double min = DBL_MAX;
457  int i;
458 
459  for (i = 0; i < cqueue_size(q); i++) {
460  min = FFMIN(min, cqueue_peek(q, i));
461  }
462 
463  return min;
464 }
465 
467 {
468  double result = 0.0, tsum = 0.0;
469  int i;
470 
471  for (i = 0; i < cqueue_size(q); i++) {
472  tsum += cqueue_peek(tq, i) * s->weights[i];
473  result += cqueue_peek(q, i) * s->weights[i] * cqueue_peek(tq, i);
474  }
475 
476  if (tsum == 0.0)
477  result = 1.0;
478 
479  return result;
480 }
481 
483  local_gain gain)
484 {
485  if (cqueue_empty(s->gain_history_original[channel])) {
486  const int pre_fill_size = s->filter_size / 2;
487  const double initial_value = s->alt_boundary_mode ? gain.max_gain : s->peak_value;
488 
489  s->prev_amplification_factor[channel] = initial_value;
490 
491  while (cqueue_size(s->gain_history_original[channel]) < pre_fill_size) {
492  cqueue_enqueue(s->gain_history_original[channel], initial_value);
493  cqueue_enqueue(s->threshold_history[channel], gain.threshold);
494  }
495  }
496 
497  cqueue_enqueue(s->gain_history_original[channel], gain.max_gain);
498 
499  while (cqueue_size(s->gain_history_original[channel]) >= s->filter_size) {
500  double minimum;
501 
502  if (cqueue_empty(s->gain_history_minimum[channel])) {
503  const int pre_fill_size = s->filter_size / 2;
504  double initial_value = s->alt_boundary_mode ? cqueue_peek(s->gain_history_original[channel], 0) : 1.0;
505  int input = pre_fill_size;
506 
507  while (cqueue_size(s->gain_history_minimum[channel]) < pre_fill_size) {
508  input++;
509  initial_value = FFMIN(initial_value, cqueue_peek(s->gain_history_original[channel], input));
510  cqueue_enqueue(s->gain_history_minimum[channel], initial_value);
511  }
512  }
513 
514  minimum = minimum_filter(s->gain_history_original[channel]);
515 
516  cqueue_enqueue(s->gain_history_minimum[channel], minimum);
517 
518  cqueue_enqueue(s->threshold_history[channel], gain.threshold);
519 
520  cqueue_pop(s->gain_history_original[channel]);
521  }
522 
523  while (cqueue_size(s->gain_history_minimum[channel]) >= s->filter_size) {
524  double smoothed, limit;
525 
526  smoothed = gaussian_filter(s, s->gain_history_minimum[channel], s->threshold_history[channel]);
527  limit = cqueue_peek(s->gain_history_original[channel], 0);
528  smoothed = FFMIN(smoothed, limit);
529 
530  cqueue_enqueue(s->gain_history_smoothed[channel], smoothed);
531 
532  cqueue_pop(s->gain_history_minimum[channel]);
533  cqueue_pop(s->threshold_history[channel]);
534  }
535 }
536 
537 static inline double update_value(double new, double old, double aggressiveness)
538 {
539  av_assert0((aggressiveness >= 0.0) && (aggressiveness <= 1.0));
540  return aggressiveness * new + (1.0 - aggressiveness) * old;
541 }
542 
544 {
545  const double diff = 1.0 / frame->nb_samples;
546  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
547  int c, i;
548 
549  for (c = 0; c < s->channels; c++) {
550  double *dst_ptr = (double *)frame->extended_data[c];
551  double current_average_value = 0.0;
552  double prev_value;
553 
554  for (i = 0; i < frame->nb_samples; i++)
555  current_average_value += dst_ptr[i] * diff;
556 
557  prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c];
558  s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1);
559 
560  for (i = 0; i < frame->nb_samples; i++) {
561  dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples);
562  }
563  }
564 }
565 
566 static double setup_compress_thresh(double threshold)
567 {
568  if ((threshold > DBL_EPSILON) && (threshold < (1.0 - DBL_EPSILON))) {
569  double current_threshold = threshold;
570  double step_size = 1.0;
571 
572  while (step_size > DBL_EPSILON) {
573  while ((llrint((current_threshold + step_size) * (UINT64_C(1) << 63)) >
574  llrint(current_threshold * (UINT64_C(1) << 63))) &&
575  (bound(current_threshold + step_size, 1.0) <= threshold)) {
576  current_threshold += step_size;
577  }
578 
579  step_size /= 2.0;
580  }
581 
582  return current_threshold;
583  } else {
584  return threshold;
585  }
586 }
587 
589  AVFrame *frame, int channel)
590 {
591  double variance = 0.0;
592  int i, c;
593 
594  if (channel == -1) {
595  for (c = 0; c < s->channels; c++) {
596  const double *data_ptr = (double *)frame->extended_data[c];
597 
598  for (i = 0; i < frame->nb_samples; i++) {
599  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
600  }
601  }
602  variance /= (s->channels * frame->nb_samples) - 1;
603  } else {
604  const double *data_ptr = (double *)frame->extended_data[channel];
605 
606  for (i = 0; i < frame->nb_samples; i++) {
607  variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero*
608  }
609  variance /= frame->nb_samples - 1;
610  }
611 
612  return FFMAX(sqrt(variance), DBL_EPSILON);
613 }
614 
616 {
617  int is_first_frame = cqueue_empty(s->gain_history_original[0]);
618  int c, i;
619 
620  if (s->channels_coupled) {
621  const double standard_deviation = compute_frame_std_dev(s, frame, -1);
622  const double current_threshold = FFMIN(1.0, s->compress_factor * standard_deviation);
623 
624  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[0];
625  double prev_actual_thresh, curr_actual_thresh;
626  s->compress_threshold[0] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[0], (1.0/3.0));
627 
628  prev_actual_thresh = setup_compress_thresh(prev_value);
629  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[0]);
630 
631  for (c = 0; c < s->channels; c++) {
632  double *const dst_ptr = (double *)frame->extended_data[c];
633  for (i = 0; i < frame->nb_samples; i++) {
634  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
635  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
636  }
637  }
638  } else {
639  for (c = 0; c < s->channels; c++) {
640  const double standard_deviation = compute_frame_std_dev(s, frame, c);
641  const double current_threshold = setup_compress_thresh(FFMIN(1.0, s->compress_factor * standard_deviation));
642 
643  const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c];
644  double prev_actual_thresh, curr_actual_thresh;
645  double *dst_ptr;
646  s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0);
647 
648  prev_actual_thresh = setup_compress_thresh(prev_value);
649  curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]);
650 
651  dst_ptr = (double *)frame->extended_data[c];
652  for (i = 0; i < frame->nb_samples; i++) {
653  const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
654  dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
655  }
656  }
657  }
658 }
659 
661 {
662  if (s->dc_correction) {
663  perform_dc_correction(s, frame);
664  }
665 
666  if (s->compress_factor > DBL_EPSILON) {
667  perform_compression(s, frame);
668  }
669 
670  if (s->channels_coupled) {
671  const local_gain gain = get_max_local_gain(s, frame, -1);
672  int c;
673 
674  for (c = 0; c < s->channels; c++)
675  update_gain_history(s, c, gain);
676  } else {
677  int c;
678 
679  for (c = 0; c < s->channels; c++)
680  update_gain_history(s, c, get_max_local_gain(s, frame, c));
681  }
682 }
683 
685 {
686  int c, i;
687 
688  for (c = 0; c < s->channels; c++) {
689  double *dst_ptr = (double *)frame->extended_data[c];
690  double current_amplification_factor;
691 
692  cqueue_dequeue(s->gain_history_smoothed[c], &current_amplification_factor);
693 
694  for (i = 0; i < frame->nb_samples && enabled; i++) {
695  const double amplification_factor = fade(s->prev_amplification_factor[c],
696  current_amplification_factor, i,
697  frame->nb_samples);
698 
699  dst_ptr[i] *= amplification_factor;
700  }
701 
702  s->prev_amplification_factor[c] = current_amplification_factor;
703  }
704 }
705 
707 {
708  AVFilterContext *ctx = inlink->dst;
710  AVFilterLink *outlink = ctx->outputs[0];
711  int ret = 1;
712 
713  while (((s->queue.available >= s->filter_size) ||
714  (s->eof && s->queue.available)) &&
717  double is_enabled;
718 
719  cqueue_dequeue(s->is_enabled, &is_enabled);
720 
721  amplify_frame(s, out, is_enabled > 0.);
722  ret = ff_filter_frame(outlink, out);
723  }
724 
726  analyze_frame(s, in);
727  if (!s->eof) {
728  ff_bufqueue_add(ctx, &s->queue, in);
730  } else {
731  av_frame_free(&in);
732  }
733 
734  return ret;
735 }
736 
738  AVFilterLink *outlink)
739 {
740  AVFrame *out = ff_get_audio_buffer(outlink, s->frame_len);
741  int c, i;
742 
743  if (!out)
744  return AVERROR(ENOMEM);
745 
746  for (c = 0; c < s->channels; c++) {
747  double *dst_ptr = (double *)out->extended_data[c];
748 
749  for (i = 0; i < out->nb_samples; i++) {
750  dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? FFMIN(s->peak_value, s->target_rms) : s->peak_value);
751  if (s->dc_correction) {
752  dst_ptr[i] *= ((i % 2) == 1) ? -1 : 1;
753  dst_ptr[i] += s->dc_correction_value[c];
754  }
755  }
756  }
757 
758  return filter_frame(inlink, out);
759 }
760 
761 static int flush(AVFilterLink *outlink)
762 {
763  AVFilterContext *ctx = outlink->src;
765  int ret = 0;
766 
767  if (!cqueue_empty(s->gain_history_smoothed[0])) {
768  ret = flush_buffer(s, ctx->inputs[0], outlink);
769  } else if (s->queue.available) {
771 
772  s->pts = out->pts;
773  ret = ff_filter_frame(outlink, out);
774  }
775 
776  return ret;
777 }
778 
780 {
781  AVFilterLink *inlink = ctx->inputs[0];
782  AVFilterLink *outlink = ctx->outputs[0];
784  AVFrame *in = NULL;
785  int ret = 0, status;
786  int64_t pts;
787 
788  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
789 
790  if (!s->eof) {
791  ret = ff_inlink_consume_samples(inlink, s->frame_len, s->frame_len, &in);
792  if (ret < 0)
793  return ret;
794  if (ret > 0) {
795  ret = filter_frame(inlink, in);
796  if (ret <= 0)
797  return ret;
798  }
799 
800  if (ff_inlink_queued_samples(inlink) >= s->frame_len) {
801  ff_filter_set_ready(ctx, 10);
802  return 0;
803  }
804  }
805 
806  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
807  if (status == AVERROR_EOF)
808  s->eof = 1;
809  }
810 
811  if (s->eof && s->queue.available)
812  return flush(outlink);
813 
814  if (s->eof && !s->queue.available) {
815  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
816  return 0;
817  }
818 
819  if (!s->eof)
820  FF_FILTER_FORWARD_WANTED(outlink, inlink);
821 
822  return FFERROR_NOT_READY;
823 }
824 
825 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
826  char *res, int res_len, int flags)
827 {
829  AVFilterLink *inlink = ctx->inputs[0];
830  int prev_filter_size = s->filter_size;
831  int ret;
832 
833  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
834  if (ret < 0)
835  return ret;
836 
837  s->filter_size |= 1;
838  if (prev_filter_size != s->filter_size) {
840 
841  for (int c = 0; c < s->channels; c++) {
845  }
846  }
847 
849 
850  return 0;
851 }
852 
854  {
855  .name = "default",
856  .type = AVMEDIA_TYPE_AUDIO,
857  .config_props = config_input,
858  },
859  { NULL }
860 };
861 
863  {
864  .name = "default",
865  .type = AVMEDIA_TYPE_AUDIO,
866  },
867  { NULL }
868 };
869 
871  .name = "dynaudnorm",
872  .description = NULL_IF_CONFIG_SMALL("Dynamic Audio Normalizer."),
873  .query_formats = query_formats,
874  .priv_size = sizeof(DynamicAudioNormalizerContext),
875  .init = init,
876  .uninit = uninit,
877  .activate = activate,
878  .inputs = avfilter_af_dynaudnorm_inputs,
879  .outputs = avfilter_af_dynaudnorm_outputs,
880  .priv_class = &dynaudnorm_class,
883 };
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:90
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)
double threshold
Definition: af_dynaudnorm.c:45
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)
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
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)
double, planar
Definition: samplefmt.h:70
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
return FFERROR_NOT_READY
static void analyze_frame(DynamicAudioNormalizerContext *s, AVFrame *frame)
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
static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q, cqueue *tq)
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:1075
#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
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
static cqueue * cqueue_create(int size, int max_size)
double * elements
Definition: af_dynaudnorm.c:49
int max_size
Definition: af_dynaudnorm.c:51
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
double max_gain
Definition: af_dynaudnorm.c:44
static av_cold void uninit(AVFilterContext *ctx)
static void cqueue_free(cqueue *q)
#define av_log(a,...)
static void cqueue_resize(cqueue *q, int new_size)
#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:1431
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
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
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
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:869
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().
GLsizei GLsizei * length
Definition: opengl_enc.c:114
#define OFFSET(x)
Definition: af_dynaudnorm.c:89
GLsizei count
Definition: opengl_enc.c:108
#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:1456
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:50
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
#define MAX_FILTER_SIZE
Definition: af_dynaudnorm.c:33
sample_rate
int nb_elements
Definition: af_dynaudnorm.c:52
AVFilter ff_af_dynaudnorm
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:1495
static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
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:564
#define MIN_FILTER_SIZE
Definition: af_dynaudnorm.c:32
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 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
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
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 const AVOption dynaudnorm_options[]
Definition: af_dynaudnorm.c:92
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 void update_gain_history(DynamicAudioNormalizerContext *s, int channel, local_gain gain)
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)
static double fade(double prev, double next, int pos, int length)