CLAM-Development  1.4.0
ChordCorrelator.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2006 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef ChordCorrelator_hxx
23 #define ChordCorrelator_hxx
24 #include <list>
25 #include <vector>
26 #include <cmath>
27 #include <sstream>
28 
29 namespace Simac
30 {
31 
42 {
43 public:
44  static std::string PitchNames(unsigned index)
45  {
46  static const char * PitchNames[] = {"G","G#","A","A#","B","C","C#","D","D#","E","F","F#"};
47  return PitchNames[index];
48  }
49  enum Pitch {G,Ab,A,Bb,B,C,Db,D,Eb,E,F,Gb};
50  typedef unsigned ChordMode;
51  typedef std::vector<double> PCP;
52  typedef std::vector<double> ChordCorrelation;
53 
55  {
56  double pattern[12];
57  const char * name;
58  unsigned nRoots;
59  };
60 
62  {
63  static ChordModePatterns patterns[] =
64  {
65  {{1,1,1,1,1,1,1,1,1,1,1,1}, "None", 1},
66  {{1,0,0,0,1,0,0,1,0,0,0,0}, "Major", 12},
67  {{1,0,0,1,0,0,0,1,0,0,0,0}, "Minor", 12},
68  {{1,0,0,0,1,0,0,1,0,0,0,1}, "Major7", 12}, // Cmaj7
69  {{1,0,0,0,1,0,0,1,0,0,1,0}, "Dominant7", 12}, // C7
70  {{1,0,0,1,0,0,0,1,0,0,0,1}, "MinorMajor7",12}, // Cm/maj7
71  {{1,0,0,1,0,0,0,1,0,0,1,0}, "Minor7", 12}, // Cm7
72 // {{1,0,1,0,0,0,0,1,0,0,0,0}, "Suspended2", 12}, // Csus2
73 // {{1,0,0,0,0,1,0,1,0,0,0,0}, "Suspended4", 12}, // Csus4
74 // {{1,0,0,0,1,0,0,1,0,1,0,0}, "Major6", 12}, // C6
75 // {{1,0,0,1,0,0,0,1,0,1,0,0}, "Minor6", 12}, // Cm6
76 // {{1,0,1,0,1,0,0,1,0,1,0,0}, "6/9", 12}, // C6/9
77  {{1,0,0,0,1,0,0,0,1,0,0,0}, "Augmented", 4}, // Caug
78  {{1,0,0,1,0,0,1,0,0,0,0,0}, "Diminished", 12}, // Cdim
79  {{1,0,0,1,0,0,1,0,0,0,1,0}, "Diminished7",12}, // Cdim7
80 // {{1,0,0,0,0,0,0,1,0,0,0,0}, "Fifth", 12}, // C5
81  {{0,0,0,0,0,0,0,0,0,0,0,0}, 0, 0}
82  };
83  return patterns;
84  }
85 
86  struct ChordPattern {
87  double pattern[12];
90  double normalization;
91 
92  };
93 public:
95  {
96  for (unsigned mode=0; modePatterns[mode].name; mode++)
97  {
98  _chordModeNames.push_back(modePatterns[mode].name);
99  double * basePattern = modePatterns[mode].pattern;
100  double normalizationFactor = 0.0;
101  for (unsigned i = 0; i<12; i++)
102  normalizationFactor += basePattern[i];
103 
104  for (unsigned root=0; root<modePatterns[mode].nRoots; root++)
105  {
106  ChordPattern pattern;
107  pattern.root = Pitch(root);
108  pattern.mode = mode;
109  pattern.normalization = normalizationFactor;
110  for (unsigned i=root; i<12; i++)
111  pattern.pattern[i] = basePattern[i-root];
112  for (unsigned i=0; i<root; i++)
113  pattern.pattern[i] = basePattern[12+i-root];
114  _chordPatterns.push_back(pattern);
115  }
116  }
117  for (unsigned i=0; i<_chordPatterns.size(); i++)
118  {
119  std::vector<double> singleRow;
120  for (unsigned j=0; j<_chordPatterns.size(); j++)
121  {
122  double chordPatternCorrelation = 0;
123  for (unsigned k=0; k<12; k++)
124  {
125  chordPatternCorrelation += (_chordPatterns[i].pattern[k] * _chordPatterns[j].pattern[k]);
126  }
127  chordPatternCorrelation /= (_chordPatterns[i].normalization + _chordPatterns[j].normalization) / 2.0;
128  singleRow.push_back(chordPatternCorrelation);
129  //singleRow.push_back(1.0);
130  }
131  _chordPatternsSimilarity.push_back(singleRow);
132  }
133  _output.resize(_chordPatterns.size());
134  }
135  void DumpChordPatterns(std::ostream & os)
136  {
137  for (unsigned pattern=0; pattern<_chordPatterns.size(); pattern++)
138  {
139  for (unsigned i=0; i<12; i++)
140  os << _chordPatterns[pattern].pattern[i] << " ";
141  os << _chordPatterns[pattern].normalization << " ";
142  os << PitchNames(_chordPatterns[pattern].root) << " ";
143  os << _chordModeNames[_chordPatterns[pattern].mode] << "\n";
144  }
145  }
146  std::string root(unsigned chordIndex) const
147  {
148  return PitchNames(_chordPatterns[chordIndex].root);
149  }
150  std::string mode(unsigned chordIndex) const
151  {
152  return _chordModeNames[_chordPatterns[chordIndex].mode];
153  }
154  std::string chordRepresentation(unsigned chordIndex) const
155  {
156  std::ostringstream os;
157  os << PitchNames(_chordPatterns[chordIndex].root) << "_";
158  os << _chordModeNames[_chordPatterns[chordIndex].mode];
159  return os.str();
160  }
161  std::vector< std::vector<double> > chordPatternsSimilarity() const
162  {
163  return _chordPatternsSimilarity;
164  }
166  {
167  }
168  void doIt(const PCP & pcp)
169  {
170  for (unsigned int i=0; i<_chordPatterns.size(); i++)
171  {
172  _output[i]=0.0;
173  double * chordPattern = _chordPatterns[i].pattern;
174  for (unsigned pitch=0; pitch<12; pitch++)
175  {
176  _output[i]+= chordPattern[pitch] * pcp[pitch];
177  }
178  _output[i]/=_chordPatterns[i].normalization;
179  }
180  }
181  const std::vector<double> & output() const
182  {
183  return _output;
184  }
185 private:
186  std::vector<ChordPattern> _chordPatterns;
187  std::vector< std::vector<double> > _chordPatternsSimilarity;
188  std::vector<std::string> _chordModeNames;
189  ChordCorrelation _output;
190 };
191 
192 } // namespace Simac
193 
194 #endif// ChordCorrelator_hxx
195