ChordCorrelator.hxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2006 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef ChordCorrelator_hxx
00023 #define ChordCorrelator_hxx
00024 #include <list>
00025 #include <vector>
00026 #include <cmath>
00027 #include <sstream>
00028 
00029 namespace Simac
00030 {
00031 
00041 class ChordCorrelator
00042 {
00043 public:
00044         static std::string PitchNames(unsigned index)
00045         {
00046                 static const char * PitchNames[] = {"G","G#","A","A#","B","C","C#","D","D#","E","F","F#"};
00047                 return PitchNames[index];
00048         }
00049         enum Pitch {G,Ab,A,Bb,B,C,Db,D,Eb,E,F,Gb};
00050         typedef unsigned ChordMode;
00051         typedef std::vector<double> PCP;
00052         typedef std::vector<double> ChordCorrelation;
00053 
00054         struct ChordModePatterns
00055         {
00056                 double pattern[12];
00057                 const char * name;
00058                 unsigned nRoots;
00059         };
00060         
00061         static ChordModePatterns * chordModePatterns()
00062         {
00063                 static ChordModePatterns patterns[] =
00064                 {
00065                         {{1,1,1,1,1,1,1,1,1,1,1,1}, "None",        1},
00066                         {{1,0,0,0,1,0,0,1,0,0,0,0}, "Major",      12},
00067                         {{1,0,0,1,0,0,0,1,0,0,0,0}, "Minor",      12},
00068                         {{1,0,0,0,1,0,0,1,0,0,0,1}, "Major7",     12}, // Cmaj7
00069                         {{1,0,0,0,1,0,0,1,0,0,1,0}, "Dominant7",  12}, // C7
00070                         {{1,0,0,1,0,0,0,1,0,0,0,1}, "MinorMajor7",12}, // Cm/maj7
00071                         {{1,0,0,1,0,0,0,1,0,0,1,0}, "Minor7",     12}, // Cm7
00072 //                      {{1,0,1,0,0,0,0,1,0,0,0,0}, "Suspended2", 12}, // Csus2
00073 //                      {{1,0,0,0,0,1,0,1,0,0,0,0}, "Suspended4", 12}, // Csus4
00074 //                      {{1,0,0,0,1,0,0,1,0,1,0,0}, "Major6",     12}, // C6
00075 //                      {{1,0,0,1,0,0,0,1,0,1,0,0}, "Minor6",     12}, // Cm6
00076 //                      {{1,0,1,0,1,0,0,1,0,1,0,0}, "6/9",        12}, // C6/9
00077                         {{1,0,0,0,1,0,0,0,1,0,0,0}, "Augmented",   4}, // Caug
00078                         {{1,0,0,1,0,0,1,0,0,0,0,0}, "Diminished", 12}, // Cdim
00079                         {{1,0,0,1,0,0,1,0,0,0,1,0}, "Diminished7",12}, // Cdim7
00080 //                      {{1,0,0,0,0,0,0,1,0,0,0,0}, "Fifth",    12}, // C5
00081                         {{0,0,0,0,0,0,0,0,0,0,0,0}, 0, 0}
00082                 };
00083                 return patterns;
00084         }
00085 
00086         struct ChordPattern {
00087                 double pattern[12];
00088                 Pitch root;
00089                 ChordMode mode;
00090                 double normalization;
00091                 
00092         };
00093 public:
00094         ChordCorrelator(ChordModePatterns * modePatterns = chordModePatterns())
00095         {
00096                 for (unsigned mode=0; modePatterns[mode].name; mode++)
00097                 {
00098                         _chordModeNames.push_back(modePatterns[mode].name);
00099                         double * basePattern = modePatterns[mode].pattern;
00100                         double normalizationFactor = 0.0;
00101                         for (unsigned i = 0; i<12; i++) 
00102                                 normalizationFactor += basePattern[i];
00103 
00104                         for (unsigned root=0; root<modePatterns[mode].nRoots; root++)
00105                         {
00106                                 ChordPattern pattern;
00107                                 pattern.root = Pitch(root);
00108                                 pattern.mode = mode;
00109                                 pattern.normalization = normalizationFactor;
00110                                 for (unsigned i=root; i<12; i++)
00111                                         pattern.pattern[i] = basePattern[i-root];
00112                                 for (unsigned i=0; i<root; i++)
00113                                         pattern.pattern[i] = basePattern[12+i-root];
00114                                 _chordPatterns.push_back(pattern);
00115                         }
00116                 }
00117                 for (unsigned i=0; i<_chordPatterns.size(); i++)
00118                 {
00119                         std::vector<double> singleRow;
00120                         for (unsigned j=0; j<_chordPatterns.size(); j++)
00121                         {
00122                                 double chordPatternCorrelation = 0;
00123                                 for (unsigned k=0; k<12; k++)
00124                                 {
00125                                         chordPatternCorrelation += (_chordPatterns[i].pattern[k] * _chordPatterns[j].pattern[k]);
00126                                 }
00127                                 chordPatternCorrelation /= (_chordPatterns[i].normalization + _chordPatterns[j].normalization) / 2.0;
00128                                 singleRow.push_back(chordPatternCorrelation);
00129                                 //singleRow.push_back(1.0);
00130                         }
00131                         _chordPatternsSimilarity.push_back(singleRow);
00132                 }
00133                 _output.resize(_chordPatterns.size());
00134         }
00135         void DumpChordPatterns(std::ostream & os)
00136         {
00137                 for (unsigned pattern=0; pattern<_chordPatterns.size(); pattern++)
00138                 {
00139                         for (unsigned i=0; i<12; i++)
00140                                 os << _chordPatterns[pattern].pattern[i] << " ";
00141                         os << _chordPatterns[pattern].normalization << " ";
00142                         os << PitchNames(_chordPatterns[pattern].root) << " ";
00143                         os << _chordModeNames[_chordPatterns[pattern].mode] << "\n";
00144                 }
00145         }
00146         std::string root(unsigned chordIndex) const
00147         {
00148                 return PitchNames(_chordPatterns[chordIndex].root);
00149         }
00150         std::string mode(unsigned chordIndex) const
00151         {
00152                 return _chordModeNames[_chordPatterns[chordIndex].mode];
00153         }
00154         std::string chordRepresentation(unsigned chordIndex) const
00155         {
00156                 std::ostringstream os;
00157                 os << PitchNames(_chordPatterns[chordIndex].root) << "_";
00158                 os << _chordModeNames[_chordPatterns[chordIndex].mode];
00159                 return os.str();
00160         }
00161         std::vector< std::vector<double> > chordPatternsSimilarity() const
00162         {
00163                 return _chordPatternsSimilarity;
00164         }
00165         ~ChordCorrelator()
00166         {
00167         }
00168         void doIt(const PCP & pcp)
00169         {
00170                 for (unsigned int i=0; i<_chordPatterns.size(); i++)
00171                 {
00172                         _output[i]=0.0;
00173                         double * chordPattern = _chordPatterns[i].pattern;
00174                         for (unsigned pitch=0; pitch<12; pitch++)
00175                         {
00176                                 _output[i]+= chordPattern[pitch] * pcp[pitch];
00177                         }
00178                         _output[i]/=_chordPatterns[i].normalization;
00179                 }
00180         }
00181         const std::vector<double> & output() const
00182         {
00183                 return _output;
00184         }
00185 private:
00186         std::vector<ChordPattern> _chordPatterns;
00187         std::vector< std::vector<double> > _chordPatternsSimilarity;
00188         std::vector<std::string> _chordModeNames;
00189         ChordCorrelation _output;
00190 };
00191 
00192 } // namespace Simac
00193 
00194 #endif// ChordCorrelator_hxx
00195 
Generated by  doxygen 1.6.3