00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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},
00069 {{1,0,0,0,1,0,0,1,0,0,1,0}, "Dominant7", 12},
00070 {{1,0,0,1,0,0,0,1,0,0,0,1}, "MinorMajor7",12},
00071 {{1,0,0,1,0,0,0,1,0,0,1,0}, "Minor7", 12},
00072
00073
00074
00075
00076
00077 {{1,0,0,0,1,0,0,0,1,0,0,0}, "Augmented", 4},
00078 {{1,0,0,1,0,0,1,0,0,0,0,0}, "Diminished", 12},
00079 {{1,0,0,1,0,0,1,0,0,0,1,0}, "Diminished7",12},
00080
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
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 }
00193
00194 #endif// ChordCorrelator_hxx
00195