Mercurial > hg > tipic
view src/FeatureDownsample.cpp @ 60:1ea2aed23d4a tip
Fix version
author | Chris Cannam |
---|---|
date | Thu, 13 Feb 2020 13:37:36 +0000 |
parents | 00b6ae41efbe |
children |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Tipic Centre for Digital Music, Queen Mary, University of London. 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 "FeatureDownsample.h" #include "dsp/signalconditioning/Filter.h" #include "base/Window.h" #include "maths/MathUtilities.h" #include <stdexcept> using namespace std; FeatureDownsample::FeatureDownsample(Parameters params) : m_params(params) { if (params.downsampleFactor < 2 || params.windowLength < 2) { throw invalid_argument ("Expected downsampleFactor and windowLength each to be at least 2"); } // Our windows are periodic rather than symmetric, but we want a // symmetric window here Window<double> w(HanningWindow, params.windowLength + 1); vector<double> wdat(w.getWindowData());; vector<double> wd(wdat.begin()+1, wdat.end()); double divisor = 0.0; for (auto x: wd) divisor += x; for (auto &x: wd) x /= divisor; // FIR filter for (int i = 0; i < m_params.featureSize; ++i) { m_filters.push_back(new Filter({ {}, wd })); } m_toNext = 1; m_toDrop = m_params.windowLength / 2; m_inCount = 0; m_outCount = 0; } FeatureDownsample::~FeatureDownsample() { for (auto &f: m_filters) delete f; } void FeatureDownsample::reset() { for (auto &f: m_filters) f->reset(); m_toNext = 1; m_toDrop = m_params.windowLength / 2; m_inCount = 0; m_outCount = 0; } RealBlock FeatureDownsample::process(const RealBlock &in) { RealBlock out; for (const auto &col: in) { RealColumn outcol; if (m_toDrop > 0) { --m_toDrop; } else { --m_toNext; } for (int i = 0; i < m_params.featureSize; ++i) { double val = 0.0; m_filters[i]->process(&col[i], &val, 1); if (m_toNext == 0) { outcol.push_back(val); } } if (m_toNext == 0) { out.push_back(MathUtilities::normaliseLp (outcol, m_params.normP, m_params.normThresh)); m_toNext = m_params.downsampleFactor; ++m_outCount; } ++m_inCount; } return out; } RealBlock FeatureDownsample::getRemainingOutput() { RealBlock pad(m_params.windowLength, RealColumn(m_params.featureSize, 0.0)); RealBlock tail = process(pad); int expected = m_inCount / m_params.downsampleFactor; RealBlock out; for (int i = 0; m_outCount < expected && i < int(tail.size()); ++i, ++m_outCount) { out.push_back(MathUtilities::normaliseLp (tail[i], m_params.normP, m_params.normThresh)); } return out; }