annotate src/FeatureExtractor.cpp @ 166:d23dad16d6f9 refactors

Simplify freq handling
author Chris Cannam
date Thu, 05 Feb 2015 11:53:23 +0000
parents cf1282d1f940
children 001db4c32eb0 ef3c4b451c57
rev   line source
Chris@37 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@37 2
Chris@37 3 /*
Chris@37 4 Vamp feature extraction plugin using the MATCH audio alignment
Chris@37 5 algorithm.
Chris@37 6
Chris@37 7 Centre for Digital Music, Queen Mary, University of London.
Chris@37 8 This file copyright 2007 Simon Dixon, Chris Cannam and QMUL.
Chris@37 9
Chris@37 10 This program is free software; you can redistribute it and/or
Chris@37 11 modify it under the terms of the GNU General Public License as
Chris@37 12 published by the Free Software Foundation; either version 2 of the
Chris@37 13 License, or (at your option) any later version. See the file
Chris@37 14 COPYING included with this distribution for more information.
Chris@37 15 */
Chris@37 16
Chris@37 17 #include "FeatureExtractor.h"
Chris@37 18
Chris@37 19 #include <iostream>
Chris@37 20
Chris@37 21 #include <cstdlib>
Chris@37 22 #include <cassert>
Chris@37 23 #include <cmath>
Chris@37 24
Chris@37 25 using namespace std;
Chris@37 26
Chris@166 27 #define DEBUG_FEATURE_EXTRACTOR 1
Chris@140 28
Chris@37 29 FeatureExtractor::FeatureExtractor(Parameters parameters) :
Chris@103 30 m_params(parameters)
Chris@37 31 {
Chris@74 32 m_featureSize = getFeatureSizeFor(parameters);
Chris@37 33 makeFreqMap();
Chris@140 34
Chris@140 35 #ifdef DEBUG_FEATURE_EXTRACTOR
Chris@140 36 cerr << "*** FeatureExtractor: sampleRate = " << parameters.sampleRate
Chris@140 37 << ", useChromaFrequencyMap = " << parameters.useChromaFrequencyMap
Chris@140 38 << ", fftSize = " << parameters.fftSize << endl;
Chris@140 39 #endif
Chris@37 40 }
Chris@37 41
Chris@74 42 int
Chris@74 43 FeatureExtractor::getFeatureSizeFor(Parameters parameters)
Chris@74 44 {
Chris@74 45 if (parameters.useChromaFrequencyMap) {
Chris@74 46 return 13;
Chris@74 47 } else {
Chris@74 48 return 84;
Chris@74 49 }
Chris@74 50 }
Chris@74 51
Chris@37 52 void
Chris@37 53 FeatureExtractor::makeFreqMap()
Chris@37 54 {
Chris@37 55 m_freqMap = vector<int>(m_params.fftSize / 2 + 1, 0);
Chris@37 56
Chris@37 57 if (m_params.useChromaFrequencyMap) {
Chris@140 58 #ifdef DEBUG_FEATURE_EXTRACTOR
Chris@37 59 cerr << "makeFreqMap: calling makeChromaFrequencyMap" << endl;
Chris@37 60 #endif
Chris@37 61 makeChromaFrequencyMap();
Chris@37 62 } else {
Chris@140 63 #ifdef DEBUG_FEATURE_EXTRACTOR
Chris@37 64 cerr << "makeFreqMap: calling makeStandardFrequencyMap" << endl;
Chris@37 65 #endif
Chris@37 66 makeStandardFrequencyMap();
Chris@37 67 }
Chris@37 68 }
Chris@37 69
Chris@37 70 void
Chris@37 71 FeatureExtractor::makeStandardFrequencyMap()
Chris@37 72 {
Chris@159 73 double refFreq = m_params.referenceFrequency;
Chris@37 74 double binWidth = m_params.sampleRate / m_params.fftSize;
Chris@37 75 int crossoverBin = (int)(2 / (pow(2, 1/12.0) - 1));
Chris@159 76 int crossoverMidi = lrint(log(crossoverBin * binWidth / refFreq)/
Chris@37 77 log(2.0) * 12 + 69);
Chris@163 78
Chris@166 79 #ifdef DEBUG_FEATURE_EXTRACTOR
Chris@163 80 cerr << "FeatureExtractor::makeStandardFrequencyMap: refFreq = " << refFreq << endl;
Chris@166 81 #endif
Chris@37 82
Chris@37 83 int i = 0;
Chris@37 84 while (i <= crossoverBin) {
Chris@37 85 m_freqMap[i] = i;
Chris@37 86 ++i;
Chris@37 87 }
Chris@37 88
Chris@37 89 while (i <= m_params.fftSize/2) {
Chris@159 90 double midi = log(i * binWidth / refFreq) / log(2.0) * 12 + 69;
Chris@37 91 if (midi > 127) midi = 127;
Chris@40 92 int target = crossoverBin + lrint(midi) - crossoverMidi;
Chris@40 93 if (target >= m_featureSize) target = m_featureSize - 1;
Chris@40 94 m_freqMap[i++] = target;
Chris@37 95 }
Chris@166 96
Chris@166 97 #ifdef DEBUG_FEATURE_EXTRACTOR
Chris@166 98 cerr << "FeatureExtractor: crossover bin is " << crossoverBin << " for midi "
Chris@166 99 << crossoverMidi << endl;
Chris@166 100 #endif
Chris@37 101 }
Chris@37 102
Chris@37 103 void
Chris@37 104 FeatureExtractor::makeChromaFrequencyMap()
Chris@37 105 {
Chris@159 106 double refFreq = m_params.referenceFrequency;
Chris@37 107 double binWidth = m_params.sampleRate / m_params.fftSize;
Chris@37 108 int crossoverBin = (int)(1 / (pow(2, 1/12.0) - 1));
Chris@37 109 int i = 0;
Chris@37 110 while (i <= crossoverBin) {
Chris@37 111 m_freqMap[i++] = 0;
Chris@37 112 }
Chris@37 113 while (i <= m_params.fftSize/2) {
Chris@159 114 double midi = log(i * binWidth / refFreq) / log(2.0) * 12 + 69;
Chris@37 115 m_freqMap[i++] = (lrint(midi)) % 12 + 1;
Chris@37 116 }
Chris@37 117 }
Chris@37 118
Chris@37 119 vector<double>
Chris@37 120 FeatureExtractor::process(const vector<double> &real, const vector<double> &imag)
Chris@37 121 {
Chris@37 122 vector<double> frame(m_featureSize, 0.0);
Chris@37 123
Chris@37 124 for (int i = 0; i <= m_params.fftSize/2; i++) {
Chris@37 125 double mag = real[i] * real[i] + imag[i] * imag[i];
Chris@37 126 frame[m_freqMap[i]] += mag;
Chris@37 127 }
Chris@37 128
Chris@103 129 return frame;
Chris@74 130 }
Chris@74 131
Chris@74 132 vector<double>
Chris@74 133 FeatureExtractor::process(const float *cframe)
Chris@74 134 {
Chris@74 135 vector<double> frame(m_featureSize, 0.0);
Chris@74 136
Chris@74 137 for (int i = 0; i <= m_params.fftSize/2; i++) {
Chris@74 138 double mag = cframe[i*2] * cframe[i*2] + cframe[i*2+1] * cframe[i*2+1];
Chris@74 139 frame[m_freqMap[i]] += mag;
Chris@74 140 }
Chris@74 141
Chris@103 142 return frame;
Chris@74 143 }
Chris@74 144