CLAM-Development  1.4.0
CircularPeakTunner.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 CircularPeakTunner_hxx
23 #define CircularPeakTunner_hxx
24 #include <list>
25 #include <vector>
26 #include <cmath>
27 
28 namespace Simac
29 {
30 
42 {
43 public:
44  typedef std::vector<std::pair<double, double> > PeakList;
45  typedef std::vector<std::pair<double, double> > PitchProfile;
46 private:
47  double _referenceTunning;
48  PeakList _output;
49  static const unsigned nSemitones = 12;
50  static const unsigned binsPerSemitone = 3;
51 public:
52  CircularPeakTunner(double referenceTunning)
53  : _referenceTunning(referenceTunning)
54  {
55  _output.reserve(nSemitones*binsPerSemitone);
56  }
58  {
59  }
68  unsigned chromagramToSemitone(double tunning, double peakPosition)
69  {
70  double scaledPosition = peakPosition/binsPerSemitone;
71  double scaledTunning = tunning/binsPerSemitone;
72  double scaledReference = _referenceTunning/binsPerSemitone;
73 
74  double shift = tunningShift(scaledReference, scaledTunning);
75  double tunnedPosition = tune(scaledPosition, shift);
76 
77  int quantizedSemitone = int(tunnedPosition + .5);
78  unsigned refoldedSemitone = (quantizedSemitone+nSemitones)%nSemitones;
79  return refoldedSemitone;
80  }
81 
82  static double tunningShift(double reference, double tunning)
83  {
84  return - tunning - std::floor(reference-tunning+0.5);
85  }
86  static double tune(double peakPosition, double shift)
87  {
88  double tunnedPosition = peakPosition + shift;
89  while (tunnedPosition<0) tunnedPosition += nSemitones;
90  while (tunnedPosition>= nSemitones) tunnedPosition -= nSemitones;
91  return tunnedPosition;
92  }
93 
94  void doIt(double center, const PeakList & peaks)
95  {
96  _output.resize(0);
97  const unsigned nPeaks=peaks.size();
98  double shift= tunningShift(_referenceTunning, center);
99  for (unsigned i=0; i<nPeaks; i++)
100  {
101  double tunnedPosition = tune(peaks[i].first,shift);
102  _output.push_back(std::make_pair(tunnedPosition,peaks[i].second));
103  }
104  }
105 
106  const PeakList & output() const
107  {
108  return _output;
109  }
110 };
111 
112 } // namespace Simac
113 
114 #endif// CircularPeakTunner_hxx
115