1 /*************************************************************************
2 
3   Copyright 2011-2015 Ibrahim Sha'ath
4 
5   This file is part of LibKeyFinder.
6 
7   LibKeyFinder is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11 
12   LibKeyFinder is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16 
17   You should have received a copy of the GNU General Public License
18   along with LibKeyFinder.  If not, see <http://www.gnu.org/licenses/>.
19 
20 *************************************************************************/
21 
22 #include "keyclassifier.h"
23 
24 namespace KeyFinder {
25 
KeyClassifier(const std::vector<double> & majorProfile,const std::vector<double> & minorProfile)26   KeyClassifier::KeyClassifier(const std::vector<double>& majorProfile, const std::vector<double>& minorProfile) {
27 
28     if (majorProfile.size() != BANDS) {
29       throw Exception("Tone profile must have 72 elements");
30     }
31 
32     if (minorProfile.size() != BANDS) {
33       throw Exception("Tone profile must have 72 elements");
34     }
35 
36     major   = new ToneProfile(majorProfile);
37     minor   = new ToneProfile(minorProfile);
38     silence = new ToneProfile(std::vector<double>(BANDS, 0.0));
39   }
40 
~KeyClassifier()41   KeyClassifier::~KeyClassifier() {
42     delete major;
43     delete minor;
44     delete silence;
45   }
46 
classify(const std::vector<double> & chromaVector)47   key_t KeyClassifier::classify(const std::vector<double>& chromaVector) {
48     std::vector<double> scores(24);
49     double bestScore = 0.0;
50     for (unsigned int i = 0; i < SEMITONES; i++) {
51       double score;
52       score = major->cosineSimilarity(chromaVector, i); // major
53       scores[i*2] = score;
54       score = minor->cosineSimilarity(chromaVector, i); // minor
55       scores[(i*2)+1] = score;
56     }
57     bestScore = silence->cosineSimilarity(chromaVector, 0);
58     // find best match, defaulting to silence
59     key_t bestMatch = SILENCE;
60     for (unsigned int i = 0; i < 24; i++) {
61       if (scores[i] > bestScore) {
62         bestScore = scores[i];
63         bestMatch = (key_t)i;
64       }
65     }
66     return bestMatch;
67   }
68 
69 }
70