Mercurial > hg > vamp-aubio-plugins
view plugins/Silence.cpp @ 17:b85fbc77677b
* Add silence detector. But I'm not happy with its results: take a look at
the aubio silence detection code and see what's up
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 09 Oct 2007 15:42:36 +0000 |
parents | |
children | 70472f9558da |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Vamp feature extraction plugins using Paul Brossier's Aubio library. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006 Chris Cannam. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include <math.h> #include "Silence.h" using std::string; using std::vector; using std::cerr; using std::endl; Silence::Silence(float inputSampleRate) : Plugin(inputSampleRate), m_ibuf(0), m_pbuf(0), m_tmpptrs(0), m_threshold(-70), m_prevSilent(false), m_first(true) { } Silence::~Silence() { if (m_ibuf) del_fvec(m_ibuf); if (m_pbuf) del_fvec(m_pbuf); if (m_tmpptrs) delete[] m_tmpptrs; } string Silence::getIdentifier() const { return "aubiosilence"; } string Silence::getName() const { return "Aubio Silence Detector"; } string Silence::getDescription() const { return "Detect levels below a certain threshold"; } string Silence::getMaker() const { return "Paul Brossier (plugin by Chris Cannam)"; } int Silence::getPluginVersion() const { return 1; } string Silence::getCopyright() const { return "GPL"; } bool Silence::initialise(size_t channels, size_t stepSize, size_t blockSize) { m_channelCount = channels; m_stepSize = stepSize; m_blockSize = blockSize; m_ibuf = new_fvec(stepSize, channels); m_pbuf = new_fvec(stepSize, channels); m_tmpptrs = new smpl_t *[channels]; return true; } void Silence::reset() { m_first = true; } size_t Silence::getPreferredStepSize() const { return 1024; } size_t Silence::getPreferredBlockSize() const { return 1024; } Silence::ParameterList Silence::getParameterDescriptors() const { ParameterList list; ParameterDescriptor desc; desc = ParameterDescriptor(); desc.identifier = "silencethreshold"; desc.name = "Silence Threshold"; desc.minValue = -120; desc.maxValue = 0; desc.defaultValue = -70; desc.unit = "dB"; desc.isQuantized = false; list.push_back(desc); return list; } float Silence::getParameter(std::string param) const { if (param == "silencethreshold") { return m_threshold; } else { return 0.0; } } void Silence::setParameter(std::string param, float value) { if (param == "silencethreshold") { m_threshold = value; } } Silence::OutputList Silence::getOutputDescriptors() const { OutputList list; OutputDescriptor d; d.identifier = "silencestart"; d.name = "Starts of Silent Regions"; d.description = "Return a single instant at the point where each silent region begins"; d.hasFixedBinCount = true; d.binCount = 0; d.sampleType = OutputDescriptor::VariableSampleRate; list.push_back(d); d.identifier = "silenceend"; d.name = "Ends of Silent Regions"; d.description = "Return a single instant at the point where each silent region ends"; d.hasFixedBinCount = true; d.binCount = 0; d.sampleType = OutputDescriptor::VariableSampleRate; list.push_back(d); d.identifier = "silencelevel"; d.name = "Silence Test"; d.description = "Return a function that switches from 1 to 0 when silence falls, and back again when it ends"; d.hasFixedBinCount = true; d.binCount = 1; d.hasKnownExtents = true; d.minValue = 0; d.maxValue = 1; d.isQuantized = true; d.quantizeStep = 1; d.sampleType = OutputDescriptor::VariableSampleRate; list.push_back(d); return list; } Silence::FeatureSet Silence::process(const float *const *inputBuffers, Vamp::RealTime timestamp) { for (size_t i = 0; i < m_stepSize; ++i) { for (size_t j = 0; j < m_channelCount; ++j) { fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i); } } bool silent = aubio_silence_detection(m_ibuf, m_threshold); FeatureSet returnFeatures; if (m_first || m_prevSilent != silent) { Vamp::RealTime featureStamp = timestamp; if ((silent && !m_first) || !silent) { // refine our result long off = 0; size_t incr = 16; if (incr > m_stepSize/8) incr = m_stepSize/8; fvec_t vec; vec.length = incr * 4; vec.channels = m_channelCount; vec.data = m_tmpptrs; if (silent) { std::cerr << "silence at " << timestamp << std::endl; } for (size_t i = 0; i < m_stepSize - incr * 4; i += incr) { for (size_t j = 0; j < m_channelCount; ++j) { m_tmpptrs[j] = m_ibuf->data[j] + i; } bool subsilent = aubio_silence_detection(&vec, m_threshold); if (silent == subsilent) { std::cerr << "silent == subsilent at " << i << " after" << std::endl; off = i; break; } } if (silent && (off == 0)) { for (size_t i = 0; i < m_stepSize - incr; i += incr) { for (size_t j = 0; j < m_channelCount; ++j) { m_tmpptrs[j] = m_pbuf->data[j] + m_stepSize - i - incr; } bool subsilent = aubio_silence_detection(&vec, m_threshold); if (!subsilent) { std::cerr << "non-silence at " << i << " samples before" << std::endl; off = -(long)i; break; } else { std::cerr << "silence at " << i << " samples before" << std::endl; } } } else { } featureStamp = timestamp + Vamp::RealTime::frame2RealTime (off, lrintf(m_inputSampleRate)); } Feature feature; feature.hasTimestamp = true; feature.timestamp = featureStamp; feature.values.push_back(silent ? 0 : 1); returnFeatures[2].push_back(feature); feature.values.clear(); if (silent) { returnFeatures[0].push_back(feature); } else { returnFeatures[1].push_back(feature); } m_prevSilent = silent; m_first = false; } // swap ibuf and pbuf data pointers, so that this block's data is // available in pbuf when processing the next block, without // having to allocate new storage for it smpl_t **tmpdata = m_ibuf->data; m_ibuf->data = m_pbuf->data; m_pbuf->data = tmpdata; return returnFeatures; } Silence::FeatureSet Silence::getRemainingFeatures() { return FeatureSet(); }