![]() |
Mixxx
|
00001 /* 00002 * Copyright (c) 2001-2006 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 } // namespace Simac 00113 00114 #endif// CircularPeakTunner_hxx 00115