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>
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.
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.
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.
28 namespace TruePeakMeter {
30 static double sinc (double x)
33 if (x < 1e-6) return 1.0;
38 static double wind (double x)
41 if (x >= 1.0) return 0.0f;
43 return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x);
46 Resampler_table *Resampler_table::_list = 0;
47 Resampler_mutex Resampler_table::_mutex;
49 Resampler_table::Resampler_table (double fr, unsigned int hl, unsigned int np)
60 _ctab = new float [hl * (np + 1)];
62 for (j = 0; j <= np; j++)
64 t = (double) j / (double) np;
65 for (i = 0; i < hl; i++)
67 p [hl - i - 1] = (float)(fr * sinc (t * fr) * wind (t / hl));
74 Resampler_table::~Resampler_table (void)
80 Resampler_table::create (double fr, unsigned int hl, unsigned int np)
88 if ((fr >= P->_fr * 0.999) && (fr <= P->_fr * 1.001) && (hl == P->_hl) && (np == P->_np))
96 P = new Resampler_table (fr, hl, np);
105 Resampler_table::destroy (Resampler_table *T)
107 Resampler_table *P, *Q;
121 if (Q) Q->_next = T->_next;
122 else _list = T->_next;
135 gcd (unsigned int a, unsigned int b)
137 if (a == 0) return b;
138 if (b == 0) return a;
144 if (a == 0) return b;
145 if (a == 1) return 1;
150 if (b == 0) return a;
151 if (b == 1) return 1;
157 Resampler::Resampler (void)
165 Resampler::~Resampler (void)
171 Resampler::setup (unsigned int fs_inp,
176 if ((hlen < 8) || (hlen > 96)) return 1;
177 return setup (fs_inp, fs_out, nchan, hlen, 1.0 - 2.6 / hlen);
181 Resampler::setup (unsigned int fs_inp,
187 unsigned int g, h, k, n, s;
190 Resampler_table *T = 0;
193 if (fs_inp && fs_out && nchan)
195 r = (double) fs_out / (double) fs_inp;
196 g = gcd (fs_out, fs_inp);
199 if ((16 * r >= 1) && (n <= 1000))
206 h = (unsigned int)(ceil (h / r));
207 k = (unsigned int)(ceil (k / r));
209 T = Resampler_table::create (frel, h, n);
210 B = new float [nchan * (2 * h - 1 + k)];
229 Resampler::clear (void)
231 Resampler_table::destroy (_table);
242 Resampler::inpdist (void) const
244 if (!_table) return 0;
245 return (int)(_table->_hl + 1 - _nread) - (double)_phase / _table->_np;
249 Resampler::inpsize (void) const
251 if (!_table) return 0;
252 return 2 * _table->_hl;
256 Resampler::reset (void)
258 if (!_table) return 1;
270 _nread = 2 * _table->_hl;
277 Resampler::process (void)
279 unsigned int hl, ph, np, dp, in, nr, nz, i, n, c;
282 if (!_table) return 1;
291 n = (2 * hl - nr) * _nchan;
292 p1 = _buff + in * _nchan;
299 if (inp_count == 0) break;
302 for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
308 for (c = 0; c < _nchan; c++) p2 [c] = 0;
309 if (nz < 2 * hl) nz++;
321 float *c1 = _table->_ctab + hl * ph;
322 float *c2 = _table->_ctab + hl * (np - ph);
323 for (c = 0; c < _nchan; c++)
328 for (i = 0; i < hl; i++)
331 s += *q1 * c1 [i] + *q2 * c2 [i];
334 *out_data++ = s - 1e-20f;
339 for (c = 0; c < _nchan; c++) *out_data++ = 0;
353 n = (2 * hl - nr) * _nchan;
354 memcpy (_buff, p1, n * sizeof (float));
370 TruePeakdsp::TruePeakdsp (void)
379 TruePeakdsp::~TruePeakdsp (void)
385 TruePeakdsp::process (float const *d, int n)
389 _src.out_count = n * 4;
390 _src.out_data = _buf;
423 TruePeakdsp::read (void)
430 TruePeakdsp::read (float &m, float &p)
439 TruePeakdsp::reset ()
447 TruePeakdsp::init (float fsamp)
449 _src.setup(fsamp, fsamp * 4.0, 1, 24, 1.0);
450 _buf = (float*) malloc(32768 * sizeof(float));
457 for (int i = 0; i < 8192; ++i) {
460 _src.inp_count = 8192;
461 _src.inp_data = zero;
462 _src.out_count = 32768;
463 _src.out_data = _buf;
470 ///////////////////////////////////////////////////////////////////////////////
476 using namespace TruePeakMeter;
478 VampTruePeak::VampTruePeak(float inputSampleRate)
479 : Plugin(inputSampleRate)
481 , m_rate (inputSampleRate)
485 VampTruePeak::~VampTruePeak()
490 VampTruePeak::getIdentifier() const
496 VampTruePeak::getName() const
502 VampTruePeak::getDescription() const
504 return "True Peak Meter (4x Oversampling)";
508 VampTruePeak::getMaker() const
510 return "Robin Gareus, Fons Adrianesen";
514 VampTruePeak::getPluginVersion() const
520 VampTruePeak::getCopyright() const
522 return "GPL version 3 or later";
526 VampTruePeak::initialise(size_t channels, size_t stepSize, size_t blockSize)
528 if (channels < getMinChannelCount() ||
529 channels > getMaxChannelCount()) {
533 if (blockSize == 0 || blockSize > 8192) {
537 if (!_meter.init (m_inputSampleRate)) {
541 m_blockSize = blockSize;
547 VampTruePeak::reset()
552 VampTruePeak::OutputList
553 VampTruePeak::getOutputDescriptors() const
558 zc.identifier = "level";
559 zc.name = "TruePeak";
560 zc.description = "TruePeak (4x Oversampling)";
562 zc.hasFixedBinCount = true;
564 zc.hasKnownExtents = false;
565 zc.isQuantized = false;
566 zc.sampleType = OutputDescriptor::OneSamplePerStep;
569 zc.identifier = "peaks";
570 zc.name = "TruePeakPeaks";
571 zc.description = "Location of Peaks above -1dBTP";
573 zc.hasFixedBinCount = true;
575 zc.hasKnownExtents = false;
576 zc.isQuantized = false;
577 zc.sampleType = OutputDescriptor::OneSamplePerStep;
583 VampTruePeak::FeatureSet
584 VampTruePeak::process(const float *const *inputBuffers,
585 Vamp::RealTime timestamp)
587 if (m_blockSize == 0) {
588 cerr << "ERROR: VampTruePeak::process: "
589 << "VampTruePeak has not been initialised"
594 _meter.process (inputBuffers[0], m_blockSize);
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);
605 VampTruePeak::FeatureSet
606 VampTruePeak::getRemainingFeatures()
608 FeatureSet returnFeatures;
614 dbtp.hasTimestamp = false;
615 dbtp.values.push_back(p);
616 returnFeatures[0].push_back(dbtp);
618 _above_m1.hasTimestamp = false;
619 returnFeatures[1].push_back(_above_m1);
621 return returnFeatures;