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 
141  if (!layouts)
142  return AVERROR(ENOMEM);
144  if (ret < 0)
145  return ret;
146 
148  if (!formats)
149  return AVERROR(ENOMEM);
151  if (ret < 0)
152  return ret;
153 
155  if (!formats)
156  return AVERROR(ENOMEM);
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 
298  av_freep(&s->prev_amplification_factor);
299  av_freep(&s->dc_correction_value);
300  av_freep(&s->compress_threshold);
301 
302  for (c = 0; c < s->channels; c++) {
303  if (s->gain_history_original)
304  cqueue_free(s->gain_history_original[c]);
305  if (s->gain_history_minimum)
306  cqueue_free(s->gain_history_minimum[c]);
307  if (s->gain_history_smoothed)
308  cqueue_free(s->gain_history_smoothed[c]);
309  if (s->threshold_history)
310  cqueue_free(s->threshold_history[c]);
311  }
312 
313  av_freep(&s->gain_history_original);
314  av_freep(&s->gain_history_minimum);
315  av_freep(&s->gain_history_smoothed);
316  av_freep(&s->threshold_history);
317 
318  cqueue_free(s->is_enabled);
319  s->is_enabled = NULL;
320 
321  av_freep(&s->weights);
322 
323  ff_bufqueue_discard_all(&s->queue);
324 }
325 
327 {
328  AVFilterContext *ctx = inlink->dst;
330  int c;
331 
332  uninit(ctx);
333 
334  s->channels = inlink->channels;
335  s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec);
336  av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len);
337 
338  s->prev_amplification_factor = av_malloc_array(inlink->channels, sizeof(*s->prev_amplification_factor));
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));
341  s->gain_history_original = av_calloc(inlink->channels, sizeof(*s->gain_history_original));
342  s->gain_history_minimum = av_calloc(inlink->channels, sizeof(*s->gain_history_minimum));
343  s->gain_history_smoothed = av_calloc(inlink->channels, sizeof(*s->gain_history_smoothed));
344  s->threshold_history = av_calloc(inlink->channels, sizeof(*s->threshold_history));
345  s->weights = av_malloc_array(MAX_FILTER_SIZE, sizeof(*s->weights));
346  s->is_enabled = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
347  if (!s->prev_amplification_factor || !s->dc_correction_value ||
348  !s->compress_threshold ||
349  !s->gain_history_original || !s->gain_history_minimum ||
350  !s->gain_history_smoothed || !s->threshold_history ||
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 
357  s->gain_history_original[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
358  s->gain_history_minimum[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
359  s->gain_history_smoothed[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
360  s->threshold_history[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE);
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) {
664  }
665 
666  if (s->compress_factor > DBL_EPSILON) {
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++)
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)) &&
715  !cqueue_empty(s->gain_history_smoothed[0])) {
716  AVFrame *out = ff_bufqueue_get(&s->queue);
717  double is_enabled;
718 
719  cqueue_dequeue(s->is_enabled, &is_enabled);
720 
721  amplify_frame(s, out, is_enabled > 0.);
722  s->pts = out->pts + out->nb_samples;
723  ret = ff_filter_frame(outlink, out);
724  }
725 
727  analyze_frame(s, in);
728  if (!s->eof) {
729  ff_bufqueue_add(ctx, &s->queue, in);
730  cqueue_enqueue(s->is_enabled, !ctx->is_disabled);
731  } else {
732  av_frame_free(&in);
733  }
734 
735  return ret;
736 }
737 
739  AVFilterLink *outlink)
740 {
741  AVFrame *out = ff_get_audio_buffer(outlink, s->frame_len);
742  int c, i;
743 
744  if (!out)
745  return AVERROR(ENOMEM);
746 
747  for (c = 0; c < s->channels; c++) {
748  double *dst_ptr = (double *)out->extended_data[c];
749 
750  for (i = 0; i < out->nb_samples; i++) {
751  dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? FFMIN(s->peak_value, s->target_rms) : s->peak_value);
752  if (s->dc_correction) {
753  dst_ptr[i] *= ((i % 2) == 1) ? -1 : 1;
754  dst_ptr[i] += s->dc_correction_value[c];
755  }
756  }
757  }
758 
759  return filter_frame(inlink, out);
760 }
761 
762 static int flush(AVFilterLink *outlink)
763 {
764  AVFilterContext *ctx = outlink->src;
766  int ret = 0;
767 
768  if (!cqueue_empty(s->gain_history_smoothed[0])) {
769  ret = flush_buffer(s, ctx->inputs[0], outlink);
770  } else if (s->queue.available) {
771  AVFrame *out = ff_bufqueue_get(&s->queue);
772 
773  s->pts = out->pts + out->nb_samples;
774  ret = ff_filter_frame(outlink, out);
775  }
776 
777  return ret;
778 }
779 
781 {
782  AVFilterLink *inlink = ctx->inputs[0];
783  AVFilterLink *outlink = ctx->outputs[0];
785  AVFrame *in = NULL;
786  int ret = 0, status;
787  int64_t pts;
788 
790 
791  if (!s->eof) {
792  ret = ff_inlink_consume_samples(inlink, s->frame_len, s->frame_len, &in);
793  if (ret < 0)
794  return ret;
795  if (ret > 0) {
797  if (ret <= 0)
798  return ret;
799  }
800 
801  if (ff_inlink_check_available_samples(inlink, s->frame_len) > 0) {
803  return 0;
804  }
805  }
806 
807  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
808  if (status == AVERROR_EOF)
809  s->eof = 1;
810  }
811 
812  if (s->eof && s->queue.available)
813  return flush(outlink);
814 
815  if (s->eof && !s->queue.available) {
816  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
817  return 0;
818  }
819 
820  if (!s->eof)
822 
823  return FFERROR_NOT_READY;
824 }
825 
826 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
827  char *res, int res_len, int flags)
828 {
830  AVFilterLink *inlink = ctx->inputs[0];
831  int prev_filter_size = s->filter_size;
832  int ret;
833 
834  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
835  if (ret < 0)
836  return ret;
837 
838  s->filter_size |= 1;
839  if (prev_filter_size != s->filter_size) {
841 
842  for (int c = 0; c < s->channels; c++) {
843  cqueue_resize(s->gain_history_original[c], s->filter_size);
844  cqueue_resize(s->gain_history_minimum[c], s->filter_size);
845  cqueue_resize(s->threshold_history[c], s->filter_size);
846  }
847  }
848 
849  s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec);
850 
851  return 0;
852 }
853 
855  {
856  .name = "default",
857  .type = AVMEDIA_TYPE_AUDIO,
858  .config_props = config_input,
859  },
860  { NULL }
861 };
862 
864  {
865  .name = "default",
866  .type = AVMEDIA_TYPE_AUDIO,
867  },
868  { NULL }
869 };
870 
872  .name = "dynaudnorm",
873  .description = NULL_IF_CONFIG_SMALL("Dynamic Audio Normalizer."),
874  .query_formats = query_formats,
875  .priv_size = sizeof(DynamicAudioNormalizerContext),
876  .init = init,
877  .uninit = uninit,
878  .activate = activate,
881  .priv_class = &dynaudnorm_class,
884 };
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_dynaudnorm.c:326
formats
formats
Definition: signature.h:48
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:86
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:86
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
flush_buffer
static int flush_buffer(DynamicAudioNormalizerContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
Definition: af_dynaudnorm.c:738
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:89
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
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
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:1096
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:925
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
analyze_frame
static void analyze_frame(DynamicAudioNormalizerContext *s, AVFrame *frame)
Definition: af_dynaudnorm.c:660
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(dynaudnorm)
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:33
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
ff_all_channel_counts
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition.
Definition: formats.c:436
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
av_frame_make_writable
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:611
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:118
AVOption
AVOption.
Definition: opt.h:248
DynamicAudioNormalizerContext::dc_correction_value
double * dc_correction_value
Definition: af_dynaudnorm.c:73
float.h
cqueue_resize
static void cqueue_resize(cqueue *q, int new_size)
Definition: af_dynaudnorm.c:244
max
#define max(a, b)
Definition: cuda_runtime.h:33
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:149
c1
static const uint64_t c1
Definition: murmur3.c:51
cqueue::max_size
int max_size
Definition: af_dynaudnorm.c:51
avfilter_af_dynaudnorm_inputs
static const AVFilterPad avfilter_af_dynaudnorm_inputs[]
Definition: af_dynaudnorm.c:854
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:170
find_peak_magnitude
static double find_peak_magnitude(AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:391
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:31
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:65
DynamicAudioNormalizerContext
Definition: af_dynaudnorm.c:55
local_gain
Definition: af_dynaudnorm.c:43
cqueue::size
int size
Definition: af_dynaudnorm.c:50
val
static double val(void *priv, double ch)
Definition: aeval.c:76
cqueue_create
static cqueue * cqueue_create(int size, int max_size)
Definition: af_dynaudnorm.c:166
pts
static int64_t pts
Definition: transcode_aac.c:652
activate
static int activate(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:780
update_value
static double update_value(double new, double old, double aggressiveness)
Definition: af_dynaudnorm.c:537
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
avfilter_af_dynaudnorm_outputs
static const AVFilterPad avfilter_af_dynaudnorm_outputs[]
Definition: af_dynaudnorm.c:863
DynamicAudioNormalizerContext::is_enabled
cqueue * is_enabled
Definition: af_dynaudnorm.c:86
DynamicAudioNormalizerContext::queue
struct FFBufQueue queue
Definition: af_dynaudnorm.c:58
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
cqueue::nb_elements
int nb_elements
Definition: af_dynaudnorm.c:52
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:1479
av_cold
#define av_cold
Definition: attributes.h:90
ff_set_common_formats
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:587
frame_size
static int frame_size(int sample_rate, int frame_len_msec)
Definition: af_dynaudnorm.c:160
minimum_filter
static double minimum_filter(cqueue *q)
Definition: af_dynaudnorm.c:454
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:257
cqueue_empty
static int cqueue_empty(cqueue *q)
Definition: af_dynaudnorm.c:202
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
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
filters.h
DynamicAudioNormalizerContext::channels
int channels
Definition: af_dynaudnorm.c:77
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
ctx
AVFormatContext * ctx
Definition: movenc.c:48
copysign
static av_always_inline double copysign(double x, double y)
Definition: libm.h:68
cqueue_size
static int cqueue_size(cqueue *q)
Definition: af_dynaudnorm.c:197
DynamicAudioNormalizerContext::weights
double * weights
Definition: af_dynaudnorm.c:75
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:293
FLAGS
#define FLAGS
Definition: af_dynaudnorm.c:90
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
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:67
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:1513
NULL
#define NULL
Definition: coverity.c:32
get_max_local_gain
static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:440
pow_2
static double pow_2(const double value)
Definition: af_dynaudnorm.c:380
perform_dc_correction
static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame)
Definition: af_dynaudnorm.c:543
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:762
inputs
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
Definition: filter_design.txt:243
DynamicAudioNormalizerContext::frame_len_msec
int frame_len_msec
Definition: af_dynaudnorm.c:61
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:1449
DynamicAudioNormalizerContext::threshold_history
cqueue ** threshold_history
Definition: af_dynaudnorm.c:84
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:207
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
bufferqueue.h
minimum
static float minimum(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:48
ff_af_dynaudnorm
AVFilter ff_af_dynaudnorm
Definition: af_dynaudnorm.c:871
compute_frame_std_dev
static double compute_frame_std_dev(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:588
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:69
DynamicAudioNormalizerContext::prev_amplification_factor
double * prev_amplification_factor
Definition: af_dynaudnorm.c:72
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:59
size
int size
Definition: twinvq_data.h:10344
amplify_frame
static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *frame, int enabled)
Definition: af_dynaudnorm.c:684
cqueue_pop
static int cqueue_pop(cqueue *q)
Definition: af_dynaudnorm.c:234
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:882
cqueue_free
static void cqueue_free(cqueue *q)
Definition: af_dynaudnorm.c:190
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
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:826
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_dynaudnorm.c:706
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
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: af_dynaudnorm.c:130
M_PI
#define M_PI
Definition: mathematics.h:52
internal.h
DynamicAudioNormalizerContext::compress_threshold
double * compress_threshold
Definition: af_dynaudnorm.c:74
update_gain_history
static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, local_gain gain)
Definition: af_dynaudnorm.c:482
in
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
Definition: audio_convert.c:326
DynamicAudioNormalizerContext::filter_size
int filter_size
Definition: af_dynaudnorm.c:62
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:79
i
int i
Definition: input.c:407
DynamicAudioNormalizerContext::threshold
double threshold
Definition: af_dynaudnorm.c:71
FFBufQueue
Structure holding the queue.
Definition: bufferqueue.h:49
DynamicAudioNormalizerContext::dc_correction
int dc_correction
Definition: af_dynaudnorm.c:63
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
DynamicAudioNormalizerContext::gain_history_minimum
cqueue ** gain_history_minimum
Definition: af_dynaudnorm.c:82
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
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:466
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
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
AVFilter
Filter definition.
Definition: avfilter.h:145
bound
static double bound(const double threshold, const double val)
Definition: af_dynaudnorm.c:385
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:217
cqueue::elements
double * elements
Definition: af_dynaudnorm.c:49
pos
unsigned int pos
Definition: spdifenc.c:412
compute_frame_rms
static double compute_frame_rms(AVFrame *frame, int channel)
Definition: af_dynaudnorm.c:413
cqueue
Definition: af_dynaudnorm.c:48
init_gaussian_filter
static void init_gaussian_filter(DynamicAudioNormalizerContext *s)
Definition: af_dynaudnorm.c:266
ff_all_samplerates
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:421
c2
static const uint64_t c2
Definition: murmur3.c:52
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
dynaudnorm_options
static const AVOption dynaudnorm_options[]
Definition: af_dynaudnorm.c:92
DynamicAudioNormalizerContext::gain_history_original
cqueue ** gain_history_original
Definition: af_dynaudnorm.c:81
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:65
DynamicAudioNormalizerContext::compress_factor
double compress_factor
Definition: af_dynaudnorm.c:70
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:70
MIN_FILTER_SIZE
#define MIN_FILTER_SIZE
Definition: af_dynaudnorm.c:32
CONST
#define CONST(name, help, val, unit)
Definition: vf_bwdif.c:373
DynamicAudioNormalizerContext::frame_len
int frame_len
Definition: af_dynaudnorm.c:60
AVFilterContext
An instance of a filter.
Definition: avfilter.h:341
DynamicAudioNormalizerContext::eof
int eof
Definition: af_dynaudnorm.c:78
audio.h
local_gain::max_gain
double max_gain
Definition: af_dynaudnorm.c:44
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:136
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
DynamicAudioNormalizerContext::channels_coupled
int channels_coupled
Definition: af_dynaudnorm.c:64
fade
static double fade(double prev, double next, int pos, int length)
Definition: af_dynaudnorm.c:372
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:134
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
perform_compression
static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame)
Definition: af_dynaudnorm.c:615
ff_set_common_samplerates
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:575
setup_compress_thresh
static double setup_compress_thresh(double threshold)
Definition: af_dynaudnorm.c:566
DynamicAudioNormalizerContext::max_amplification
double max_amplification
Definition: af_dynaudnorm.c:68
DynamicAudioNormalizerContext::gain_history_smoothed
cqueue ** gain_history_smoothed
Definition: af_dynaudnorm.c:83
cqueue_dequeue
static int cqueue_dequeue(cqueue *q, double *element)
Definition: af_dynaudnorm.c:223
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:193
ff_set_common_channel_layouts
int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *channel_layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates.
Definition: formats.c:568
local_gain::threshold
double threshold
Definition: af_dynaudnorm.c:45
min
float min
Definition: vorbis_enc_data.h:456