CFugue
Chords.cpp
1 
2 #include "stdafx.h"
3 
4 #include "Chords.h"
5 #include <algorithm>
6 
7 namespace CFugue
8 {
9  ///<brief>Standard Chord Definitions</brief>
10  /// Each entry in the chord definition holds the chord name, followed by the half-step intervals.
11  static const ChordDef DefChordDefinitions[] =
12  {
13  {_T("MAJ"), {4,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
14  {_T("MIN"), {3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
15  {_T("AUG"), {4,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
16  {_T("DIM"), {3,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
17  {_T("DOM7"), {4,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
18  {_T("MAJ7"), {4,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
19  {_T("MIN7"), {3,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
20  {_T("SUS4"), {5,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
21  {_T("SUS2"), {2,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 2},
22  {_T("MAJ6"), {4,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
23  {_T("MIN6"), {3,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
24  {_T("DOM9"), {4,7,10,14,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
25  {_T("MAJ9"), {4,7,11,14,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
26  {_T("MIN9"), {3,7,10,14,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
27  {_T("DIM7"), {3,6,9,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
28  {_T("ADD9"), {4,7,14,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
29  {_T("MIN11"), {7,10,14,15,17,0,0,0,0,0,0,0,0,0,0,0}, 5},
30  {_T("DOM11"), {7,10,14,17,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
31  {_T("DOM13"), {7,10,14,16,21,0,0,0,0,0,0,0,0,0,0,0}, 5},
32  {_T("MIN13"), {7,10,14,15,21,0,0,0,0,0,0,0,0,0,0,0}, 5},
33  {_T("MAJ13"), {7,11,14,16,21,0,0,0,0,0,0,0,0,0,0,0}, 5},
34  {_T("DOM7_5"), {4,6,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
35  {_T("DOM7<5"), {4,6,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
36  {_T("DOM75"), {4,8,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
37  {_T("DOM7>5"), {4,8,10,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
38  {_T("MAJ7_5"), {4,6,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
39  {_T("MAJ7<5"), {4,6,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
40  {_T("MAJ75"), {4,8,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
41  {_T("MAJ7>5"), {4,8,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
42  {_T("MINMAJ7"), {3,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0}, 3},
43  {_T("DOM7_5_9"), {4,6,10,13,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
44  {_T("DOM7<5<9"), {4,6,10,13,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
45  {_T("DOM7_59"), {4,6,10,15,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
46  {_T("DOM7<5>9"), {4,6,10,15,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
47  {_T("DOM75_9"), {4,8,10,13,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
48  {_T("DOM7>5<9"), {4,8,10,13,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
49  {_T("DOM759"), {4,8,10,15,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
50  {_T("DOM7>5>9"), {4,8,10,15,0,0,0,0,0,0,0,0,0,0,0,0}, 4},
51  };
52 
53 #ifndef _countof
54  // helper function to find the size of array
55  template < typename T, size_t N >
56  inline size_t _countof(T(&arr)[N]) { return std::extent< T[N] >::value; }
57 #endif
58 
59  // Return if the first element is greater than the second
60  template<typename T>
61  bool phRepComparator(const T* input1, const T* input2)
62  {
63  return _tcslen(input1->szChordName) > _tcslen(input2->szChordName);
64  }
65 
66  template<typename T>
67  void LoadVector(std::map<TCHAR, std::vector<const T*> >& vecArray, const T* inputArr, int nInputSize)
68  {
69  // For each entry in the definition
70  for(int i=0; i < nInputSize; ++i)
71  {
72  const T& Obj = inputArr[i];
73  // Find the First character
74  const TCHAR chIndex = Obj.szChordName[0];
75  // Store the definition, indexed at its first character
76  vecArray[chIndex].push_back(inputArr+i);
77  }
78 
79  typedef typename std::map<TCHAR, std::vector<const T*> >::value_type VecIterTypeT;
80 
81  // Sort each vector such that longer strings come first
82  std::for_each(vecArray.begin(), vecArray.end(), [](VecIterTypeT& iter)
83  {
84  std::vector<const T*>& vec = iter.second;
85  std::sort(vec.begin(), vec.end(), phRepComparator<T>);
86  });
87  }
88 
89  // Checks if the given prefix string is complete present in the string.
90  // Return value would be same as the length of the prefix string, if successful.
91  // Return value would be zero, in case the prefix string is not present completely.
92  inline unsigned int IsPrefixMatching(const TCHAR* sz, const TCHAR* pfx)
93  {
94  unsigned int nMatched = 0;
95 
96  while(*sz && *pfx && *sz == *pfx)
97  {
98  sz++;
99  pfx++;
100  nMatched++;
101  }
102 
103  return (*pfx == _T('\0')) ? nMatched : 0;
104  }
105 
106  // Searches the vectors to find the best prefix that matches the sequence of
107  // characters pointed by sz.
108  // @param retVal Holds the object whose strint completely matched the prefix of sz
109  // @return the number of characters correctly matched (should be the same as the length of retVal)
110  template<typename T>
111  inline unsigned int ExtractMatchingObject(const std::map<TCHAR, std::vector<const T*> >& vecArray, const TCHAR* sz, T* retVal)
112  {
113  const TCHAR chIndex = sz[0];
114 
115  const auto iterVecObjects = vecArray.find(chIndex);
116 
117  if(iterVecObjects != vecArray.end())
118  {
119  const std::vector<const T*>& vecObjects = iterVecObjects->second;
120 
121  unsigned int nMatched = 0;
122 
123  for(size_t i=0, nMax = vecObjects.size(); i < nMax; ++i)
124  {
125  *retVal = *vecObjects[i];
126 
127  if((nMatched = IsPrefixMatching(sz, retVal->szChordName)) > 0)
128  return nMatched;
129  }
130  }
131 
132  return 0;
133  }
134 
136  {
137  LoadDefinitions();
138  }
139 
140  Chords::Chords(const ChordDef* pChords, int nSize)
141  {
142  LoadDefinitions(pChords, nSize);
143  }
144 
145  void Chords::LoadDefinitions(const ChordDef* pChords /*=NULL*/, int nSize /*=0*/)
146  {
147  m_Definitions.clear();
148  if(pChords == NULL || nSize == 0)
149  {
150  pChords = DefChordDefinitions;
151  nSize = _countof(DefChordDefinitions);
152  }
153  LoadVector(this->m_Definitions, pChords, nSize);
154  }
155 
156  void Chords::AddDefinitions(const ChordDef* pChords, int nSize)
157  {
158  // Load the input Arrays into internal structures
159  if(pChords != NULL && nSize != 0)
160  LoadVector(this->m_Definitions, pChords, nSize);
161  }
162 
163  unsigned int Chords::ExtractMatchingChord(const TCHAR* szToken, ChordDef* retVal) const
164  {
165  return ExtractMatchingObject(this->m_Definitions, szToken, retVal);
166  }
167 
168  unsigned int Chords::GetDefaultMatchingChord(const TCHAR* szToken, ChordDef* retVal)
169  {
170  static Chords staticObj; // Loads the default chord definitions
171  return staticObj.ExtractMatchingChord(szToken, retVal);
172  }
173 
174 } // namespace CFugue
Chords()
Initialize the Chords with default definitions.
Definition: Chords.cpp:135
void LoadDefinitions(const ChordDef *pChords=NULL, int nSize=0)
Definition: Chords.cpp:145
unsigned int ExtractMatchingChord(const TCHAR *szToken, ChordDef *retVal) const
Definition: Chords.cpp:163
Definition of a Chord entry.
Definition: Chords.h:19
Maniuplates Chord definitions for Western Music
Definition: Chords.h:31
static unsigned int GetDefaultMatchingChord(const TCHAR *szToken, ChordDef *retVal)
Definition: Chords.cpp:168
void AddDefinitions(const ChordDef *pChords, int nSize)
Definition: Chords.cpp:156

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem