Mercurial > hg > tipic
changeset 12:d9f993e094df
Compensate for filter & resampler delay
author | Chris Cannam |
---|---|
date | Fri, 14 Aug 2015 18:37:24 +0100 |
parents | 7518c113bd03 |
children | 2e83471044c0 |
files | src/PitchFilterbank.cpp |
diffstat | 1 files changed, 50 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/PitchFilterbank.cpp Fri Aug 14 18:13:04 2015 +0100 +++ b/src/PitchFilterbank.cpp Fri Aug 14 18:37:24 2015 +0100 @@ -37,6 +37,7 @@ vector<double> a(filter_a[ix], filter_a[ix] + coeffs); vector<double> b(filter_b[ix], filter_b[ix] + coeffs); m_filters.push_back(new Filter({ a, b })); + m_toCompensate.push_back(totalDelay(i)); } m_filtered.resize(m_nfilters); @@ -61,8 +62,6 @@ RealBlock process(const RealSequence &in) { - cerr << "process" << endl; - for (auto r: m_resamplers) { m_resampled[r.first] = r.second->process(in.data(), in.size()); } @@ -75,6 +74,26 @@ pushFiltered(i, m_resampled[rate]); } + return energiesFromFiltered(false); + } + + RealBlock getRemainingOutput() { + + for (auto r: m_resamplers) { + RealSequence in(r.second->getLatency(), 0.0); + m_resampled[r.first] = r.second->process(in.data(), in.size()); + } + + for (int i = 0; i < m_nfilters; ++i) { + int rate = filterRate(i); + pushFiltered(i, m_resampled[rate]); + } + + return energiesFromFiltered(true); + } + + RealBlock energiesFromFiltered(bool drain) { + //!!! todo make this known through api. these values are at 22050Hz int windowSize = 4410; @@ -89,8 +108,11 @@ //!!! fs=882 (it's 176.4) int n = windowSize / factor; int hop = n / 2; - - while (m_filtered[i].size() >= unsigned(n)) { + + unsigned int minReq = n; + if (drain) minReq = hop; + + while (m_filtered[i].size() >= minReq) { double energy = calculateEnergy(m_filtered[i], n, factor); m_energies[i].push_back(energy); m_filtered[i] = RealSequence(m_filtered[i].begin() + hop, @@ -107,7 +129,6 @@ } RealBlock out(minCols); - cerr << "process: minCols = " << minCols << endl; for (int j = 0; j < minCols; ++j) { for (int i = 0; i < m_nfilters; ++i) { out[j].push_back(m_energies[i][0]); @@ -117,21 +138,34 @@ return out; } - - RealBlock getRemainingOutput() { - //!!! for now! but we do have some buffered - return RealBlock(); - } void pushFiltered(int i, const RealSequence &resampled) { + int n = resampled.size(); RealSequence filtered(n, 0.0); m_filters[i]->process(resampled.data(), filtered.data(), n); - m_filtered[i].insert(m_filtered[i].end(), filtered.begin(), filtered.end()); + + int pushStart = 0, pushCount = n; + + if (m_toCompensate[i] > 0) { + pushCount = max(pushCount - m_toCompensate[i], 0); + int compensating = n - pushCount; + pushStart += compensating; + m_toCompensate[i] -= compensating; + if (m_toCompensate[i] < 0) { + throw logic_error("Compensated for more latency than exists"); + } + } + + m_filtered[i].insert(m_filtered[i].end(), + filtered.begin() + pushStart, + filtered.begin() + pushStart + pushCount); } double calculateEnergy(const RealSequence &seq, int n, double factor) { double energy = 0.0; + int sz = seq.size(); + if (n > sz) n = sz; for (int i = 0; i < n; ++i) { energy += seq[i] * seq[i]; } @@ -151,6 +185,7 @@ map<int, Resampler *> m_resamplers; // rate -> resampler map<int, RealSequence> m_resampled; + vector<int> m_toCompensate; // latency remaining at start, per filter vector<RealSequence> m_filtered; vector<deque<double>> m_energies; @@ -171,12 +206,14 @@ return 22050; } } + int resamplerDelay(int filterIndex) const { + return const_cast<D *>(this)->resamplerFor(filterIndex)->getLatency(); + } int filterDelay(int filterIndex) const { return filter_delay[20 + filterIndex]; } int totalDelay(int filterIndex) const { - return filterDelay(filterIndex) + - const_cast<D *>(this)->resamplerFor(filterIndex)->getLatency(); + return resamplerDelay(filterIndex) + filterDelay(filterIndex); } };