1 // Copyright 2004 "Gilles Degottex"
3 // This file is part of "Music"
5 // "Music" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 2.1 of the License, or
8 // (at your option) any later version.
10 // "Music" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "CumulativeDiffAlgo.h"
28 #include <CppAddons/CAMath.h>
42 void CumulativeDiffAlgo::init()
44 setMinMaxLength(int(GetSamplingRate()/h2f(GetSemitoneMax())), int(GetSamplingRate()/h2f(GetSemitoneMin())));
47 CumulativeDiffAlgo::CumulativeDiffAlgo(double noise_treshold)
48 : m_noise_threshold(noise_treshold)
54 //! return the average differance on the sample delimited by [0,size]
55 // - ne pas utiliser tout size
56 // - sauter des données
57 double diff(const deque<double>& buff, size_t size, size_t s)
60 for(size_t i=0; i<size; i++)
61 r += abs(buff[i] - buff[i+s]);
65 void CumulativeDiffAlgo::apply(const deque<double>& buff)
67 if(buff.size()<2*m_max_length)
74 for(size_t i=0; i<m_max_length; i++)
75 max_vol = max(max_vol, buff[i]);
77 // use a relative threshold
78 double threshold = m_noise_threshold*max_vol;
80 // cerr << "min=" << min_length << " max=" << m_max_length << " threshold=" << treshold << endl;
84 for(s=m_min_length; r<=threshold && s<m_max_length; s++)
85 r = diff(buff, m_max_length, s);
87 while((r=diff(buff, m_max_length, s+1))>threshold && s<m_max_length)
90 // cerr << "s=" << s << " r=" << r << endl;
92 while(s+1<m_max_length && (r=diff(buff, m_max_length, s+1))<old_r)
94 // cerr << "s=" << s << " r=" << r << endl;
99 // cerr << "s=" << s << " r=" << old_r << endl;
101 // cerr << "absolute threshold=" << m_noise_threshold << " max volume="<<max_vol<<" relative threshold="<<threshold << " s="<<s << " m_max_length="<<m_max_length << endl;
103 m_wave_length = (s<m_max_length)?s:0;
107 * ~YIN version, unused because too costly for the CPU: O(n^3) ...
108 double CumulativeDiffAlgo::squar_diff(const deque<double>& buff, size_t s)
111 for(size_t i=0; i<s; i++)
113 double d = buff[i] - buff[i+s];
119 double CumulativeDiffAlgo::norm_squar_diff(const deque<double>& buff, size_t s)
122 for(size_t i=0; i<s; i++)
123 r += squar_diff(buff, i);
125 return squar_diff(buff, s) / (r/s);
127 void CumulativeDiffAlgo::receive(const deque<double>& buff)
129 assert(m_sampling_rate>0);
130 size_t min_length = size_t(m_sampling_rate * m_min_wave_length);
131 size_t max_length = size_t(m_sampling_rate * m_max_wave_length);
133 if(buff.size()<2*max_length) return;
135 cerr << "min=" << min_length << " max=" << max_length << " noise=" << m_noise_treshold << endl;
138 double max_vol = 0.0;
140 for(s=min_length; r>m_noise_treshold && s<max_length; s++)
142 max_vol = max(max_vol, buff[s]);
144 r = norm_squar_diff(buff, s);
145 // cerr << "s=" << s << " r=" << r << endl;
148 cerr << "s=" << s << " r=" << r << endl;
149 // cerr << "---" << endl;
156 r = norm_squar_diff(buff, s);
157 // cerr << "s=" << s << " r=" << r << endl;
159 while(r<old_r && s<max_length);
163 cerr << "s=" << s << " r=" << r << endl;
165 cerr << "m_noise_treshold=" << m_noise_treshold << " max_vol=" << max_vol << " r=" << r << endl;
168 if(max_vol>m_noise_treshold && s<max_length)
170 cerr << "r=" << r << " m_noise_treshold=" << m_noise_treshold << endl;
171 m_freq = double(m_sampling_rate)/s;
174 cerr << "m_sampling_rate=" << m_sampling_rate << " freq=" << m_freq << endl;