FFmpeg
af_replaygain.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1998 - 2009 Conifer Software
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * ReplayGain scanner
24  */
25 
26 #include <float.h>
27 
28 #include "libavutil/avassert.h"
30 #include "libavutil/opt.h"
31 #include "audio.h"
32 #include "avfilter.h"
33 #include "filters.h"
34 #include "formats.h"
35 
36 #define HISTOGRAM_SLOTS 12000
37 #define BUTTER_ORDER 2
38 #define YULE_ORDER 10
39 
40 typedef struct ReplayGainFreqInfo {
42  double BYule[YULE_ORDER + 1];
43  double AYule[YULE_ORDER + 1];
44  double BButter[BUTTER_ORDER + 1];
45  double AButter[BUTTER_ORDER + 1];
47 
48 static const ReplayGainFreqInfo freqinfos[] =
49 {
50  {
51  192000,
52  { 0.01184742123123, -0.04631092400086, 0.06584226961238,
53  -0.02165588522478, -0.05656260778952, 0.08607493592760,
54  -0.03375544339786, -0.04216579932754, 0.06416711490648,
55  -0.03444708260844, 0.00697275872241 },
56  { 1.00000000000000, -5.24727318348167, 10.60821585192244,
57  -8.74127665810413, -1.33906071371683, 8.07972882096606,
58  -5.46179918950847, 0.54318070652536, 0.87450969224280,
59  -0.34656083539754, 0.03034796843589 },
60  { 0.99653501465135, -1.99307002930271, 0.99653501465135 },
61  { 1.00000000000000, -1.99305802314321, 0.99308203546221 },
62  },
63  {
64  176400,
65  { 0.00268568524529, -0.00852379426080, 0.00852704191347,
66  0.00146116310295, -0.00950855828762, 0.00625449515499,
67  0.00116183868722, -0.00362461417136, 0.00203961000134,
68  -0.00050664587933, 0.00004327455427 },
69  { 1.00000000000000, -5.57512782763045, 12.44291056065794,
70  -12.87462799681221, 3.08554846961576, 6.62493459880692,
71  -7.07662766313248, 2.51175542736441, 0.06731510802735,
72  -0.24567753819213, 0.03961404162376 },
73  { 0.99622916581118, -1.99245833162236, 0.99622916581118 },
74  { 1.00000000000000, -1.99244411238133, 0.99247255086339 },
75  },
76  {
77  144000,
78  { 0.00639682359450, -0.02556437970955, 0.04230854400938,
79  -0.03722462201267, 0.01718514827295, 0.00610592243009,
80  -0.03065965747365, 0.04345745003539, -0.03298592681309,
81  0.01320937236809, -0.00220304127757 },
82  { 1.00000000000000, -6.14814623523425, 15.80002457141566,
83  -20.78487587686937, 11.98848552310315, 3.36462015062606,
84  -10.22419868359470, 6.65599702146473, -1.67141861110485,
85  -0.05417956536718, 0.07374767867406 },
86  { 0.99538268958706, -1.99076537917413, 0.99538268958706 },
87  { 1.00000000000000, -1.99074405950505, 0.99078669884321 },
88  },
89  {
90  128000,
91  { 0.00553120584305, -0.02112620545016, 0.03549076243117,
92  -0.03362498312306, 0.01425867248183, 0.01344686928787,
93  -0.03392770787836, 0.03464136459530, -0.02039116051549,
94  0.00667420794705, -0.00093763762995 },
95  { 1.00000000000000, -6.14581710839925, 16.04785903675838,
96  -22.19089131407749, 15.24756471580286, -0.52001440400238,
97  -8.00488641699940, 6.60916094768855, -2.37856022810923,
98  0.33106947986101, 0.00459820832036 },
99  { 0.99480702681278, -1.98961405362557, 0.99480702681278 },
100  { 1.00000000000000, -1.98958708647324, 0.98964102077790 },
101  },
102  {
103  112000,
104  { 0.00528778718259, -0.01893240907245, 0.03185982561867,
105  -0.02926260297838, 0.00715743034072, 0.01985743355827,
106  -0.03222614850941, 0.02565681978192, -0.01210662313473,
107  0.00325436284541, -0.00044173593001 },
108  { 1.00000000000000, -6.24932108456288, 17.42344320538476,
109  -27.86819709054896, 26.79087344681326,-13.43711081485123,
110  -0.66023612948173, 6.03658091814935, -4.24926577030310,
111  1.40829268709186, -0.19480852628112 },
112  { 0.99406737810867, -1.98813475621734, 0.99406737810867 },
113  { 1.00000000000000, -1.98809955990514, 0.98816995252954 },
114  },
115  {
116  96000,
117  { 0.00588138296683, -0.01613559730421, 0.02184798954216,
118  -0.01742490405317, 0.00464635643780, 0.01117772513205,
119  -0.02123865824368, 0.01959354413350, -0.01079720643523,
120  0.00352183686289, -0.00063124341421 },
121  { 1.00000000000000, -5.97808823642008, 16.21362507964068,
122  -25.72923730652599, 25.40470663139513,-14.66166287771134,
123  2.81597484359752, 2.51447125969733, -2.23575306985286,
124  0.75788151036791, -0.10078025199029 },
125  { 0.99308203517541, -1.98616407035082, 0.99308203517541 },
126  { 1.00000000000000, -1.98611621154089, 0.98621192916075 },
127  },
128  {
129  88200,
130  { 0.02667482047416, -0.11377479336097, 0.23063167910965,
131  -0.30726477945593, 0.33188520686529, -0.33862680249063,
132  0.31807161531340, -0.23730796929880, 0.12273894790371,
133  -0.03840017967282, 0.00549673387936 },
134  { 1.00000000000000, -6.31836451657302, 18.31351310801799,
135  -31.88210014815921, 36.53792146976740,-28.23393036467559,
136  14.24725258227189, -4.04670980012854, 0.18865757280515,
137  0.25420333563908, -0.06012333531065 },
138  { 0.99247255046129, -1.98494510092259, 0.99247255046129 },
139  { 1.00000000000000, -1.98488843762335, 0.98500176422183 },
140  },
141  {
142  64000,
143  { 0.02613056568174, -0.08128786488109, 0.14937282347325,
144  -0.21695711675126, 0.25010286673402, -0.23162283619278,
145  0.17424041833052, -0.10299599216680, 0.04258696481981,
146  -0.00977952936493, 0.00105325558889 },
147  { 1.00000000000000, -5.73625477092119, 16.15249794355035,
148  -29.68654912464508, 39.55706155674083,-39.82524556246253,
149  30.50605345013009,-17.43051772821245, 7.05154573908017,
150  -1.80783839720514, 0.22127840210813 },
151  { 0.98964101933472, -1.97928203866944, 0.98964101933472 },
152  { 1.00000000000000, -1.97917472731009, 0.97938935002880 },
153  },
154  {
155  56000,
156  { 0.03144914734085, -0.06151729206963, 0.08066788708145,
157  -0.09737939921516, 0.08943210803999, -0.06989984672010,
158  0.04926972841044, -0.03161257848451, 0.01456837493506,
159  -0.00316015108496, 0.00132807215875 },
160  { 1.00000000000000, -4.87377313090032, 12.03922160140209,
161  -20.10151118381395, 25.10388534415171,-24.29065560815903,
162  18.27158469090663,-10.45249552560593, 4.30319491872003,
163  -1.13716992070185, 0.14510733527035 },
164  { 0.98816995007392, -1.97633990014784, 0.98816995007392 },
165  { 1.00000000000000, -1.97619994516973, 0.97647985512594 },
166  },
167  {
168  48000,
169  { 0.03857599435200, -0.02160367184185, -0.00123395316851,
170  -0.00009291677959, -0.01655260341619, 0.02161526843274,
171  -0.02074045215285, 0.00594298065125, 0.00306428023191,
172  0.00012025322027, 0.00288463683916 },
173  { 1.00000000000000, -3.84664617118067, 7.81501653005538,
174  -11.34170355132042, 13.05504219327545,-12.28759895145294,
175  9.48293806319790, -5.87257861775999, 2.75465861874613,
176  -0.86984376593551, 0.13919314567432 },
177  { 0.98621192462708, -1.97242384925416, 0.98621192462708 },
178  { 1.00000000000000, -1.97223372919527, 0.97261396931306 },
179  },
180  {
181  44100,
182  { 0.05418656406430, -0.02911007808948, -0.00848709379851,
183  -0.00851165645469, -0.00834990904936, 0.02245293253339,
184  -0.02596338512915, 0.01624864962975, -0.00240879051584,
185  0.00674613682247, -0.00187763777362 },
186  { 1.00000000000000, -3.47845948550071, 6.36317777566148,
187  -8.54751527471874, 9.47693607801280, -8.81498681370155,
188  6.85401540936998, -4.39470996079559, 2.19611684890774,
189  -0.75104302451432, 0.13149317958808 },
190  { 0.98500175787242, -1.97000351574484, 0.98500175787242 },
191  { 1.00000000000000, -1.96977855582618, 0.97022847566350 },
192  },
193  {
194  37800,
195  { 0.08717879977844, -0.01000374016172, -0.06265852122368,
196  -0.01119328800950, -0.00114279372960, 0.02081333954769,
197  -0.01603261863207, 0.01936763028546, 0.00760044736442,
198  -0.00303979112271, -0.00075088605788 },
199  { 1.00000000000000, -2.62816311472146, 3.53734535817992,
200  -3.81003448678921, 3.91291636730132, -3.53518605896288,
201  2.71356866157873, -1.86723311846592, 1.12075382367659,
202  -0.48574086886890, 0.11330544663849 },
203  { 0.98252400815195, -1.96504801630391, 0.98252400815195 },
204  { 1.00000000000000, -1.96474258269041, 0.96535344991740 },
205  },
206  {
207  32000,
208  { 0.15457299681924, -0.09331049056315, -0.06247880153653,
209  0.02163541888798, -0.05588393329856, 0.04781476674921,
210  0.00222312597743, 0.03174092540049, -0.01390589421898,
211  0.00651420667831, -0.00881362733839 },
212  { 1.00000000000000, -2.37898834973084, 2.84868151156327,
213  -2.64577170229825, 2.23697657451713, -1.67148153367602,
214  1.00595954808547, -0.45953458054983, 0.16378164858596,
215  -0.05032077717131, 0.02347897407020 },
216  { 0.97938932735214, -1.95877865470428, 0.97938932735214 },
217  { 1.00000000000000, -1.95835380975398, 0.95920349965459 },
218  },
219  {
220  24000,
221  { 0.30296907319327, -0.22613988682123, -0.08587323730772,
222  0.03282930172664, -0.00915702933434, -0.02364141202522,
223  -0.00584456039913, 0.06276101321749, -0.00000828086748,
224  0.00205861885564, -0.02950134983287 },
225  { 1.00000000000000, -1.61273165137247, 1.07977492259970,
226  -0.25656257754070, -0.16276719120440, -0.22638893773906,
227  0.39120800788284, -0.22138138954925, 0.04500235387352,
228  0.02005851806501, 0.00302439095741 },
229  { 0.97531843204928, -1.95063686409857, 0.97531843204928 },
230  { 1.00000000000000, -1.95002759149878, 0.95124613669835 },
231  },
232  {
233  22050,
234  { 0.33642304856132, -0.25572241425570, -0.11828570177555,
235  0.11921148675203, -0.07834489609479, -0.00469977914380,
236  -0.00589500224440, 0.05724228140351, 0.00832043980773,
237  -0.01635381384540, -0.01760176568150 },
238  { 1.00000000000000, -1.49858979367799, 0.87350271418188,
239  0.12205022308084, -0.80774944671438, 0.47854794562326,
240  -0.12453458140019, -0.04067510197014, 0.08333755284107,
241  -0.04237348025746, 0.02977207319925 },
242  { 0.97316523498161, -1.94633046996323, 0.97316523498161 },
243  { 1.00000000000000, -1.94561023566527, 0.94705070426118 },
244  },
245  {
246  18900,
247  { 0.38524531015142, -0.27682212062067, -0.09980181488805,
248  0.09951486755646, -0.08934020156622, -0.00322369330199,
249  -0.00110329090689, 0.03784509844682, 0.01683906213303,
250  -0.01147039862572, -0.01941767987192 },
251  { 1.00000000000000, -1.29708918404534, 0.90399339674203,
252  -0.29613799017877, -0.42326645916207, 0.37934887402200,
253  -0.37919795944938, 0.23410283284785, -0.03892971758879,
254  0.00403009552351, 0.03640166626278 },
255  { 0.96535326815829, -1.93070653631658, 0.96535326815829 },
256  { 1.00000000000000, -1.92950577983524, 0.93190729279793 },
257  },
258  {
259  16000,
260  { 0.44915256608450, -0.14351757464547, -0.22784394429749,
261  -0.01419140100551, 0.04078262797139, -0.12398163381748,
262  0.04097565135648, 0.10478503600251, -0.01863887810927,
263  -0.03193428438915, 0.00541907748707 },
264  { 1.00000000000000, -0.62820619233671, 0.29661783706366,
265  -0.37256372942400, 0.00213767857124, -0.42029820170918,
266  0.22199650564824, 0.00613424350682, 0.06747620744683,
267  0.05784820375801, 0.03222754072173 },
268  { 0.96454515552826, -1.92909031105652, 0.96454515552826 },
269  { 1.00000000000000, -1.92783286977036, 0.93034775234268 },
270  },
271  {
272  12000,
273  { 0.56619470757641, -0.75464456939302, 0.16242137742230,
274  0.16744243493672, -0.18901604199609, 0.30931782841830,
275  -0.27562961986224, 0.00647310677246, 0.08647503780351,
276  -0.03788984554840, -0.00588215443421 },
277  { 1.00000000000000, -1.04800335126349, 0.29156311971249,
278  -0.26806001042947, 0.00819999645858, 0.45054734505008,
279  -0.33032403314006, 0.06739368333110, -0.04784254229033,
280  0.01639907836189, 0.01807364323573 },
281  { 0.96009142950541, -1.92018285901082, 0.96009142950541 },
282  { 1.00000000000000, -1.91858953033784, 0.92177618768381 },
283  },
284  {
285  11025,
286  { 0.58100494960553, -0.53174909058578, -0.14289799034253,
287  0.17520704835522, 0.02377945217615, 0.15558449135573,
288  -0.25344790059353, 0.01628462406333, 0.06920467763959,
289  -0.03721611395801, -0.00749618797172 },
290  { 1.00000000000000, -0.51035327095184, -0.31863563325245,
291  -0.20256413484477, 0.14728154134330, 0.38952639978999,
292  -0.23313271880868, -0.05246019024463, -0.02505961724053,
293  0.02442357316099, 0.01818801111503 },
294  { 0.95856916599601, -1.91713833199203, 0.95856916599601 },
295  { 1.00000000000000, -1.91542108074780, 0.91885558323625 },
296  },
297  {
298  8000,
299  { 0.53648789255105, -0.42163034350696, -0.00275953611929,
300  0.04267842219415, -0.10214864179676, 0.14590772289388,
301  -0.02459864859345, -0.11202315195388, -0.04060034127000,
302  0.04788665548180, -0.02217936801134 },
303  { 1.00000000000000, -0.25049871956020, -0.43193942311114,
304  -0.03424681017675, -0.04678328784242, 0.26408300200955,
305  0.15113130533216, -0.17556493366449, -0.18823009262115,
306  0.05477720428674, 0.04704409688120 },
307  { 0.94597685600279, -1.89195371200558, 0.94597685600279 },
308  { 1.00000000000000, -1.88903307939452, 0.89487434461664 },
309  },
310 };
311 
312 typedef struct ReplayGainContext {
313  const AVClass *class;
314 
316  float peak;
317  float gain;
319  const double *yule_coeff_a;
320  const double *yule_coeff_b;
321  const double *butter_coeff_a;
322  const double *butter_coeff_b;
323  float yule_hist_a[256];
324  float yule_hist_b[256];
325  float butter_hist_a[256];
326  float butter_hist_b[256];
328 
330  AVFilterFormatsConfig **cfg_in,
331  AVFilterFormatsConfig **cfg_out)
332 {
333  static const enum AVSampleFormat formats[] = {
336  };
337  static const AVChannelLayout layouts[] = {
339  { .nb_channels = 0 },
340  };
341 
343 
344  int i, ret;
345 
346  ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, formats);
347  if (ret < 0)
348  return ret;
349 
351  if (ret < 0)
352  return ret;
353 
354  rates = NULL;
355  for (i = 0; i < FF_ARRAY_ELEMS(freqinfos); i++) {
356  if ((ret = ff_add_format(&rates, freqinfos[i].sample_rate)) < 0)
357  return ret;
358  }
359 
360  return ff_set_common_samplerates2(ctx, cfg_in, cfg_out, rates);
361 }
362 
364 {
366  AVFilterContext *ctx = inlink->dst;
367  ReplayGainContext *s = ctx->priv;
368  int i;
369 
370  for (i = 0; i < FF_ARRAY_ELEMS(freqinfos); i++) {
371  if (freqinfos[i].sample_rate == inlink->sample_rate)
372  break;
373  }
375 
376  s->yule_coeff_a = freqinfos[i].AYule;
377  s->yule_coeff_b = freqinfos[i].BYule;
378  s->butter_coeff_a = freqinfos[i].AButter;
379  s->butter_coeff_b = freqinfos[i].BButter;
380 
381  s->yule_hist_i = 20;
382  s->butter_hist_i = 4;
383  l->min_samples =
384  l->max_samples = inlink->sample_rate / 20;
385 
386  return 0;
387 }
388 
389 /*
390  * Update largest absolute sample value.
391  */
392 static void calc_stereo_peak(const float *samples, int nb_samples,
393  float *peak_p)
394 {
395  float peak = 0.0;
396 
397  while (nb_samples--) {
398  if (samples[0] > peak)
399  peak = samples[0];
400  else if (-samples[0] > peak)
401  peak = -samples[0];
402 
403  if (samples[1] > peak)
404  peak = samples[1];
405  else if (-samples[1] > peak)
406  peak = -samples[1];
407 
408  samples += 2;
409  }
410 
411  *peak_p = FFMAX(peak, *peak_p);
412 }
413 
414 /*
415  * Calculate stereo RMS level. Minimum value is about -100 dB for
416  * digital silence. The 90 dB offset is to compensate for the
417  * normalized float range and 3 dB is for stereo samples.
418  */
419 static double calc_stereo_rms(const float *samples, int nb_samples)
420 {
421  int count = nb_samples;
422  double sum = 1e-16;
423 
424  while (count--) {
425  sum += samples[0] * samples[0] + samples[1] * samples[1];
426  samples += 2;
427  }
428 
429  return 10 * log10 (sum / nb_samples) + 90.0 - 3.0;
430 }
431 
432 /*
433  * Optimized implementation of 2nd-order IIR stereo filter.
434  */
436  float *samples, int nb_samples)
437 {
438  const double *coeff_a = s->butter_coeff_a;
439  const double *coeff_b = s->butter_coeff_b;
440  float *hist_a = s->butter_hist_a;
441  float *hist_b = s->butter_hist_b;
442  double left, right;
443  int i, j;
444 
445  i = s->butter_hist_i;
446 
447  // If filter history is very small magnitude, clear it completely
448  // to prevent denormals from rattling around in there forever
449  // (slowing us down).
450 
451  for (j = -4; j < 0; ++j)
452  if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f)
453  break;
454 
455  if (!j) {
456  memset(s->butter_hist_a, 0, sizeof(s->butter_hist_a));
457  memset(s->butter_hist_b, 0, sizeof(s->butter_hist_b));
458  }
459 
460  while (nb_samples--) {
461  left = (hist_b[i ] = samples[0]) * coeff_b[0];
462  right = (hist_b[i + 1] = samples[1]) * coeff_b[0];
463  left += hist_b[i - 2] * coeff_b[1] - hist_a[i - 2] * coeff_a[1];
464  right += hist_b[i - 1] * coeff_b[1] - hist_a[i - 1] * coeff_a[1];
465  left += hist_b[i - 4] * coeff_b[2] - hist_a[i - 4] * coeff_a[2];
466  right += hist_b[i - 3] * coeff_b[2] - hist_a[i - 3] * coeff_a[2];
467  samples[0] = hist_a[i ] = (float) left;
468  samples[1] = hist_a[i + 1] = (float) right;
469  samples += 2;
470 
471  if ((i += 2) == 256) {
472  memcpy(hist_a, hist_a + 252, sizeof(*hist_a) * 4);
473  memcpy(hist_b, hist_b + 252, sizeof(*hist_b) * 4);
474  i = 4;
475  }
476  }
477 
478  s->butter_hist_i = i;
479 }
480 
481 /*
482  * Optimized implementation of 10th-order IIR stereo filter.
483  */
485  float *dst, int nb_samples)
486 {
487  const double *coeff_a = s->yule_coeff_a;
488  const double *coeff_b = s->yule_coeff_b;
489  float *hist_a = s->yule_hist_a;
490  float *hist_b = s->yule_hist_b;
491  double left, right;
492  int i, j;
493 
494  i = s->yule_hist_i;
495 
496  // If filter history is very small magnitude, clear it completely to
497  // prevent denormals from rattling around in there forever
498  // (slowing us down).
499 
500  for (j = -20; j < 0; ++j)
501  if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f)
502  break;
503 
504  if (!j) {
505  memset(s->yule_hist_a, 0, sizeof(s->yule_hist_a));
506  memset(s->yule_hist_b, 0, sizeof(s->yule_hist_b));
507  }
508 
509  while (nb_samples--) {
510  left = (hist_b[i] = src[0]) * coeff_b[0];
511  right = (hist_b[i + 1] = src[1]) * coeff_b[0];
512  left += hist_b[i - 2] * coeff_b[ 1] - hist_a[i - 2] * coeff_a[1 ];
513  right += hist_b[i - 1] * coeff_b[ 1] - hist_a[i - 1] * coeff_a[1 ];
514  left += hist_b[i - 4] * coeff_b[ 2] - hist_a[i - 4] * coeff_a[2 ];
515  right += hist_b[i - 3] * coeff_b[ 2] - hist_a[i - 3] * coeff_a[2 ];
516  left += hist_b[i - 6] * coeff_b[ 3] - hist_a[i - 6] * coeff_a[3 ];
517  right += hist_b[i - 5] * coeff_b[ 3] - hist_a[i - 5] * coeff_a[3 ];
518  left += hist_b[i - 8] * coeff_b[ 4] - hist_a[i - 8] * coeff_a[4 ];
519  right += hist_b[i - 7] * coeff_b[ 4] - hist_a[i - 7] * coeff_a[4 ];
520  left += hist_b[i - 10] * coeff_b[ 5] - hist_a[i - 10] * coeff_a[5 ];
521  right += hist_b[i - 9] * coeff_b[ 5] - hist_a[i - 9] * coeff_a[5 ];
522  left += hist_b[i - 12] * coeff_b[ 6] - hist_a[i - 12] * coeff_a[6 ];
523  right += hist_b[i - 11] * coeff_b[ 6] - hist_a[i - 11] * coeff_a[6 ];
524  left += hist_b[i - 14] * coeff_b[ 7] - hist_a[i - 14] * coeff_a[7 ];
525  right += hist_b[i - 13] * coeff_b[ 7] - hist_a[i - 13] * coeff_a[7 ];
526  left += hist_b[i - 16] * coeff_b[ 8] - hist_a[i - 16] * coeff_a[8 ];
527  right += hist_b[i - 15] * coeff_b[ 8] - hist_a[i - 15] * coeff_a[8 ];
528  left += hist_b[i - 18] * coeff_b[ 9] - hist_a[i - 18] * coeff_a[9 ];
529  right += hist_b[i - 17] * coeff_b[ 9] - hist_a[i - 17] * coeff_a[9 ];
530  left += hist_b[i - 20] * coeff_b[10] - hist_a[i - 20] * coeff_a[10];
531  right += hist_b[i - 19] * coeff_b[10] - hist_a[i - 19] * coeff_a[10];
532  dst[0] = hist_a[i ] = (float)left;
533  dst[1] = hist_a[i + 1] = (float)right;
534  src += 2;
535  dst += 2;
536 
537  if ((i += 2) == 256) {
538  memcpy(hist_a, hist_a + 236, sizeof(*hist_a) * 20);
539  memcpy(hist_b, hist_b + 236, sizeof(*hist_b) * 20);
540  i = 20;
541  }
542  }
543 
544  s->yule_hist_i = i;
545 }
546 
547 /*
548  * Calculate the ReplayGain value from the specified loudness histogram;
549  * clip to -24 / +64 dB.
550  */
551 static float calc_replaygain(uint32_t *histogram)
552 {
553  uint32_t loud_count = 0, total_windows = 0;
554  float gain;
555  int i;
556 
557  for (i = 0; i < HISTOGRAM_SLOTS; i++)
558  total_windows += histogram [i];
559 
560  while (i--)
561  if ((loud_count += histogram [i]) * 20 >= total_windows)
562  break;
563 
564  gain = (float)(64.54 - i / 100.0);
565 
566  return av_clipf(gain, -24.0, 64.0);
567 }
568 
570 {
571  AVFilterContext *ctx = inlink->dst;
572  AVFilterLink *outlink = ctx->outputs[0];
573  ReplayGainContext *s = ctx->priv;
574  int64_t level;
575  AVFrame *out;
576 
577  out = ff_get_audio_buffer(outlink, in->nb_samples);
578  if (!out) {
579  av_frame_free(&in);
580  return AVERROR(ENOMEM);
581  }
582 
583  calc_stereo_peak((float *)in->data[0],
584  in->nb_samples, &s->peak);
585  yule_filter_stereo_samples(s, (const float *)in->data[0],
586  (float *)out->data[0],
587  out->nb_samples);
588  butter_filter_stereo_samples(s, (float *)out->data[0],
589  out->nb_samples);
590  level = lrint(floor(100 * calc_stereo_rms((float *)out->data[0],
591  out->nb_samples)));
593 
594  s->histogram[level]++;
595 
596  av_frame_free(&out);
597  return ff_filter_frame(outlink, in);
598 }
599 
600 static int request_frame(AVFilterLink *outlink)
601 {
602  AVFilterContext *ctx = outlink->src;
603  ReplayGainContext *s = ctx->priv;
604  int ret = 0;
605 
606  ret = ff_request_frame(ctx->inputs[0]);
607 
608  if (ret == AVERROR_EOF) {
609  s->gain = calc_replaygain(s->histogram);
610 
611  av_log(ctx, AV_LOG_INFO, "track_gain = %+.2f dB\n", s->gain);
612  av_log(ctx, AV_LOG_INFO, "track_peak = %.6f\n", s->peak);
613  }
614 
615  return ret;
616 }
617 
618 static const AVFilterPad replaygain_inputs[] = {
619  {
620  .name = "default",
621  .type = AVMEDIA_TYPE_AUDIO,
622  .filter_frame = filter_frame,
623  .config_props = config_input,
624  },
625 };
626 
627 static const AVFilterPad replaygain_outputs[] = {
628  {
629  .name = "default",
630  .type = AVMEDIA_TYPE_AUDIO,
631  .request_frame = request_frame,
632  },
633 };
634 
635 #define OFFSET(x) offsetof(ReplayGainContext, x)
636 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_EXPORT|AV_OPT_FLAG_READONLY
637 
638 static const AVOption replaygain_options[] = {
639  { "track_gain", "track gain (dB)", OFFSET(gain), AV_OPT_TYPE_FLOAT,{.dbl=0}, -FLT_MAX, FLT_MAX, FLAGS },
640  { "track_peak", "track peak", OFFSET(peak), AV_OPT_TYPE_FLOAT,{.dbl=0}, -FLT_MAX, FLT_MAX, FLAGS },
641  { NULL }
642 };
643 
644 AVFILTER_DEFINE_CLASS(replaygain);
645 
647  .name = "replaygain",
648  .description = NULL_IF_CONFIG_SMALL("ReplayGain scanner."),
649  .priv_size = sizeof(ReplayGainContext),
650  .priv_class = &replaygain_class,
655 };
formats
formats
Definition: signature.h:47
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:98
level
uint8_t level
Definition: svq3.c:205
request_frame
static int request_frame(AVFilterLink *outlink)
Definition: af_replaygain.c:600
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
out
FILE * out
Definition: movenc.c:55
AV_CHANNEL_LAYOUT_STEREO
#define AV_CHANNEL_LAYOUT_STEREO
Definition: channel_layout.h:393
YULE_ORDER
#define YULE_ORDER
Definition: af_replaygain.c:38
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1061
HISTOGRAM_SLOTS
#define HISTOGRAM_SLOTS
Definition: af_replaygain.c:36
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:335
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
int64_t
long long int64_t
Definition: coverity.c:34
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
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
AVOption
AVOption.
Definition: opt.h:429
ff_request_frame
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:475
ReplayGainContext::butter_hist_i
int butter_hist_i
Definition: af_replaygain.c:318
ff_set_common_channel_layouts_from_list2
int ff_set_common_channel_layouts_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const AVChannelLayout *fmts)
Definition: formats.c:920
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(replaygain)
float.h
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
ReplayGainContext
Definition: af_replaygain.c:312
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
ReplayGainContext::butter_coeff_a
const double * butter_coeff_a
Definition: af_replaygain.c:321
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
formats.h
calc_replaygain
static float calc_replaygain(uint32_t *histogram)
Definition: af_replaygain.c:551
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: af_replaygain.c:329
butter_filter_stereo_samples
static void butter_filter_stereo_samples(ReplayGainContext *s, float *samples, int nb_samples)
Definition: af_replaygain.c:435
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
av_clip64
#define av_clip64
Definition: common.h:103
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
ReplayGainContext::yule_coeff_a
const double * yule_coeff_a
Definition: af_replaygain.c:319
float
float
Definition: af_crystalizer.c:122
s
#define s(width, name)
Definition: cbs_vp9.c:198
floor
static __device__ float floor(float a)
Definition: cuda_runtime.h:173
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:40
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ReplayGainFreqInfo::AButter
double AButter[BUTTER_ORDER+1]
Definition: af_replaygain.c:45
ff_set_common_samplerates2
int ff_set_common_samplerates2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *samplerates)
Definition: formats.c:935
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
ReplayGainContext::yule_coeff_b
const double * yule_coeff_b
Definition: af_replaygain.c:320
ReplayGainContext::yule_hist_i
int yule_hist_i
Definition: af_replaygain.c:318
ReplayGainContext::butter_coeff_b
const double * butter_coeff_b
Definition: af_replaygain.c:322
ReplayGainContext::butter_hist_a
float butter_hist_a[256]
Definition: af_replaygain.c:325
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_replaygain.c:569
ReplayGainContext::peak
float peak
Definition: af_replaygain.c:316
NULL
#define NULL
Definition: coverity.c:32
replaygain_inputs
static const AVFilterPad replaygain_inputs[]
Definition: af_replaygain.c:618
ReplayGainFreqInfo::sample_rate
int sample_rate
Definition: af_replaygain.c:41
ff_add_format
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition: formats.c:504
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_replaygain.c:363
OFFSET
#define OFFSET(x)
Definition: af_replaygain.c:635
av_clipf
av_clipf
Definition: af_crystalizer.c:122
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:197
f
f
Definition: af_crystalizer.c:122
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:94
replaygain_options
static const AVOption replaygain_options[]
Definition: af_replaygain.c:638
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:317
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
ReplayGainContext::histogram
uint32_t histogram[HISTOGRAM_SLOTS]
Definition: af_replaygain.c:315
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
yule_filter_stereo_samples
static void yule_filter_stereo_samples(ReplayGainContext *s, const float *src, float *dst, int nb_samples)
Definition: af_replaygain.c:484
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition: opt.h:271
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:469
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ReplayGainContext::yule_hist_b
float yule_hist_b[256]
Definition: af_replaygain.c:324
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
replaygain_outputs
static const AVFilterPad replaygain_outputs[]
Definition: af_replaygain.c:627
BUTTER_ORDER
#define BUTTER_ORDER
Definition: af_replaygain.c:37
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
calc_stereo_rms
static double calc_stereo_rms(const float *samples, int nb_samples)
Definition: af_replaygain.c:419
AVFilter
Filter definition.
Definition: avfilter.h:201
ret
ret
Definition: filter_design.txt:187
freqinfos
static const ReplayGainFreqInfo freqinfos[]
Definition: af_replaygain.c:48
ReplayGainFreqInfo::BButter
double BButter[BUTTER_ORDER+1]
Definition: af_replaygain.c:44
ReplayGainFreqInfo
Definition: af_replaygain.c:40
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
ff_set_common_formats_from_list2
int ff_set_common_formats_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const int *fmts)
Definition: formats.c:1016
channel_layout.h
ReplayGainContext::yule_hist_a
float yule_hist_a[256]
Definition: af_replaygain.c:323
FLAGS
#define FLAGS
Definition: af_replaygain.c:636
rates
static const int rates[]
Definition: swresample.c:103
avfilter.h
AVFILTER_FLAG_METADATA_ONLY
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition: avfilter.h:168
calc_stereo_peak
static void calc_stereo_peak(const float *samples, int nb_samples, float *peak_p)
Definition: af_replaygain.c:392
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
ff_af_replaygain
const AVFilter ff_af_replaygain
Definition: af_replaygain.c:646
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
audio.h
ReplayGainFreqInfo::AYule
double AYule[YULE_ORDER+1]
Definition: af_replaygain.c:43
ReplayGainContext::butter_hist_b
float butter_hist_b[256]
Definition: af_replaygain.c:326
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ReplayGainContext::gain
float gain
Definition: af_replaygain.c:317
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
src
#define src
Definition: vp8dsp.c:248
ReplayGainFreqInfo::BYule
double BYule[YULE_ORDER+1]
Definition: af_replaygain.c:42