Chris@26
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@26
|
2
|
Chris@26
|
3 /*
|
Chris@26
|
4 Vamp feature extraction plugin using the MATCH audio alignment
|
Chris@26
|
5 algorithm.
|
Chris@26
|
6
|
Chris@26
|
7 Centre for Digital Music, Queen Mary, University of London.
|
Chris@26
|
8 This file copyright 2007 Simon Dixon, Chris Cannam and QMUL.
|
Chris@26
|
9
|
Chris@26
|
10 This program is free software; you can redistribute it and/or
|
Chris@26
|
11 modify it under the terms of the GNU General Public License as
|
Chris@26
|
12 published by the Free Software Foundation; either version 2 of the
|
Chris@26
|
13 License, or (at your option) any later version. See the file
|
Chris@26
|
14 COPYING included with this distribution for more information.
|
Chris@26
|
15 */
|
Chris@26
|
16
|
Chris@26
|
17 #include "DistanceMetric.h"
|
Chris@26
|
18
|
Chris@26
|
19 #include <cassert>
|
Chris@26
|
20 #include <cmath>
|
Chris@133
|
21 #include <iostream>
|
Chris@26
|
22
|
Chris@133
|
23 using namespace std;
|
Chris@26
|
24
|
Chris@140
|
25 //#define DEBUG_DISTANCE_METRIC 1
|
Chris@140
|
26
|
Chris@143
|
27 DistanceMetric::DistanceMetric(Parameters params) :
|
Chris@143
|
28 m_params(params)
|
Chris@140
|
29 {
|
Chris@140
|
30 #ifdef DEBUG_DISTANCE_METRIC
|
Chris@143
|
31 cerr << "*** DistanceMetric: norm = " << m_params.norm
|
Chris@143
|
32 << endl;
|
Chris@140
|
33 #endif
|
Chris@140
|
34 }
|
Chris@140
|
35
|
Chris@26
|
36 double
|
Chris@26
|
37 DistanceMetric::calcDistance(const vector<double> &f1,
|
Chris@26
|
38 const vector<double> &f2)
|
Chris@26
|
39 {
|
Chris@26
|
40 double d = 0;
|
Chris@143
|
41 double sum1 = 0;
|
Chris@143
|
42 double sum2 = 0;
|
Chris@26
|
43 double sum = 0;
|
Chris@26
|
44
|
Chris@26
|
45 int featureSize = f1.size();
|
Chris@26
|
46 assert(int(f2.size()) == featureSize);
|
Chris@26
|
47
|
Chris@26
|
48 for (int i = 0; i < featureSize; i++) {
|
Chris@26
|
49 d += fabs(f1[i] - f2[i]);
|
Chris@143
|
50 sum1 += fabs(f1[i]);
|
Chris@143
|
51 sum2 += fabs(f2[i]);
|
Chris@26
|
52 }
|
Chris@26
|
53
|
Chris@143
|
54 sum = sum1 + sum2;
|
Chris@143
|
55
|
Chris@143
|
56 if (sum == 0) {
|
Chris@26
|
57 return 0;
|
Chris@143
|
58 }
|
Chris@26
|
59
|
Chris@143
|
60 double distance = 0;
|
Chris@26
|
61
|
Chris@143
|
62 if (m_params.norm == NormaliseDistanceToSum) {
|
Chris@143
|
63
|
Chris@143
|
64 distance = d / sum; // 0 <= d/sum <= 2
|
Chris@143
|
65
|
Chris@143
|
66 } else if (m_params.norm == NormaliseDistanceToLogSum) {
|
Chris@143
|
67
|
Chris@143
|
68 // note if this were to be restored, it would have to use
|
Chris@143
|
69 // totalEnergies vector instead of f1[freqMapSize] which used to
|
Chris@143
|
70 // store the total energy:
|
Chris@143
|
71 // double weight = (5 + Math.log(f1[freqMapSize] + f2[freqMapSize]))/10.0;
|
Chris@143
|
72
|
Chris@143
|
73 double weight = (8 + log(sum)) / 10.0;
|
Chris@133
|
74
|
Chris@143
|
75 if (weight < 0) weight = 0;
|
Chris@143
|
76 else if (weight > 1) weight = 1;
|
Chris@26
|
77
|
Chris@143
|
78 distance = d / sum * weight;
|
Chris@143
|
79
|
Chris@143
|
80 } else {
|
Chris@143
|
81
|
Chris@143
|
82 distance = d;
|
Chris@143
|
83 }
|
Chris@143
|
84
|
Chris@143
|
85 return distance;
|
Chris@26
|
86 }
|
Chris@26
|
87
|