Fix memory-leak in case of Vamp plugin setup error
[ardour.git] / libs / vamp-plugins / TruePeak.cpp
1 /*
2  * Copyright (C) 2006 Chris Cannam
3  * Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
4  * COPYRIGHT (C) 2012-2019 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 along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25
26 #include "TruePeak.h"
27
28 namespace TruePeakMeter {
29
30 static double sinc (double x)
31 {
32         x = fabs (x);
33         if (x < 1e-6) return 1.0;
34         x *= M_PI;
35         return sin (x) / x;
36 }
37
38 static double wind (double x)
39 {
40         x = fabs (x);
41         if (x >= 1.0) return 0.0f;
42         x *= M_PI;
43         return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x);
44 }
45
46 Resampler_table  *Resampler_table::_list = 0;
47 Resampler_mutex   Resampler_table::_mutex;
48
49 Resampler_table::Resampler_table (double fr, unsigned int hl, unsigned int np)
50         : _next (0)
51         , _refc (0)
52         , _fr (fr)
53         , _hl (hl)
54         , _np (np)
55 {
56         unsigned int  i, j;
57         double        t;
58         float        *p;
59
60         _ctab = new float [hl * (np + 1)];
61         p = _ctab;
62         for (j = 0; j <= np; j++)
63         {
64                 t = (double) j / (double) np;
65                 for (i = 0; i < hl; i++)
66                 {
67                         p [hl - i - 1] = (float)(fr * sinc (t * fr) * wind (t / hl));
68                         t += 1;
69                 }
70                 p += hl;
71         }
72 }
73
74 Resampler_table::~Resampler_table (void)
75 {
76         delete[] _ctab;
77 }
78
79 Resampler_table *
80 Resampler_table::create (double fr, unsigned int hl, unsigned int np)
81 {
82         Resampler_table *P;
83
84         _mutex.lock ();
85         P = _list;
86         while (P)
87         {
88                 if ((fr >= P->_fr * 0.999) && (fr <= P->_fr * 1.001) && (hl == P->_hl) && (np == P->_np))
89                 {
90                         P->_refc++;
91                         _mutex.unlock ();
92                         return P;
93                 }
94                 P = P->_next;
95         }
96         P = new Resampler_table (fr, hl, np);
97         P->_refc = 1;
98         P->_next = _list;
99         _list = P;
100         _mutex.unlock ();
101         return P;
102 }
103
104 void
105 Resampler_table::destroy (Resampler_table *T)
106 {
107         Resampler_table *P, *Q;
108
109         _mutex.lock ();
110         if (T)
111         {
112                 T->_refc--;
113                 if (T->_refc == 0)
114                 {
115                         P = _list;
116                         Q = 0;
117                         while (P)
118                         {
119                                 if (P == T)
120                                 {
121                                         if (Q) Q->_next = T->_next;
122                                         else      _list = T->_next;
123                                         break;
124                                 }
125                                 Q = P;
126                                 P = P->_next;
127                         }
128                         delete T;
129                 }
130         }
131         _mutex.unlock ();
132 }
133
134 static unsigned int
135 gcd (unsigned int a, unsigned int b)
136 {
137         if (a == 0) return b;
138         if (b == 0) return a;
139         while (1)
140         {
141                 if (a > b)
142                 {
143                         a = a % b;
144                         if (a == 0) return b;
145                         if (a == 1) return 1;
146                 }
147                 else
148                 {
149                         b = b % a;
150                         if (b == 0) return a;
151                         if (b == 1) return 1;
152                 }
153         }
154         return 1;
155 }
156
157 Resampler::Resampler (void)
158         : _table (0)
159         , _nchan (0)
160         , _buff  (0)
161 {
162         reset ();
163 }
164
165 Resampler::~Resampler (void)
166 {
167         clear ();
168 }
169
170 int
171 Resampler::setup (unsigned int fs_inp,
172                   unsigned int fs_out,
173                   unsigned int nchan,
174                   unsigned int hlen)
175 {
176         if ((hlen < 8) || (hlen > 96)) return 1;
177         return setup (fs_inp, fs_out, nchan, hlen, 1.0 - 2.6 / hlen);
178 }
179
180 int
181 Resampler::setup (unsigned int fs_inp,
182                   unsigned int fs_out,
183                   unsigned int nchan,
184                   unsigned int hlen,
185                   double       frel)
186 {
187         unsigned int       g, h, k, n, s;
188         double             r;
189         float              *B = 0;
190         Resampler_table    *T = 0;
191
192         k = s = 0;
193         if (fs_inp && fs_out && nchan)
194         {
195                 r = (double) fs_out / (double) fs_inp;
196                 g = gcd (fs_out, fs_inp);
197                 n = fs_out / g;
198                 s = fs_inp / g;
199                 if ((16 * r >= 1) && (n <= 1000))
200                 {
201                         h = hlen;
202                         k = 250;
203                         if (r < 1)
204                         {
205                                 frel *= r;
206                                 h = (unsigned int)(ceil (h / r));
207                                 k = (unsigned int)(ceil (k / r));
208                         }
209                         T = Resampler_table::create (frel, h, n);
210                         B = new float [nchan * (2 * h - 1 + k)];
211                 }
212         }
213         clear ();
214         if (T)
215         {
216                 _table = T;
217                 _buff  = B;
218                 _nchan = nchan;
219                 _inmax = k;
220                 _pstep = s;
221                 return reset ();
222         } else {
223                 delete[] B;
224                 return 1;
225         }
226 }
227
228 void
229 Resampler::clear (void)
230 {
231         Resampler_table::destroy (_table);
232         delete[] _buff;
233         _buff  = 0;
234         _table = 0;
235         _nchan = 0;
236         _inmax = 0;
237         _pstep = 0;
238         reset ();
239 }
240
241 double
242 Resampler::inpdist (void) const
243 {
244         if (!_table) return 0;
245         return (int)(_table->_hl + 1 - _nread) - (double)_phase / _table->_np;
246 }
247
248 int
249 Resampler::inpsize (void) const
250 {
251         if (!_table) return 0;
252         return 2 * _table->_hl;
253 }
254
255 int
256 Resampler::reset (void)
257 {
258         if (!_table) return 1;
259
260         inp_count = 0;
261         out_count = 0;
262         inp_data = 0;
263         out_data = 0;
264         _index = 0;
265         _nread = 0;
266         _nzero = 0;
267         _phase = 0;
268         if (_table)
269         {
270                 _nread = 2 * _table->_hl;
271                 return 0;
272         }
273         return 1;
274 }
275
276 int
277 Resampler::process (void)
278 {
279         unsigned int   hl, ph, np, dp, in, nr, nz, i, n, c;
280         float          *p1, *p2;
281
282         if (!_table) return 1;
283
284         hl = _table->_hl;
285         np = _table->_np;
286         dp = _pstep;
287         in = _index;
288         nr = _nread;
289         ph = _phase;
290         nz = _nzero;
291         n = (2 * hl - nr) * _nchan;
292         p1 = _buff + in * _nchan;
293         p2 = p1 + n;
294
295         while (out_count)
296         {
297                 if (nr)
298                 {
299                         if (inp_count == 0) break;
300                         if (inp_data)
301                         {
302                                 for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
303                                 inp_data += _nchan;
304                                 nz = 0;
305                         }
306                         else
307                         {
308                                 for (c = 0; c < _nchan; c++) p2 [c] = 0;
309                                 if (nz < 2 * hl) nz++;
310                         }
311                         nr--;
312                         p2 += _nchan;
313                         inp_count--;
314                 }
315                 else
316                 {
317                         if (out_data)
318                         {
319                                 if (nz < 2 * hl)
320                                 {
321                                         float *c1 = _table->_ctab + hl * ph;
322                                         float *c2 = _table->_ctab + hl * (np - ph);
323                                         for (c = 0; c < _nchan; c++)
324                                         {
325                                                 float *q1 = p1 + c;
326                                                 float *q2 = p2 + c;
327                                                 float s = 1e-20f;
328                                                 for (i = 0; i < hl; i++)
329                                                 {
330                                                         q2 -= _nchan;
331                                                         s += *q1 * c1 [i] + *q2 * c2 [i];
332                                                         q1 += _nchan;
333                                                 }
334                                                 *out_data++ = s - 1e-20f;
335                                         }
336                                 }
337                                 else
338                                 {
339                                         for (c = 0; c < _nchan; c++) *out_data++ = 0;
340                                 }
341                         }
342                         out_count--;
343
344                         ph += dp;
345                         if (ph >= np)
346                         {
347                                 nr = ph / np;
348                                 ph -= nr * np;
349                                 in += nr;
350                                 p1 += nr * _nchan;;
351                                 if (in >= _inmax)
352                                 {
353                                         n = (2 * hl - nr) * _nchan;
354                                         memcpy (_buff, p1, n * sizeof (float));
355                                         in = 0;
356                                         p1 = _buff;
357                                         p2 = p1 + n;
358                                 }
359                         }
360                 }
361         }
362         _index = in;
363         _nread = nr;
364         _phase = ph;
365         _nzero = nz;
366
367         return 0;
368 }
369
370 TruePeakdsp::TruePeakdsp (void)
371         : _m (0)
372         , _p (0)
373         , _res (true)
374         , _res_peak (true)
375         , _buf (NULL)
376 {
377 }
378
379 TruePeakdsp::~TruePeakdsp (void)
380 {
381         free(_buf);
382 }
383
384 void
385 TruePeakdsp::process (float const *d, int n)
386 {
387         _src.inp_count = n;
388         _src.inp_data = d;
389         _src.out_count = n * 4;
390         _src.out_data = _buf;
391         _src.process ();
392
393         float x = 0;
394         float v;
395         float *b = _buf;
396         while (n--) {
397                 v = fabsf(*b++);
398                 if (v > x) x = v;
399                 v = fabsf(*b++);
400                 if (v > x) x = v;
401                 v = fabsf(*b++);
402                 if (v > x) x = v;
403                 v = fabsf(*b++);
404                 if (v > x) x = v;
405         }
406
407         if (_res) {
408                 _m = x;
409                 _res = false;
410         } else if (x > _m) {
411                 _m = x;
412         }
413
414         if (_res_peak) {
415                 _p = x;
416                 _res_peak = false;
417         } else if (x > _p) {
418                 _p = x;
419         }
420 }
421
422 float
423 TruePeakdsp::read (void)
424 {
425         _res = true;
426         return _m;
427 }
428
429 void
430 TruePeakdsp::read (float &m, float &p)
431 {
432         _res = true;
433         _res_peak = true;
434         m = _m;
435         p = _p;
436 }
437
438 void
439 TruePeakdsp::reset ()
440 {
441         _res = true;
442         _m = 0;
443         _p = 0;
444 }
445
446 bool
447 TruePeakdsp::init (float fsamp)
448 {
449         _src.setup(fsamp, fsamp * 4.0, 1, 24, 1.0);
450         _buf = (float*) malloc(32768 * sizeof(float));
451         if (!_buf) {
452                 return false;
453         }
454
455         /* q/d initialize */
456         float zero[8192];
457         for (int i = 0; i < 8192; ++i) {
458                 zero[i]= 0.0;
459         }
460         _src.inp_count = 8192;
461         _src.inp_data = zero;
462         _src.out_count = 32768;
463         _src.out_data = _buf;
464         _src.process ();
465         return true;
466 }
467
468 }
469
470 ///////////////////////////////////////////////////////////////////////////////
471
472 using std::string;
473 using std::vector;
474 using std::cerr;
475 using std::endl;
476 using namespace TruePeakMeter;
477
478 VampTruePeak::VampTruePeak(float inputSampleRate)
479     : Plugin(inputSampleRate)
480     , m_blockSize(0)
481     , m_rate (inputSampleRate)
482 {
483 }
484
485 VampTruePeak::~VampTruePeak()
486 {
487 }
488
489 string
490 VampTruePeak::getIdentifier() const
491 {
492         return "dBTP";
493 }
494
495 string
496 VampTruePeak::getName() const
497 {
498         return "dBTP Meter";
499 }
500
501 string
502 VampTruePeak::getDescription() const
503 {
504         return "True Peak Meter (4x Oversampling)";
505 }
506
507 string
508 VampTruePeak::getMaker() const
509 {
510         return "Robin Gareus, Fons Adrianesen";
511 }
512
513 int
514 VampTruePeak::getPluginVersion() const
515 {
516         return 2;
517 }
518
519 string
520 VampTruePeak::getCopyright() const
521 {
522         return "GPL version 3 or later";
523 }
524
525 bool
526 VampTruePeak::initialise(size_t channels, size_t stepSize, size_t blockSize)
527 {
528         if (channels < getMinChannelCount() ||
529                         channels > getMaxChannelCount()) {
530                 return false;
531         }
532
533         if (blockSize == 0 || blockSize > 8192) {
534                 return false;
535         }
536
537         if (!_meter.init (m_inputSampleRate)) {
538                 return false;
539         }
540
541         m_blockSize = blockSize;
542
543         return true;
544 }
545
546 void
547 VampTruePeak::reset()
548 {
549         _meter.reset ();
550 }
551
552 VampTruePeak::OutputList
553 VampTruePeak::getOutputDescriptors() const
554 {
555         OutputList list;
556
557         OutputDescriptor zc;
558         zc.identifier = "level";
559         zc.name = "TruePeak";
560         zc.description = "TruePeak (4x Oversampling)";
561         zc.unit = "dbTP";
562         zc.hasFixedBinCount = true;
563         zc.binCount = 0;
564         zc.hasKnownExtents = false;
565         zc.isQuantized = false;
566         zc.sampleType = OutputDescriptor::OneSamplePerStep;
567         list.push_back(zc);
568
569         zc.identifier = "peaks";
570         zc.name = "TruePeakPeaks";
571         zc.description = "Location of Peaks above -1dBTP";
572         zc.unit = "sec";
573         zc.hasFixedBinCount = true;
574         zc.binCount = 0;
575         zc.hasKnownExtents = false;
576         zc.isQuantized = false;
577         zc.sampleType = OutputDescriptor::OneSamplePerStep;
578         list.push_back(zc);
579
580         return list;
581 }
582
583 VampTruePeak::FeatureSet
584 VampTruePeak::process(const float *const *inputBuffers,
585                       Vamp::RealTime timestamp)
586 {
587         if (m_blockSize == 0) {
588                 cerr << "ERROR: VampTruePeak::process: "
589                         << "VampTruePeak has not been initialised"
590                         << endl;
591                 return FeatureSet();
592         }
593
594         _meter.process (inputBuffers[0], m_blockSize);
595
596         // TODO optional (not rt safe)
597         if (_meter.read () >= .89125 /* -1dBTP */) {
598                 long f = Vamp::RealTime::realTime2Frame (timestamp, m_rate);
599                 _above_m1.values.push_back ((float) f);
600         }
601
602         return FeatureSet();
603 }
604
605 VampTruePeak::FeatureSet
606 VampTruePeak::getRemainingFeatures()
607 {
608         FeatureSet returnFeatures;
609
610         float m, p;
611         _meter.read(m, p);
612
613         Feature dbtp;
614         dbtp.hasTimestamp = false;
615         dbtp.values.push_back(p);
616         returnFeatures[0].push_back(dbtp);
617
618         _above_m1.hasTimestamp = false;
619         returnFeatures[1].push_back(_above_m1);
620
621         return returnFeatures;
622 }