2 * Copyright (C) 2013-2016 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
4 * Copyright (C) 2006 Chris Cannam
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 3 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
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 namespace TruePeakMeter {
29 static double sinc (double x)
32 if (x < 1e-6) return 1.0;
37 static double wind (double x)
40 if (x >= 1.0) return 0.0f;
42 return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x);
45 Resampler_table *Resampler_table::_list = 0;
46 Resampler_mutex Resampler_table::_mutex;
48 Resampler_table::Resampler_table (double fr, unsigned int hl, unsigned int np)
59 _ctab = new float [hl * (np + 1)];
61 for (j = 0; j <= np; j++)
63 t = (double) j / (double) np;
64 for (i = 0; i < hl; i++)
66 p [hl - i - 1] = (float)(fr * sinc (t * fr) * wind (t / hl));
73 Resampler_table::~Resampler_table (void)
79 Resampler_table::create (double fr, unsigned int hl, unsigned int np)
87 if ((fr >= P->_fr * 0.999) && (fr <= P->_fr * 1.001) && (hl == P->_hl) && (np == P->_np))
95 P = new Resampler_table (fr, hl, np);
104 Resampler_table::destroy (Resampler_table *T)
106 Resampler_table *P, *Q;
120 if (Q) Q->_next = T->_next;
121 else _list = T->_next;
134 gcd (unsigned int a, unsigned int b)
136 if (a == 0) return b;
137 if (b == 0) return a;
143 if (a == 0) return b;
144 if (a == 1) return 1;
149 if (b == 0) return a;
150 if (b == 1) return 1;
156 Resampler::Resampler (void)
164 Resampler::~Resampler (void)
170 Resampler::setup (unsigned int fs_inp,
175 if ((hlen < 8) || (hlen > 96)) return 1;
176 return setup (fs_inp, fs_out, nchan, hlen, 1.0 - 2.6 / hlen);
180 Resampler::setup (unsigned int fs_inp,
186 unsigned int g, h, k, n, s;
189 Resampler_table *T = 0;
192 if (fs_inp && fs_out && nchan)
194 r = (double) fs_out / (double) fs_inp;
195 g = gcd (fs_out, fs_inp);
198 if ((16 * r >= 1) && (n <= 1000))
205 h = (unsigned int)(ceil (h / r));
206 k = (unsigned int)(ceil (k / r));
208 T = Resampler_table::create (frel, h, n);
209 B = new float [nchan * (2 * h - 1 + k)];
226 Resampler::clear (void)
228 Resampler_table::destroy (_table);
239 Resampler::inpdist (void) const
241 if (!_table) return 0;
242 return (int)(_table->_hl + 1 - _nread) - (double)_phase / _table->_np;
246 Resampler::inpsize (void) const
248 if (!_table) return 0;
249 return 2 * _table->_hl;
253 Resampler::reset (void)
255 if (!_table) return 1;
267 _nread = 2 * _table->_hl;
274 Resampler::process (void)
276 unsigned int hl, ph, np, dp, in, nr, nz, i, n, c;
279 if (!_table) return 1;
288 n = (2 * hl - nr) * _nchan;
289 p1 = _buff + in * _nchan;
296 if (inp_count == 0) break;
299 for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
305 for (c = 0; c < _nchan; c++) p2 [c] = 0;
306 if (nz < 2 * hl) nz++;
318 float *c1 = _table->_ctab + hl * ph;
319 float *c2 = _table->_ctab + hl * (np - ph);
320 for (c = 0; c < _nchan; c++)
325 for (i = 0; i < hl; i++)
328 s += *q1 * c1 [i] + *q2 * c2 [i];
331 *out_data++ = s - 1e-20f;
336 for (c = 0; c < _nchan; c++) *out_data++ = 0;
350 n = (2 * hl - nr) * _nchan;
351 memcpy (_buff, p1, n * sizeof (float));
367 TruePeakdsp::TruePeakdsp (void)
375 TruePeakdsp::~TruePeakdsp (void)
381 TruePeakdsp::process (float const *d, int n)
385 _src.out_count = n * 4;
386 _src.out_data = _buf;
419 TruePeakdsp::read (void)
426 TruePeakdsp::read (float &m, float &p)
435 TruePeakdsp::reset ()
443 TruePeakdsp::init (float fsamp)
445 _src.setup(fsamp, fsamp * 4.0, 1, 24, 1.0);
446 _buf = (float*) malloc(32768 * sizeof(float));
453 for (int i = 0; i < 8192; ++i) {
456 _src.inp_count = 8192;
457 _src.inp_data = zero;
458 _src.out_count = 32768;
459 _src.out_data = _buf;
466 ///////////////////////////////////////////////////////////////////////////////
472 using namespace TruePeakMeter;
474 VampTruePeak::VampTruePeak(float inputSampleRate)
475 : Plugin(inputSampleRate)
477 , m_rate (inputSampleRate)
481 VampTruePeak::~VampTruePeak()
486 VampTruePeak::getIdentifier() const
492 VampTruePeak::getName() const
498 VampTruePeak::getDescription() const
500 return "True Peak Meter (4x Oversampling)";
504 VampTruePeak::getMaker() const
506 return "Robin Gareus, Fons Adrianesen";
510 VampTruePeak::getPluginVersion() const
516 VampTruePeak::getCopyright() const
518 return "GPL version 3 or later";
522 VampTruePeak::initialise(size_t channels, size_t stepSize, size_t blockSize)
524 if (channels < getMinChannelCount() ||
525 channels > getMaxChannelCount()) {
529 if (blockSize == 0 || blockSize > 8192) {
533 if (!_meter.init (m_inputSampleRate)) {
537 m_blockSize = blockSize;
543 VampTruePeak::reset()
548 VampTruePeak::OutputList
549 VampTruePeak::getOutputDescriptors() const
554 zc.identifier = "level";
555 zc.name = "TruePeak";
556 zc.description = "TruePeak (4x Oversampling)";
558 zc.hasFixedBinCount = true;
560 zc.hasKnownExtents = false;
561 zc.isQuantized = false;
562 zc.sampleType = OutputDescriptor::OneSamplePerStep;
565 zc.identifier = "peaks";
566 zc.name = "TruePeakPeaks";
567 zc.description = "Location of Peaks above -1dBTP";
569 zc.hasFixedBinCount = true;
571 zc.hasKnownExtents = false;
572 zc.isQuantized = false;
573 zc.sampleType = OutputDescriptor::OneSamplePerStep;
579 VampTruePeak::FeatureSet
580 VampTruePeak::process(const float *const *inputBuffers,
581 Vamp::RealTime timestamp)
583 if (m_blockSize == 0) {
584 cerr << "ERROR: VampTruePeak::process: "
585 << "VampTruePeak has not been initialised"
590 _meter.process (inputBuffers[0], m_blockSize);
592 // TODO optional (not rt safe)
593 if (_meter.read () >= .89125 /* -1dBTP */) {
594 long f = Vamp::RealTime::realTime2Frame (timestamp, m_rate);
595 _above_m1.values.push_back ((float) f);
601 VampTruePeak::FeatureSet
602 VampTruePeak::getRemainingFeatures()
604 FeatureSet returnFeatures;
610 dbtp.hasTimestamp = false;
611 dbtp.values.push_back(p);
612 returnFeatures[0].push_back(dbtp);
614 _above_m1.hasTimestamp = false;
615 returnFeatures[1].push_back(_above_m1);
617 return returnFeatures;