Mercurial > hg > tipic
changeset 27:cb86b8b7ed90
Add output bin names; begin handling tuning frequency
author | Chris Cannam |
---|---|
date | Wed, 30 Sep 2015 10:26:24 +0100 |
parents | 3d1c5cabadcc |
children | 7b618e3f9a8b |
files | src/PitchFilterbank.cpp src/PitchFilterbank.h src/TipicVampPlugin.cpp |
diffstat | 3 files changed, 56 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/src/PitchFilterbank.cpp Tue Sep 29 17:14:05 2015 +0100 +++ b/src/PitchFilterbank.cpp Wed Sep 30 10:26:24 2015 +0100 @@ -13,6 +13,8 @@ #include <stdexcept> #include <iostream> +#include <cmath> + using namespace std; static const int HIGHEST_FILTER_INDEX_AT_882 = 38; // MIDI pitch 59 @@ -23,11 +25,23 @@ class PitchFilterbank::D { public: - D(int sampleRate, float tuningFrequency) : + D(int sampleRate, double tuningFrequency) : m_nfilters(HIGHEST_FILTER_INDEX + 1), m_sampleRate(sampleRate), m_tuningFrequency(tuningFrequency) { + // To handle a non-440 tuning frequency, we resample the input + // by this tuning ratio and then adjust the output block + // timings accordingly. Ratio is calculated on the basis that + // for tuning freq >440 we want to lower the pitch of the + // input audio by slowing it down, therefore we want to + // pretend that it came in at a lower sample rate than it + // really did, and for >440 the opposite applies. The + // effective input sample rate is the rate at which we pretend + // the audio was supplied. + m_tuningRatio = 440.0 / m_tuningFrequency; + m_effectiveInputSampleRate = int(round(m_sampleRate * m_tuningRatio)); + //!!! todo: tuning frequency adjustment // * resample input by a small amount // * adjust output block timings by a small amount @@ -39,9 +53,9 @@ // here & so need to adapt magnitudes in compensation to match // original - m_resamplers[882] = new Resampler(sampleRate, 882); - m_resamplers[4410] = new Resampler(sampleRate, 4410); - m_resamplers[22050] = new Resampler(sampleRate, 22050); + m_resamplers[882] = new Resampler(m_effectiveInputSampleRate, 882); + m_resamplers[4410] = new Resampler(m_effectiveInputSampleRate, 4410); + m_resamplers[22050] = new Resampler(m_effectiveInputSampleRate, 22050); for (int i = 0; i < m_nfilters; ++i) { int ix = i + 20; @@ -62,7 +76,7 @@ } int getSampleRate() const { return m_sampleRate; } - float getTuningFrequency() const { return m_tuningFrequency; } + double getTuningFrequency() const { return m_tuningFrequency; } RealBlock process(const RealSequence &in) { @@ -206,7 +220,9 @@ private: int m_nfilters; int m_sampleRate; - float m_tuningFrequency; + int m_effectiveInputSampleRate; + double m_tuningFrequency; + double m_tuningRatio; // This vector is initialised with 88 filter instances. // m_filters[n] (for n from 0 to 87) is for MIDI pitch 21+n, so we @@ -249,7 +265,7 @@ } }; -PitchFilterbank::PitchFilterbank(int sampleRate, float tuningFrequency) : +PitchFilterbank::PitchFilterbank(int sampleRate, double tuningFrequency) : m_d(new D(sampleRate, tuningFrequency)) { } @@ -263,7 +279,7 @@ PitchFilterbank::reset() { int rate = m_d->getSampleRate(); - float freq = m_d->getTuningFrequency(); + double freq = m_d->getTuningFrequency(); delete m_d; m_d = new D(rate, freq); } @@ -280,3 +296,11 @@ return m_d->getRemainingOutput(); } +void +PitchFilterbank::getPitchRange(int &minMidiPitch, int &maxMidiPitch) +{ + minMidiPitch = 21; + maxMidiPitch = 108; +} + +
--- a/src/PitchFilterbank.h Tue Sep 29 17:14:05 2015 +0100 +++ b/src/PitchFilterbank.h Wed Sep 30 10:26:24 2015 +0100 @@ -8,7 +8,7 @@ class PitchFilterbank { public: - PitchFilterbank(int sampleRate, float tuningFrequency); + PitchFilterbank(int sampleRate, double tuningFrequency); ~PitchFilterbank(); void reset(); @@ -17,6 +17,8 @@ RealBlock getRemainingOutput(); + static void getPitchRange(int &minMidiPitch, int &maxMidiPitch); + private: class D; D *m_d;
--- a/src/TipicVampPlugin.cpp Tue Sep 29 17:14:05 2015 +0100 +++ b/src/TipicVampPlugin.cpp Wed Sep 30 10:26:24 2015 +0100 @@ -9,6 +9,7 @@ #include <bqvec/VectorOps.h> #include <iostream> +#include <sstream> using namespace std; @@ -170,6 +171,18 @@ { } +static vector<string> noteNames + { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; + +static std::string noteName(int i) +{ + string name = noteNames[i % 12]; + int oct = i / 12 - 1; + ostringstream sstr; + sstr << i << " " << name << oct << ends; + return sstr.str(); +} + Tipic::OutputList Tipic::getOutputDescriptors() const { @@ -181,7 +194,13 @@ d.description = ""; d.unit = ""; d.hasFixedBinCount = true; - d.binCount = 88; + int min = 0, max = 0; + PitchFilterbank::getPitchRange(min, max); + d.binCount = max - min + 1; + d.binNames.clear(); + for (int p = min; p <= max; ++p) { + d.binNames.push_back(noteName(p)); + } d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::FixedSampleRate; @@ -196,6 +215,7 @@ d.unit = ""; d.hasFixedBinCount = true; d.binCount = 12; + d.binNames = noteNames; d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::FixedSampleRate; @@ -207,28 +227,12 @@ d.identifier = "clp"; d.name = "Chroma Log Pitch Features"; d.description = ""; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 12; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 22050 / 2205; //!!! get block size & hop from filterbank - d.hasDuration = false; m_clpOutputNo = list.size(); list.push_back(d); d.identifier = "crp"; d.name = "Chroma DCT-Reduced Log Pitch Features"; d.description = ""; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 12; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 22050 / 2205; //!!! get block size & hop from filterbank - d.hasDuration = false; m_crpOutputNo = list.size(); list.push_back(d);