Mercurial > hg > vamp-aubio-plugins
changeset 7:4493cb063598
* Add tempo tracker plugin from piem
* Add various MIDI note range options to note tracker
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 22 May 2006 11:43:23 +0000 |
parents | 1ad0444bd0ff |
children | 616d69a5bb5e |
files | libmain.cpp plugins/Notes.cpp plugins/Notes.h plugins/Tempo.cpp plugins/Tempo.h |
diffstat | 5 files changed, 471 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/libmain.cpp Wed May 17 15:44:30 2006 +0000 +++ b/libmain.cpp Mon May 22 11:43:23 2006 +0000 @@ -20,10 +20,12 @@ #include "plugins/Onset.h" #include "plugins/Pitch.h" #include "plugins/Notes.h" +#include "plugins/Tempo.h" static Vamp::PluginAdapter<Onset> onsetAdapter; static Vamp::PluginAdapter<Pitch> pitchAdapter; static Vamp::PluginAdapter<Notes> notesAdapter; +static Vamp::PluginAdapter<Tempo> tempoAdapter; const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int index) { @@ -31,6 +33,7 @@ case 0: return onsetAdapter.getDescriptor(); case 1: return pitchAdapter.getDescriptor(); case 2: return notesAdapter.getDescriptor(); + case 3: return tempoAdapter.getDescriptor(); default: return 0; } }
--- a/plugins/Notes.cpp Wed May 17 15:44:30 2006 +0000 +++ b/plugins/Notes.cpp Mon May 22 11:43:23 2006 +0000 @@ -36,7 +36,12 @@ m_pitchmode(aubio_pitchm_freq), m_threshold(0.3), m_silence(-90), - m_median(6) + m_median(6), + m_minpitch(32), + m_maxpitch(95), + m_wrapRange(false), + m_avoidLeaps(false), + m_prevPitch(-1) { } @@ -116,6 +121,7 @@ lrintf(m_inputSampleRate)); m_currentOnset = Vamp::RealTime::zeroTime; m_haveCurrent = false; + m_prevPitch = -1; return true; } @@ -175,6 +181,48 @@ list.push_back(desc); desc = ParameterDescriptor(); + desc.name = "minpitch"; + desc.description = "Minimum Pitch"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 32; + desc.unit = "MIDI units"; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.name = "maxpitch"; + desc.description = "Maximum Pitch"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 95; + desc.unit = "MIDI units"; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.name = "wraprange"; + desc.description = "Fold Higher or Lower Notes into Range"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.name = "avoidleaps"; + desc.description = "Avoid Multi-Octave Jumps"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc = ParameterDescriptor(); desc.name = "peakpickthreshold"; desc.description = "Peak Picker Threshold"; desc.minValue = 0; @@ -207,6 +255,14 @@ return m_threshold; } else if (param == "silencethreshold") { return m_silence; + } else if (param == "minpitch") { + return m_minpitch; + } else if (param == "maxpitch") { + return m_maxpitch; + } else if (param == "wraprange") { + return m_wrapRange ? 1.0 : 0.0; + } else if (param == "avoidleaps") { + return m_avoidLeaps ? 1.0 : 0.0; } else { return 0.0; } @@ -237,6 +293,14 @@ m_threshold = value; } else if (param == "silencethreshold") { m_silence = value; + } else if (param == "minpitch") { + m_minpitch = lrintf(value); + } else if (param == "maxpitch") { + m_maxpitch = lrintf(value); + } else if (param == "wraprange") { + m_wrapRange = (value > 0.5); + } else if (param == "avoidleaps") { + m_avoidLeaps = (value > 0.5); } } @@ -324,12 +388,41 @@ float median = toSort[toSort.size()/2]; if (median < 45.0) return; + float freq = median; + int midiPitch = (int)FLOOR(aubio_freqtomidi(freq) + 0.5); + + if (m_avoidLeaps) { + if (m_prevPitch >= 0) { + while (midiPitch < m_prevPitch - 12) { + midiPitch += 12; + freq *= 2; + } + while (midiPitch > m_prevPitch + 12) { + midiPitch -= 12; + freq /= 2; + } + } + } + + while (midiPitch < m_minpitch) { + if (!m_wrapRange) return; + midiPitch += 12; + freq *= 2; + } + + while (midiPitch > m_maxpitch) { + if (!m_wrapRange) return; + midiPitch -= 12; + freq /= 2; + } + + m_prevPitch = midiPitch; + Feature feature; feature.hasTimestamp = true; if (m_currentOnset < m_delay) m_currentOnset = m_delay; feature.timestamp = m_currentOnset - m_delay; - feature.values.push_back(median); -// feature.values.push_back(FLOOR(aubio_freqtomidi(median) + 0.5)); + feature.values.push_back(freq); feature.values.push_back (Vamp::RealTime::realTime2Frame(offTime, lrintf(m_inputSampleRate)) - Vamp::RealTime::realTime2Frame(m_currentOnset, lrintf(m_inputSampleRate)));
--- a/plugins/Notes.h Wed May 17 15:44:30 2006 +0000 +++ b/plugins/Notes.h Mon May 22 11:43:23 2006 +0000 @@ -69,6 +69,10 @@ size_t m_stepSize; size_t m_blockSize; size_t m_channelCount; + int m_minpitch; + int m_maxpitch; + bool m_wrapRange; + bool m_avoidLeaps; std::deque<float> m_notebuf; size_t m_count; Vamp::RealTime m_delay; @@ -76,6 +80,7 @@ Vamp::RealTime m_lastTimeStamp; float m_currentLevel; bool m_haveCurrent; + int m_prevPitch; void pushNote(FeatureSet &, const Vamp::RealTime &); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/Tempo.cpp Mon May 22 11:43:23 2006 +0000 @@ -0,0 +1,290 @@ +/* -*- 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 "Tempo.h" + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +Tempo::Tempo(float inputSampleRate) : + Plugin(inputSampleRate), + m_ibuf(0), + m_fftgrain(0), + m_onset(0), + m_pv(0), + m_peakpick(0), + m_onsetdet(0), + m_onsettype(aubio_onset_specdiff), + m_beattracking(0), + m_dfframe(0), + m_btout(0), + m_btcounter(0), + m_threshold(0.3), + m_silence(-90), + m_channelCount(1) +{ +} + +Tempo::~Tempo() +{ + if (m_onsetdet) aubio_onsetdetection_free(m_onsetdet); + if (m_ibuf) del_fvec(m_ibuf); + if (m_onset) del_fvec(m_onset); + if (m_fftgrain) del_cvec(m_fftgrain); + if (m_pv) del_aubio_pvoc(m_pv); + if (m_peakpick) del_aubio_peakpicker(m_peakpick); + if (m_beattracking) del_aubio_beattracking(m_beattracking); + if (m_dfframe) del_fvec(m_dfframe); + if (m_btout) del_fvec(m_btout); +} + +string +Tempo::getName() const +{ + return "aubiotempo"; +} + +string +Tempo::getDescription() const +{ + return "Aubio Tempo Detector"; +} + +string +Tempo::getMaker() const +{ + return "Paul Brossier (plugin by Chris Cannam)"; +} + +int +Tempo::getPluginVersion() const +{ + return 1; +} + +string +Tempo::getCopyright() const +{ + return "GPL"; +} + +bool +Tempo::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_onset = new_fvec(1, channels); + m_fftgrain = new_cvec(blockSize, channels); + m_pv = new_aubio_pvoc(blockSize, stepSize, channels); + m_peakpick = new_aubio_peakpicker(m_threshold); + + m_onsetdet = new_aubio_onsetdetection(m_onsettype, blockSize, channels); + + m_delay = Vamp::RealTime::frame2RealTime(3 * stepSize, + lrintf(m_inputSampleRate)); + + m_lastBeat = Vamp::RealTime::zeroTime - m_delay - m_delay; + + m_winlen = 512*512/stepSize; + m_dfframe = new_fvec(m_winlen,channels); + m_btstep = m_winlen/4; + m_btout = new_fvec(m_btstep,channels); + m_beattracking = new_aubio_beattracking(m_winlen,channels); + + return true; +} + +void +Tempo::reset() +{ +} + +size_t +Tempo::getPreferredStepSize() const +{ + return 512; +} + +size_t +Tempo::getPreferredBlockSize() const +{ + return 2 * getPreferredStepSize(); +} + +Tempo::ParameterList +Tempo::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.name = "onsettype"; + desc.description = "Onset Detection Function Type"; + desc.minValue = 0; + desc.maxValue = 6; + desc.defaultValue = (int)aubio_onset_complex; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Energy Based"); + desc.valueNames.push_back("Spectral Difference"); + desc.valueNames.push_back("High-Frequency Content"); + desc.valueNames.push_back("Complex Domain"); + desc.valueNames.push_back("Phase Deviation"); + desc.valueNames.push_back("Kullback-Liebler"); + desc.valueNames.push_back("Modified Kullback-Liebler"); + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.name = "peakpickthreshold"; + desc.description = "Peak Picker Threshold"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0.3; + desc.isQuantized = false; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.name = "silencethreshold"; + desc.description = "Silence Threshold"; + desc.minValue = -120; + desc.maxValue = 0; + desc.defaultValue = -90; + desc.unit = "dB"; + desc.isQuantized = false; + list.push_back(desc); + + return list; +} + +float +Tempo::getParameter(std::string param) const +{ + if (param == "onsettype") { + return m_onsettype; + } else if (param == "peakpickthreshold") { + return m_threshold; + } else if (param == "silencethreshold") { + return m_silence; + } else { + return 0.0; + } +} + +void +Tempo::setParameter(std::string param, float value) +{ + if (param == "onsettype") { + switch (lrintf(value)) { + case 0: m_onsettype = aubio_onset_energy; break; + case 1: m_onsettype = aubio_onset_specdiff; break; + case 2: m_onsettype = aubio_onset_hfc; break; + case 3: m_onsettype = aubio_onset_complex; break; + case 4: m_onsettype = aubio_onset_phase; break; + case 5: m_onsettype = aubio_onset_kl; break; + case 6: m_onsettype = aubio_onset_mkl; break; + } + } else if (param == "peakpickthreshold") { + m_threshold = value; + } else if (param == "silencethreshold") { + m_silence = value; + } +} + +Tempo::OutputList +Tempo::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.name = "beats"; + d.unit = ""; + d.description = "Beats"; + d.hasFixedBinCount = true; + d.binCount = 0; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + list.push_back(d); + + return list; +} + +Tempo::FeatureSet +Tempo::process(float **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); + } + } + + aubio_pvoc_do(m_pv, m_ibuf, m_fftgrain); + aubio_onsetdetection(m_onsetdet, m_fftgrain, m_onset); + + if ( m_btcounter == m_btstep - 1 ) { + aubio_beattracking_do(m_beattracking,m_dfframe,m_btout); + /* rotate dfframe */ + for (size_t i = 0 ; i < m_winlen - m_btstep; i++ ) + m_dfframe->data[0][i] = m_dfframe->data[0][i+m_btstep]; + for (size_t i = m_winlen - m_btstep ; i < m_winlen; i++ ) + m_dfframe->data[0][i] = 0.; + + m_btcounter = -1; + } + m_btcounter++; + bool isonset = aubio_peakpick_pimrt_wt( m_onset, m_peakpick, + &(m_dfframe->data[0][m_winlen - m_btstep + m_btcounter])); + bool istactus = 0; + + + /* check if any of the predicted beat correspond to the current time */ + for (size_t i = 1; i < m_btout->data[0][0]; i++ ) { + if (m_btcounter == m_btout->data[0][i]) { + if (aubio_silence_detection(m_ibuf, m_silence)) { + isonset = false; + istactus = false; + } else { + istactus = true; + } + } + } + + FeatureSet returnFeatures; + + if (istactus == true) { + if (timestamp - m_lastBeat >= m_delay) { + Feature onsettime; + onsettime.hasTimestamp = true; + if (timestamp < m_delay) timestamp = m_delay; + onsettime.timestamp = timestamp - m_delay; + returnFeatures[0].push_back(onsettime); + m_lastBeat = timestamp; + } + } + + return returnFeatures; +} + +Tempo::FeatureSet +Tempo::getRemainingFeatures() +{ + return FeatureSet(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/Tempo.h Mon May 22 11:43:23 2006 +0000 @@ -0,0 +1,77 @@ +/* -*- 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. + +*/ + +#ifndef _TEMPO_PLUGIN_H_ +#define _TEMPO_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <aubio/aubio.h> + +class Tempo : public Vamp::Plugin +{ +public: + Tempo(float inputSampleRate); + virtual ~Tempo(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string) const; + void setParameter(std::string, float); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(float **inputBuffers, Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + fvec_t *m_ibuf; + cvec_t *m_fftgrain; + fvec_t *m_onset; + aubio_pvoc_t *m_pv; + aubio_pickpeak_t *m_peakpick; + aubio_onsetdetection_t *m_onsetdet; + aubio_onsetdetection_type m_onsettype; + aubio_beattracking_t *m_beattracking; + fvec_t *m_dfframe; + fvec_t *m_btout; + uint_t m_winlen; + sint_t m_btstep; + sint_t m_btcounter; + float m_threshold; + float m_silence; + size_t m_stepSize; + size_t m_blockSize; + size_t m_channelCount; + Vamp::RealTime m_delay; + Vamp::RealTime m_lastBeat; +}; + + +#endif