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