Chris@37: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@37: Chris@37: /* Chris@37: Vamp feature extraction plugin using the MATCH audio alignment Chris@37: algorithm. Chris@37: Chris@37: Centre for Digital Music, Queen Mary, University of London. Chris@37: This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. Chris@37: Chris@37: This program is free software; you can redistribute it and/or Chris@37: modify it under the terms of the GNU General Public License as Chris@37: published by the Free Software Foundation; either version 2 of the Chris@37: License, or (at your option) any later version. See the file Chris@37: COPYING included with this distribution for more information. Chris@37: */ Chris@37: Chris@37: #include "FeatureExtractor.h" Chris@37: Chris@37: #include Chris@37: Chris@37: #include Chris@37: #include Chris@37: #include Chris@37: Chris@37: using namespace std; Chris@37: Chris@140: //#define DEBUG_FEATURE_EXTRACTOR 1 Chris@140: Chris@37: FeatureExtractor::FeatureExtractor(Parameters parameters) : Chris@103: m_params(parameters) Chris@37: { Chris@74: m_featureSize = getFeatureSizeFor(parameters); Chris@37: makeFreqMap(); Chris@140: Chris@140: #ifdef DEBUG_FEATURE_EXTRACTOR Chris@140: cerr << "*** FeatureExtractor: sampleRate = " << parameters.sampleRate Chris@140: << ", useChromaFrequencyMap = " << parameters.useChromaFrequencyMap Chris@140: << ", fftSize = " << parameters.fftSize << endl; Chris@140: #endif Chris@37: } Chris@37: Chris@74: int Chris@74: FeatureExtractor::getFeatureSizeFor(Parameters parameters) Chris@74: { Chris@74: if (parameters.useChromaFrequencyMap) { Chris@74: return 13; Chris@74: } else { Chris@74: return 84; Chris@74: } Chris@74: } Chris@74: Chris@37: void Chris@37: FeatureExtractor::makeFreqMap() Chris@37: { Chris@37: m_freqMap = vector(m_params.fftSize / 2 + 1, 0); Chris@37: Chris@37: if (m_params.useChromaFrequencyMap) { Chris@140: #ifdef DEBUG_FEATURE_EXTRACTOR Chris@37: cerr << "makeFreqMap: calling makeChromaFrequencyMap" << endl; Chris@37: #endif Chris@37: makeChromaFrequencyMap(); Chris@37: } else { Chris@140: #ifdef DEBUG_FEATURE_EXTRACTOR Chris@37: cerr << "makeFreqMap: calling makeStandardFrequencyMap" << endl; Chris@37: #endif Chris@37: makeStandardFrequencyMap(); Chris@37: } Chris@37: } Chris@37: Chris@37: void Chris@37: FeatureExtractor::makeStandardFrequencyMap() Chris@37: { Chris@37: double binWidth = m_params.sampleRate / m_params.fftSize; Chris@37: int crossoverBin = (int)(2 / (pow(2, 1/12.0) - 1)); Chris@37: int crossoverMidi = lrint(log(crossoverBin*binWidth/440.0)/ Chris@37: log(2.0) * 12 + 69); Chris@37: Chris@37: // freq = 440 * Math.pow(2, (midi-69)/12.0) / binWidth; Chris@37: Chris@37: int i = 0; Chris@37: while (i <= crossoverBin) { Chris@37: m_freqMap[i] = i; Chris@37: ++i; Chris@37: } Chris@37: Chris@37: while (i <= m_params.fftSize/2) { Chris@37: double midi = log(i*binWidth/440.0) / log(2.0) * 12 + 69; Chris@37: if (midi > 127) midi = 127; Chris@40: int target = crossoverBin + lrint(midi) - crossoverMidi; Chris@40: if (target >= m_featureSize) target = m_featureSize - 1; Chris@40: m_freqMap[i++] = target; Chris@37: } Chris@37: } Chris@37: Chris@37: void Chris@37: FeatureExtractor::makeChromaFrequencyMap() Chris@37: { Chris@37: double binWidth = m_params.sampleRate / m_params.fftSize; Chris@37: int crossoverBin = (int)(1 / (pow(2, 1/12.0) - 1)); Chris@37: int i = 0; Chris@37: while (i <= crossoverBin) { Chris@37: m_freqMap[i++] = 0; Chris@37: } Chris@37: while (i <= m_params.fftSize/2) { Chris@37: double midi = log(i*binWidth/440.0) / log(2.0) * 12 + 69; Chris@37: m_freqMap[i++] = (lrint(midi)) % 12 + 1; Chris@37: } Chris@37: } Chris@37: Chris@37: vector Chris@37: FeatureExtractor::process(const vector &real, const vector &imag) Chris@37: { Chris@37: vector frame(m_featureSize, 0.0); Chris@37: Chris@37: for (int i = 0; i <= m_params.fftSize/2; i++) { Chris@37: double mag = real[i] * real[i] + imag[i] * imag[i]; Chris@37: frame[m_freqMap[i]] += mag; Chris@37: } Chris@37: Chris@103: return frame; Chris@74: } Chris@74: Chris@74: vector Chris@74: FeatureExtractor::process(const float *cframe) Chris@74: { Chris@74: vector frame(m_featureSize, 0.0); Chris@74: Chris@74: for (int i = 0; i <= m_params.fftSize/2; i++) { Chris@74: double mag = cframe[i*2] * cframe[i*2] + cframe[i*2+1] * cframe[i*2+1]; Chris@74: frame[m_freqMap[i]] += mag; Chris@74: } Chris@74: Chris@103: return frame; Chris@74: } Chris@74: