X-Git-Url: https://git.aubio.org/?p=vamp-aubio-plugins.git;a=blobdiff_plain;f=plugins%2FPitch.cpp;h=5fd37301aab179389c2a828ad00ade1d63e4cedb;hp=635909d419d6607746a4e91d8fe634a41278f60c;hb=76eec45012ee0e4d999c3cc31debee1d533c0731;hpb=3144a5db172787cf4334b4cdd0ccd2eac7593ab0 diff --git a/plugins/Pitch.cpp b/plugins/Pitch.cpp index 635909d..5fd3730 100644 --- a/plugins/Pitch.cpp +++ b/plugins/Pitch.cpp @@ -22,34 +22,53 @@ using std::vector; using std::cerr; using std::endl; +static float +getFrequencyForMIDIPitch(int midiPitch) +{ + return 440.f * powf(2.0, (float(midiPitch) - 69.0) / 12.0); +} + Pitch::Pitch(float inputSampleRate) : Plugin(inputSampleRate), m_ibuf(0), + m_obuf(0), m_pitchdet(0), - m_pitchtype(aubio_pitch_yinfft), - m_pitchmode(aubio_pitchm_freq) + m_pitchtype(PitchYinFFT), + m_minfreq(getFrequencyForMIDIPitch(32)), + m_maxfreq(getFrequencyForMIDIPitch(95)), + m_silence(-90), + m_wrapRange(false), + m_stepSize(0), + m_blockSize(0) { } Pitch::~Pitch() { - if (m_pitchdet) del_aubio_pitchdetection(m_pitchdet); + if (m_pitchdet) del_aubio_pitch(m_pitchdet); if (m_ibuf) del_fvec(m_ibuf); + if (m_obuf) del_fvec(m_obuf); } string -Pitch::getName() const +Pitch::getIdentifier() const { return "aubiopitch"; } string -Pitch::getDescription() const +Pitch::getName() const { return "Aubio Pitch Detector"; } string +Pitch::getDescription() const +{ + return "Track estimated note pitches"; +} + +string Pitch::getMaker() const { return "Paul Brossier (plugin by Chris Cannam)"; @@ -58,7 +77,7 @@ Pitch::getMaker() const int Pitch::getPluginVersion() const { - return 1; + return 3; } string @@ -70,18 +89,18 @@ Pitch::getCopyright() const bool Pitch::initialise(size_t channels, size_t stepSize, size_t blockSize) { - m_channelCount = channels; + if (channels != 1) { + std::cerr << "Pitch::initialise: channels must be 1" << std::endl; + return false; + } + m_stepSize = stepSize; m_blockSize = blockSize; - m_ibuf = new_fvec(stepSize, channels); + m_ibuf = new_fvec(stepSize); + m_obuf = new_fvec(1); - m_pitchdet = new_aubio_pitchdetection(blockSize, - stepSize, - channels, - lrintf(m_inputSampleRate), - m_pitchtype, - m_pitchmode); + reset(); return true; } @@ -89,6 +108,15 @@ Pitch::initialise(size_t channels, size_t stepSize, size_t blockSize) void Pitch::reset() { + if (m_pitchdet) del_aubio_pitch(m_pitchdet); + + m_pitchdet = new_aubio_pitch + (const_cast(getAubioNameForPitchType(m_pitchtype)), + m_blockSize, + m_stepSize, + lrintf(m_inputSampleRate)); + + aubio_pitch_set_unit(m_pitchdet, const_cast("freq")); } size_t @@ -109,11 +137,11 @@ Pitch::getParameterDescriptors() const ParameterList list; ParameterDescriptor desc; - desc.name = "pitchtype"; - desc.description = "Pitch Detection Function Type"; + desc.identifier = "pitchtype"; + desc.name = "Pitch Detection Function Type"; desc.minValue = 0; desc.maxValue = 4; - desc.defaultValue = (int)aubio_pitch_yinfft; + desc.defaultValue = (int)PitchYinFFT; desc.isQuantized = true; desc.quantizeStep = 1; desc.valueNames.push_back("YIN Frequency Estimator"); @@ -123,6 +151,46 @@ Pitch::getParameterDescriptors() const desc.valueNames.push_back("YIN with FFT"); list.push_back(desc); + desc = ParameterDescriptor(); + desc.identifier = "minfreq"; + desc.name = "Minimum Fundamental Frequency"; + desc.minValue = 1; + desc.maxValue = m_inputSampleRate/2; + desc.defaultValue = getFrequencyForMIDIPitch(32); + desc.unit = "Hz"; + desc.isQuantized = false; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.identifier = "maxfreq"; + desc.name = "Maximum Fundamental Frequency"; + desc.minValue = 1; + desc.maxValue = m_inputSampleRate/2; + desc.defaultValue = getFrequencyForMIDIPitch(95); + desc.unit = "Hz"; + desc.isQuantized = false; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.identifier = "wraprange"; + desc.name = "Fold Higher or Lower Frequencies into Range"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.identifier = "silencethreshold"; + desc.name = "Silence Threshold"; + desc.minValue = -120; + desc.maxValue = 0; + desc.defaultValue = -90; + desc.unit = "dB"; + desc.isQuantized = false; + list.push_back(desc); + return list; } @@ -131,6 +199,14 @@ Pitch::getParameter(std::string param) const { if (param == "pitchtype") { return m_pitchtype; + } else if (param == "minfreq") { + return m_minfreq; + } else if (param == "maxfreq") { + return m_maxfreq; + } else if (param == "wraprange") { + return m_wrapRange ? 1.0 : 0.0; + } else if (param == "silencethreshold") { + return m_silence; } else { return 0.0; } @@ -141,12 +217,20 @@ Pitch::setParameter(std::string param, float value) { if (param == "pitchtype") { switch (lrintf(value)) { - case 0: m_pitchtype = aubio_pitch_yin; break; - case 1: m_pitchtype = aubio_pitch_mcomb; break; - case 2: m_pitchtype = aubio_pitch_schmitt; break; - case 3: m_pitchtype = aubio_pitch_fcomb; break; - case 4: m_pitchtype = aubio_pitch_yinfft; break; + case 0: m_pitchtype = PitchYin; break; + case 1: m_pitchtype = PitchMComb; break; + case 2: m_pitchtype = PitchSchmitt; break; + case 3: m_pitchtype = PitchFComb; break; + case 4: m_pitchtype = PitchYinFFT; break; } + } else if (param == "minfreq") { + m_minfreq = value; + } else if (param == "maxfreq") { + m_maxfreq = value; + } else if (param == "wraprange") { + m_wrapRange = (value > 0.5); + } else if (param == "silencethreshold") { + m_silence = value; } } @@ -156,14 +240,18 @@ Pitch::getOutputDescriptors() const OutputList list; OutputDescriptor d; - d.name = "frequency"; + d.identifier = "frequency"; + d.name = "Fundamental Frequency"; d.unit = "Hz"; - d.description = "Frequency"; d.hasFixedBinCount = true; d.binCount = 1; d.hasKnownExtents = false; d.isQuantized = false; - d.sampleType = OutputDescriptor::OneSamplePerStep; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + if (m_stepSize != 0) { + d.sampleRate = m_inputSampleRate / m_stepSize; + } list.push_back(d); return list; @@ -171,21 +259,47 @@ Pitch::getOutputDescriptors() const Pitch::FeatureSet Pitch::process(const float *const *inputBuffers, - Vamp::RealTime /* timestamp */) + Vamp::RealTime timestamp) { + FeatureSet returnFeatures; + + if (m_stepSize == 0) { + std::cerr << "Pitch::process: Pitch plugin not initialised" << std::endl; + return returnFeatures; + } + 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); + fvec_write_sample(m_ibuf, inputBuffers[0][i], i); + } + + aubio_pitch_do(m_pitchdet, m_ibuf, m_obuf); + + float freq = m_obuf->data[0]; + + bool silent = aubio_silence_detection(m_ibuf, m_silence); + if (silent) { +// std::cerr << "(silent)" << std::endl; + return returnFeatures; + } + + if (m_wrapRange) { + while (freq > 0 && freq < m_minfreq) { + freq = freq * 2.0; + } + while (freq > m_maxfreq) { + freq = freq / 2.0; } } - float pitch = aubio_pitchdetection(m_pitchdet, m_ibuf); + if (freq < m_minfreq || freq > m_maxfreq) { + return returnFeatures; + } Feature feature; - feature.hasTimestamp = false; - feature.values.push_back(pitch); + feature.hasTimestamp = true; + feature.timestamp = timestamp; + feature.values.push_back(freq); - FeatureSet returnFeatures; returnFeatures[0].push_back(feature); return returnFeatures; }