Chris@23: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ matthiasm@0: Chris@35: /* Chris@35: NNLS-Chroma / Chordino Chris@35: Chris@35: Audio feature extraction plugins for chromagram and chord Chris@35: estimation. Chris@35: Chris@35: Centre for Digital Music, Queen Mary University of London. Chris@35: This file copyright 2008-2010 Matthias Mauch and QMUL. Chris@35: Chris@35: This program is free software; you can redistribute it and/or Chris@35: modify it under the terms of the GNU General Public License as Chris@35: published by the Free Software Foundation; either version 2 of the Chris@35: License, or (at your option) any later version. See the file Chris@35: COPYING included with this distribution for more information. Chris@35: */ Chris@35: Chris@35: #include "Tuning.h" Chris@27: Chris@27: #include "chromamethods.h" Chris@27: Chris@27: #include Chris@27: #include matthiasm@0: #include matthiasm@9: Chris@27: #include matthiasm@0: matthiasm@0: const bool debug_on = false; matthiasm@0: Chris@35: Tuning::Tuning(float inputSampleRate) : Chris@35: NNLSBase(inputSampleRate) matthiasm@0: { Chris@35: if (debug_on) cerr << "--> Tuning" << endl; matthiasm@0: } matthiasm@0: Chris@35: Tuning::~Tuning() matthiasm@0: { Chris@35: if (debug_on) cerr << "--> ~Tuning" << endl; matthiasm@0: } matthiasm@0: matthiasm@52: size_t matthiasm@52: Tuning::getPreferredStepSize() const matthiasm@52: { matthiasm@52: if (debug_on) cerr << "--> getPreferredStepSize" << endl; matthiasm@52: return 2048*4; matthiasm@52: } matthiasm@52: matthiasm@0: string Chris@35: Tuning::getIdentifier() const matthiasm@0: { Chris@23: if (debug_on) cerr << "--> getIdentifier" << endl; Chris@35: return "tuning"; matthiasm@0: } matthiasm@0: matthiasm@0: string Chris@35: Tuning::getName() const matthiasm@0: { Chris@23: if (debug_on) cerr << "--> getName" << endl; Chris@35: return "Tuning"; matthiasm@0: } matthiasm@0: matthiasm@0: string Chris@35: Tuning::getDescription() const matthiasm@0: { matthiasm@0: // Return something helpful here! Chris@23: if (debug_on) cerr << "--> getDescription" << endl; matthiasm@58: return "The tuning plugin can estimate the local and global tuning of piece. The same tuning method is used for the NNLS Chroma and Chordino plugins."; matthiasm@0: } matthiasm@0: matthiasm@52: Tuning::ParameterList matthiasm@52: Tuning::getParameterDescriptors() const matthiasm@52: { matthiasm@52: if (debug_on) cerr << "--> getParameterDescriptors" << endl; matthiasm@52: ParameterList list; matthiasm@52: matthiasm@52: ParameterDescriptor d0; matthiasm@52: d0.identifier = "rollon"; mail@114: d0.name = "bass noise threshold"; mail@114: d0.description = "Consider the cumulative energy spectrum (from low to high frequencies). All bins below the first bin whose cumulative energy exceeds the quantile [bass noise threshold] x [total energy] will be set to 0. A threshold value of 0 means that no bins will be changed."; matthiasm@59: d0.unit = "%"; matthiasm@52: d0.minValue = 0; matthiasm@59: d0.maxValue = 5; matthiasm@52: d0.defaultValue = 0; matthiasm@52: d0.isQuantized = true; matthiasm@59: d0.quantizeStep = 0.5; matthiasm@52: list.push_back(d0); matthiasm@52: matthiasm@52: matthiasm@52: return list; matthiasm@52: } matthiasm@52: Chris@35: Tuning::OutputList Chris@35: Tuning::getOutputDescriptors() const matthiasm@0: { Chris@23: if (debug_on) cerr << "--> getOutputDescriptors" << endl; matthiasm@0: OutputList list; matthiasm@0: Chris@35: int index = 0; matthiasm@0: matthiasm@0: OutputDescriptor d0; matthiasm@0: d0.identifier = "tuning"; matthiasm@0: d0.name = "Tuning"; matthiasm@58: d0.description = "Returns a single label (at time 0 seconds) containing an estimate of the concert pitch in Hz."; matthiasm@0: d0.unit = "Hz"; matthiasm@0: d0.hasFixedBinCount = true; mail@71: d0.binCount = 1; matthiasm@0: d0.hasKnownExtents = true; Chris@23: d0.minValue = 427.47; Chris@23: d0.maxValue = 452.89; matthiasm@0: d0.isQuantized = false; matthiasm@0: d0.sampleType = OutputDescriptor::VariableSampleRate; mail@71: d0.hasDuration = true; matthiasm@0: list.push_back(d0); Chris@35: m_outputTuning = index++; matthiasm@0: Chris@23: OutputDescriptor d10; Chris@23: d10.identifier = "localtuning"; Chris@37: d10.name = "Local Tuning"; matthiasm@58: d10.description = "Returns a tuning estimate at every analysis frame, an average of the (recent) previous frame-wise estimates of the concert pitch in Hz."; Chris@23: d10.unit = "Hz"; Chris@23: d10.hasFixedBinCount = true; Chris@23: d10.binCount = 1; Chris@23: d10.hasKnownExtents = true; Chris@23: d10.minValue = 427.47; Chris@23: d10.maxValue = 452.89; Chris@23: d10.isQuantized = false; Chris@23: d10.sampleType = OutputDescriptor::FixedSampleRate; Chris@164: d10.sampleRate = (m_stepSize == 0) ? m_inputSampleRate/2048 : m_inputSampleRate/m_stepSize; Chris@23: d10.hasDuration = false; Chris@23: list.push_back(d10); Chris@35: m_outputLocalTuning = index++; matthiasm@1: matthiasm@0: return list; matthiasm@0: } matthiasm@0: matthiasm@0: matthiasm@0: bool Chris@35: Tuning::initialise(size_t channels, size_t stepSize, size_t blockSize) matthiasm@0: { Chris@23: if (debug_on) { Chris@23: cerr << "--> initialise"; Chris@23: } matthiasm@1: Chris@35: if (!NNLSBase::initialise(channels, stepSize, blockSize)) { Chris@35: return false; Chris@35: } matthiasm@1: matthiasm@0: return true; matthiasm@0: } matthiasm@0: matthiasm@0: void Chris@35: Tuning::reset() matthiasm@0: { Chris@23: if (debug_on) cerr << "--> reset"; Chris@35: NNLSBase::reset(); matthiasm@0: } matthiasm@0: Chris@35: Tuning::FeatureSet Chris@35: Tuning::process(const float *const *inputBuffers, Vamp::RealTime timestamp) matthiasm@0: { Chris@23: if (debug_on) cerr << "--> process" << endl; Chris@35: Chris@35: NNLSBase::baseProcess(inputBuffers, timestamp); matthiasm@0: Chris@23: Feature f10; // local tuning Chris@23: f10.hasTimestamp = true; Chris@23: f10.timestamp = timestamp; Chris@35: float normalisedtuning = m_localTuning[m_localTuning.size()-1]; Chris@23: float tuning440 = 440 * pow(2,normalisedtuning/12); Chris@23: f10.values.push_back(tuning440); matthiasm@0: Chris@23: FeatureSet fs; Chris@35: fs[m_outputLocalTuning].push_back(f10); Chris@23: return fs; matthiasm@0: } matthiasm@0: Chris@35: Tuning::FeatureSet Chris@35: Tuning::getRemainingFeatures() matthiasm@0: { Chris@23: if (debug_on) cerr << "--> getRemainingFeatures" << endl; Chris@23: FeatureSet fsOut; Chris@35: if (m_logSpectrum.size() == 0) return fsOut; Chris@35: Chris@23: // Chris@23: /** Calculate Tuning Chris@23: calculate tuning from (using the angle of the complex number defined by the Chris@23: cumulative mean real and imag values) Chris@23: **/ mail@80: mail@80: float meanTuningImag = 0; mail@80: float meanTuningReal = 0; mail@80: for (int iBPS = 0; iBPS < nBPS; ++iBPS) { mail@80: meanTuningReal += m_meanTunings[iBPS] * cosvalues[iBPS]; mail@80: meanTuningImag += m_meanTunings[iBPS] * sinvalues[iBPS]; mail@80: } mail@80: mail@80: Chris@23: float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI)); matthiasm@1: Chris@23: char buffer0 [50]; matthiasm@1: matthiasm@59: sprintf(buffer0, "%0.1f Hz", cumulativetuning); matthiasm@1: Chris@23: // push tuning to FeatureSet fsOut Chris@23: Feature f0; // tuning Chris@23: f0.hasTimestamp = true; matthiasm@59: f0.timestamp = Vamp::RealTime::frame2RealTime(0, lrintf(m_inputSampleRate)); matthiasm@59: f0.values.push_back(cumulativetuning); Chris@23: f0.label = buffer0; mail@71: f0.hasDuration = true; mail@71: f0.duration = m_logSpectrum[m_logSpectrum.size()-1].timestamp; Chris@35: fsOut[m_outputTuning].push_back(f0); matthiasm@1: Chris@23: return fsOut; matthiasm@0: matthiasm@0: } matthiasm@0: