Chris@103: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@103: Chris@103: /* Chris@103: Vamp feature extraction plugin using the MATCH audio alignment Chris@103: algorithm. Chris@103: Chris@103: Centre for Digital Music, Queen Mary, University of London. Chris@236: Copyright (c) 2007-2020 Simon Dixon, Chris Cannam, and Queen Mary Chris@230: University of London, Copyright (c) 2014-2015 Tido GmbH. Chris@103: Chris@103: This program is free software; you can redistribute it and/or Chris@103: modify it under the terms of the GNU General Public License as Chris@103: published by the Free Software Foundation; either version 2 of the Chris@103: License, or (at your option) any later version. See the file Chris@103: COPYING included with this distribution for more information. Chris@103: */ Chris@103: Chris@103: #include "FeatureConditioner.h" Chris@103: Chris@103: #include Chris@130: #include Chris@103: Chris@103: using namespace std; Chris@103: Chris@140: //#define DEBUG_FEATURE_CONDITIONER 1 Chris@140: Chris@140: FeatureConditioner::FeatureConditioner(Parameters parameters) : Chris@140: m_params(parameters), Chris@140: m_ltAverage(0.0) Chris@140: { Chris@140: #ifdef DEBUG_FEATURE_CONDITIONER Chris@140: cerr << "*** FeatureConditioner: norm = " << parameters.norm Chris@140: << ", order = " << parameters.order Chris@140: << ", silenceThreshold = " << parameters.silenceThreshold Chris@140: << ", decay = " << parameters.decay << endl; Chris@140: #endif Chris@140: } Chris@140: Chris@185: feature_t Chris@185: FeatureConditioner::process(const feature_t &feature) Chris@103: { Chris@103: if (m_prev.empty()) { Chris@103: m_prev.resize(feature.size(), 0.0); Chris@103: } Chris@103: if (m_prev.size() != feature.size()) { Chris@103: cerr << "ERROR: FeatureConditioner::process: feature size " Chris@103: << feature.size() << " differs from previous feature size " Chris@103: << m_prev.size() << endl; Chris@103: return feature; Chris@103: } Chris@103: Chris@180: int size = static_cast(feature.size()); Chris@103: Chris@185: feature_t out(size, 0.0); Chris@103: Chris@103: double totalEnergy = 0; Chris@116: Chris@116: switch (m_params.order) { Chris@116: Chris@116: case OutputRectifiedDerivative: Chris@103: for (int i = 0; i < size; i++) { Chris@103: totalEnergy += feature[i]; Chris@103: if (feature[i] > m_prev[i]) { Chris@103: out[i] = feature[i] - m_prev[i]; Chris@103: } else { Chris@103: out[i] = 0; Chris@103: } Chris@103: } Chris@116: break; Chris@116: Chris@116: case OutputDerivative: Chris@103: for (int i = 0; i < size; i++) { Chris@116: totalEnergy += feature[i]; Chris@130: out[i] = fabs(feature[i] - m_prev[i]); Chris@116: } Chris@116: break; Chris@116: Chris@116: case OutputFeatures: Chris@116: for (int i = 0; i < size; i++) { Chris@116: totalEnergy += feature[i]; Chris@103: out[i] = feature[i]; Chris@103: } Chris@116: break; Chris@103: } Chris@103: Chris@139: if (m_ltAverage == 0.0) { Chris@103: m_ltAverage = totalEnergy; Chris@103: } else { Chris@103: double decay = m_params.decay; Chris@103: m_ltAverage = m_ltAverage * decay + totalEnergy * (1.0 - decay); Chris@103: } Chris@103: Chris@103: if (totalEnergy <= m_params.silenceThreshold) { Chris@103: for (int i = 0; i < size; i++) { Chris@103: out[i] = 0; Chris@103: } Chris@103: } else if (m_params.norm == NormaliseToSum1) { Chris@103: for (int i = 0; i < size; i++) { Chris@185: out[i] = featurebin_t(out[i] / totalEnergy); Chris@103: } Chris@103: } else if (m_params.norm == NormaliseToLTAverage) { Chris@103: for (int i = 0; i < size; i++) { Chris@185: out[i] = featurebin_t(out[i] / m_ltAverage); Chris@103: } Chris@103: } Chris@103: Chris@103: m_prev = feature; Chris@103: return out; Chris@103: } Chris@103: