add basic VAMP plugin for EBUr128 analysis
[ardour.git] / libs / vamp-plugins / ebu_r128_proc.cc
1 // ------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2010-2011 Fons Adriaensen <fons@linuxaudio.org>
4 //  Copyright (C) 2015 Robin Gareus <robin@gareus.org>
5 //    
6 //  This program is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 2 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program 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
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //
20 // ------------------------------------------------------------------------
21
22
23 #include <string.h>
24 #include <math.h>
25 #include "ebu_r128_proc.h"
26
27 namespace Fons {
28
29 float Ebu_r128_hist::_bin_power [100] = { 0.0f };
30 float Ebu_r128_proc::_chan_gain [5] = { 1.0f, 1.0f, 1.0f, 1.41f, 1.41f };
31
32
33 Ebu_r128_hist::Ebu_r128_hist (void)
34 {
35     _histc = new int [751];
36     initstat ();
37     reset ();
38 }
39
40
41 Ebu_r128_hist::~Ebu_r128_hist (void)
42 {
43     delete[] _histc;
44 }
45
46
47 void Ebu_r128_hist::reset (void)
48 {
49     memset (_histc, 0, 751 * sizeof (float));
50     _count = 0;
51     _error = 0;
52 }
53
54
55 void Ebu_r128_hist::initstat (void)
56 {
57     int i;
58
59     if (_bin_power [0]) return;
60     for (i = 0; i < 100; i++)
61     {
62         _bin_power [i] = powf (10.0f, i / 100.0f);
63     }
64 }
65
66
67 void Ebu_r128_hist::addpoint (float v)
68 {
69     int k;
70
71     k = (int) floorf (10 * v + 700.5f);
72     if (k < 0) return;
73     if (k > 750)
74     {
75         k = 750;
76         _error++;
77     }
78     _histc [k]++;
79     _count++;
80 }
81
82
83 float Ebu_r128_hist::integrate (int i)
84 {
85     int   j, k, n;
86     float s;
87
88     j = i % 100;
89     n = 0;
90     s = 0;
91     while (i <= 750)
92     {
93         k = _histc [i++];
94         n += k;
95         s += k * _bin_power [j++];
96         if (j == 100)
97         {
98             j = 0;
99             s /= 10.0f;
100         }
101     }   
102     return s / n;
103 }
104
105
106 void Ebu_r128_hist::calc_integ (float *vi, float *th)
107 {
108     int   k;
109     float s;
110
111     if (_count < 50)
112     {
113         *vi = -200.0f;
114         return;
115     }
116     s = integrate (0);
117 //  Original threshold was -8 dB below result of first integration
118 //    if (th) *th = 10 * log10f (s) - 8.0f;
119 //    k = (int)(floorf (100 * log10f (s) + 0.5f)) + 620;
120 //  Threshold redefined to -10 dB below result of first integration
121     if (th) *th = 10 * log10f (s) - 10.0f;
122     k = (int)(floorf (100 * log10f (s) + 0.5f)) + 600;
123     if (k < 0) k = 0;
124     s = integrate (k);
125     *vi = 10 * log10f (s);
126 }
127
128
129 void Ebu_r128_hist::calc_range (float *v0, float *v1, float *th)
130 {
131     int   i, j, k, n;
132     float a, b, s;
133
134     if (_count < 20)
135     {
136         *v0 = -200.0f;
137         *v1 = -200.0f;
138         return;
139     }
140     s = integrate (0);
141     if (th) *th = 10 * log10f (s) - 20.0f;
142     k = (int)(floorf (100 * log10f (s) + 0.5)) + 500;
143     if (k < 0) k = 0;
144     for (i = k, n = 0; i <= 750; i++) n += _histc [i]; 
145     a = 0.10f * n;
146     b = 0.95f * n;
147     for (i =   k, s = 0; s < a; i++) s += _histc [i];
148     for (j = 750, s = n; s > b; j--) s -= _histc [j];
149     *v0 = (i - 701) / 10.0f;
150     *v1 = (j - 699) / 10.0f;
151 }
152
153
154
155
156 Ebu_r128_proc::Ebu_r128_proc (void)
157 {
158     reset ();
159 }
160
161
162 Ebu_r128_proc::~Ebu_r128_proc (void)
163 {
164 }
165
166
167 void Ebu_r128_proc::init (int nchan, float fsamp)
168 {
169     _nchan = nchan;
170     _fsamp = fsamp;
171     _fragm = (int) fsamp / 20;
172     detect_init (_fsamp);
173     reset ();
174 }
175
176
177 void Ebu_r128_proc::reset (void)
178 {
179     _integr = false;
180     _frcnt = _fragm;
181     _frpwr = 1e-30f;
182     _wrind  = 0;
183     _div1 = 0;
184     _div2 = 0;
185     _loudness_M = -200.0f;
186     _loudness_S = -200.0f;
187     memset (_power, 0, 64 * sizeof (float));
188     integr_reset ();
189     detect_reset ();
190 }
191
192
193 void Ebu_r128_proc::integr_reset (void)
194 {
195     _hist_M.reset ();
196     _hist_S.reset ();
197     _maxloudn_M = -200.0f;
198     _maxloudn_S = -200.0f;
199     _integrated = -200.0f;
200     _integ_thr  = -200.0f;
201     _range_min  = -200.0f;
202     _range_max  = -200.0f;
203     _range_thr  = -200.0f;
204     _div1 = _div2 = 0;
205 }
206
207
208 void Ebu_r128_proc::process (int nfram, const float *const *input)
209 {
210     int  i, k;
211     
212     for (i = 0; i < _nchan; i++) _ipp [i] = input [i];
213     while (nfram)
214     {
215         k = (_frcnt < nfram) ? _frcnt : nfram;
216         _frpwr += detect_process (k);
217         _frcnt -= k;
218         if (_frcnt == 0)
219         {
220             _power [_wrind++] = _frpwr / _fragm;
221             _frcnt = _fragm;
222             _frpwr = 1e-30f;
223             _wrind &= 63;
224             _loudness_M = addfrags (8);
225             _loudness_S = addfrags (60);
226             if (!isfinite(_loudness_M) || _loudness_M < -200.f) _loudness_M = -200.0f;
227             if (!isfinite(_loudness_S) || _loudness_S < -200.f) _loudness_S = -200.0f;
228             if (_loudness_M > _maxloudn_M) _maxloudn_M = _loudness_M;
229             if (_loudness_S > _maxloudn_S) _maxloudn_S = _loudness_S;
230             if (_integr)
231             {
232                 if (++_div1 == 2)
233                 {
234                     _hist_M.addpoint (_loudness_M);
235                     _div1 = 0;
236                 }
237                 if (++_div2 == 10)
238                 {
239                     _hist_S.addpoint (_loudness_S);
240                     _div2 = 0;
241                     _hist_M.calc_integ (&_integrated, &_integ_thr);
242                     _hist_S.calc_range (&_range_min, &_range_max, &_range_thr);
243                 }
244             }
245         }
246         for (i = 0; i < _nchan; i++) _ipp [i] += k;
247         nfram -= k;
248     }
249 }
250
251
252 float Ebu_r128_proc::addfrags (int nfrag)
253 {
254     int    i, k;
255     float  s;
256
257     s = 0;
258     k = (_wrind - nfrag) & 63;
259     for (i = 0; i < nfrag; i++) s += _power [(i + k) & 63];
260     return -0.6976f + 10 * log10f (s / nfrag);
261 }
262
263
264 void Ebu_r128_proc::detect_init (float fsamp)
265 {
266     float a, b, c, d, r, u1, u2, w1, w2;
267
268     r = 1 / tan (4712.3890f / fsamp);
269     w1 = r / 1.12201f; 
270     w2 = r * 1.12201f;
271     u1 = u2 = 1.4085f + 210.0f / fsamp;
272     a = u1 * w1;
273     b = w1 * w1;
274     c = u2 * w2;
275     d = w2 * w2;
276     r = 1 + a + b;
277     _a0 = (1 + c + d) / r;
278     _a1 = (2 - 2 * d) / r;
279     _a2 = (1 - c + d) / r;
280     _b1 = (2 - 2 * b) / r;
281     _b2 = (1 - a + b) / r;
282     r = 48.0f / fsamp;
283     a = 4.9886075f * r;
284     b = 6.2298014f * r * r;
285     r = 1 + a + b;
286     a *= 2 / r;
287     b *= 4 / r;
288     _c3 = a + b;
289     _c4 = b;
290     r = 1.004995f / r;
291     _a0 *= r;
292     _a1 *= r;
293     _a2 *= r;
294 }
295
296
297 void Ebu_r128_proc::detect_reset (void)
298 {
299     for (int i = 0; i < MAXCH; i++) _fst [i].reset ();
300 }
301
302
303 float Ebu_r128_proc::detect_process (int nfram)
304 {
305     int   i, j;
306     float si, sj;
307     float x, y, z1, z2, z3, z4;
308     float const *p;
309     Ebu_r128_fst *S;
310
311     si = 0;
312     for (i = 0, S = _fst; i < _nchan; i++, S++)
313     {
314         z1 = S->_z1;
315         z2 = S->_z2;
316         z3 = S->_z3;
317         z4 = S->_z4;
318         p = _ipp [i];
319         sj = 0;
320         for (j = 0; j < nfram; j++)
321         {
322             x = p [j] - _b1 * z1 - _b2 * z2 + 1e-15f;
323             y = _a0 * x + _a1 * z1 + _a2 * z2 - _c3 * z3 - _c4 * z4;
324             z2 = z1;
325             z1 = x;
326             z4 += z3;
327             z3 += y;
328             sj += y * y;
329         }
330         if (_nchan == 1) si = 2 * sj;
331         else si += _chan_gain [i] * sj;
332         S->_z1 = !isfinite(z1) ? 0 : z1;
333         S->_z2 = !isfinite(z2) ? 0 : z2;
334         S->_z3 = !isfinite(z3) ? 0 : z3;
335         S->_z4 = !isfinite(z4) ? 0 : z4;
336     }
337     return si;
338 }
339
340 };