CircularPeakTunner.hxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef CircularPeakTunner_hxx
00023 #define CircularPeakTunner_hxx
00024 #include <list>
00025 #include <vector>
00026 #include <cmath>
00027
00028 namespace Simac
00029 {
00030
00041 class CircularPeakTunner
00042 {
00043 public:
00044 typedef std::vector<std::pair<double, double> > PeakList;
00045 typedef std::vector<std::pair<double, double> > PitchProfile;
00046 private:
00047 double _referenceTunning;
00048 PeakList _output;
00049 static const unsigned nSemitones = 12;
00050 static const unsigned binsPerSemitone = 3;
00051 public:
00052 CircularPeakTunner(double referenceTunning)
00053 : _referenceTunning(referenceTunning)
00054 {
00055 _output.reserve(nSemitones*binsPerSemitone);
00056 }
00057 ~CircularPeakTunner()
00058 {
00059 }
00068 unsigned chromagramToSemitone(double tunning, double peakPosition)
00069 {
00070 double scaledPosition = peakPosition/binsPerSemitone;
00071 double scaledTunning = tunning/binsPerSemitone;
00072 double scaledReference = _referenceTunning/binsPerSemitone;
00073
00074 double shift = tunningShift(scaledReference, scaledTunning);
00075 double tunnedPosition = tune(scaledPosition, shift);
00076
00077 int quantizedSemitone = int(tunnedPosition + .5);
00078 unsigned refoldedSemitone = (quantizedSemitone+nSemitones)%nSemitones;
00079 return refoldedSemitone;
00080 }
00081
00082 static double tunningShift(double reference, double tunning)
00083 {
00084 return - tunning - std::floor(reference-tunning+0.5);
00085 }
00086 static double tune(double peakPosition, double shift)
00087 {
00088 double tunnedPosition = peakPosition + shift;
00089 while (tunnedPosition<0) tunnedPosition += nSemitones;
00090 while (tunnedPosition>= nSemitones) tunnedPosition -= nSemitones;
00091 return tunnedPosition;
00092 }
00093
00094 void doIt(double center, const PeakList & peaks)
00095 {
00096 _output.resize(0);
00097 const unsigned nPeaks=peaks.size();
00098 double shift= tunningShift(_referenceTunning, center);
00099 for (unsigned i=0; i<nPeaks; i++)
00100 {
00101 double tunnedPosition = tune(peaks[i].first,shift);
00102 _output.push_back(std::make_pair(tunnedPosition,peaks[i].second));
00103 }
00104 }
00105
00106 const PeakList & output() const
00107 {
00108 return _output;
00109 }
00110 };
00111
00112 }
00113
00114 #endif// CircularPeakTunner_hxx
00115