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 "MultiCumulativeDiffAlgo.h"
27 #include <CppAddons/CAMath.h>
41 void MultiCumulativeDiffAlgo::init()
43 for(size_t i=0; i<size(); i++)
45 if(m_diffs[i]!=NULL) delete m_diffs[i];
47 m_diffs[i] = new CumulativeDiff(1, i+GetSemitoneMin());
51 MultiCumulativeDiffAlgo::MultiCumulativeDiffAlgo(int latency_factor, double test_complexity)
53 assert(GetSamplingRate()>0);
55 m_test_complexity = test_complexity;
57 m_diffs.resize(size());
58 for(size_t i=0; i<size(); i++)
62 bool MultiCumulativeDiffAlgo::is_minima(int ih)
64 if(ih+1>=0 && ih+1<int(size()))
65 if(m_components[ih+1]<=m_components[ih])
67 if(ih-1>=0 && ih-1<int(size()))
68 if(m_components[ih-1]<=m_components[ih])
72 double MultiCumulativeDiffAlgo::getFondamentalWaveLength() const
74 return int(GetSamplingRate()/h2f(m_first_fond+GetSemitoneMin(), GetAFreq()));
76 void MultiCumulativeDiffAlgo::apply(const deque<double>& buff)
78 assert(GetSamplingRate()>0);
79 for(size_t i=0; i<size(); i++)
81 m_components[i] = 1.0;
82 m_is_fondamental[i] = false;
87 if(buff.empty() || buff.size()<(m_test_complexity+1)*m_diffs[0]->m_s)
91 for(size_t i=0; i<buff.size() && v<=getAmplitudeTreshold() && i<m_diffs[0]->m_s; i++)
92 v = max(v, abs(buff[i]));
94 if(v>getAmplitudeTreshold())
96 // compute all components
97 m_components_max = 0.0;
98 double min_comp = 1000000;
100 for(int ih=int(size())-1; ih>=0; ih--)
102 m_diffs[ih]->receive(buff, 0);
103 m_components[ih] = m_diffs[ih]->m_error;
104 m_components_max = max(m_components_max, m_components[ih]);
108 for(int ih=int(size())-1; ih>=0; ih--)
112 bool crit_min = true;
113 // criteria: the fond and his first harmonics are minimas
117 (is_minima(ih-19) || is_minima(ih-19-1) || is_minima(ih-19+1)) &&
122 bool crit_small_enough = true;
125 if(m_components[ih]/m_components_max>getComponentTreshold())
126 crit_small_enough = false;
127 ok = crit_small_enough;
130 // bool crit_cross_zero = true;
132 // criteria: wave should cross the zero value
136 for(int s=0; cross && s<int(m_diffs[ih]->m_s); s++)
138 double sg = Math::sgn(buff[s]);
139 bool same_side = true;
140 for(int i=0; same_side && i<int(m_diffs[ih]->m_s); i++)
141 same_side = Math::sgn(buff[s+i])==sg;
146 ok = crit_cross_zero = cross;
150 // bool crit_integ_cst = true;
151 // criteria: integral should be nearly constant while shifting
153 // (the previous criteria seems sufficient to remove high comp.)
156 // cerr << "ih=" << ih <<
157 // " harm_min=(("<<is_minima(ih-12)<<","<<is_minima(ih-12-1)<<","<<is_minima(ih-12+1)<<"),("<<
158 // is_minima(ih-19)<<","<<is_minima(ih-19-1)<<","<<is_minima(ih-19+1)<<"),("<<
159 // is_minima(ih-24)<<","<<is_minima(ih-24-1)<<","<<is_minima(ih-24+1)<<"))"<< crit_min <<
160 // " increase=" << crit_incr_err <<
161 // " cross_zero=" << crit_cross_zero <<
162 // " integ_cst=" << crit_integ_cst <<
163 // " ok=" << ok << " c=" << m_components[ih] << endl;)
165 // if all criteria are ok
172 sum += wh*(m_components_max-m_components[ih]); n++;
173 i=12; if(ih-i>=0) {sum+=wh*(m_components_max-m_components[ih-i]); n++;}
174 i=19; if(ih-i>=0) {sum+=wh*(m_components_max-m_components[ih-i]); n++;}
175 i=24; if(ih-i>=0) {sum+=wh*(m_components_max-m_components[ih-i]); n++;}
177 LOG(cerr << "ih=" << ih << " sum=" << sum << endl;)
182 size_t step = size_t(m_diffs[ih]->m_s/m_test_complexity);
184 for(size_t s=0; ok && s<m_diffs[ih]->m_s; s+=step)
187 m_diffs[ih-1]->receive(buff, s);
188 m_components[ih-1] = m_diffs[ih-1]->m_error;
190 if(ih+1<int(size())){
191 m_diffs[ih+1]->receive(buff, s);
192 m_components[ih+1] = m_diffs[ih+1]->m_error;
194 m_diffs[ih]->receive(buff, s);
195 m_components[ih] = m_diffs[ih]->m_error;
202 min_comp = m_components[ih];
209 // cerr << "ff: " << m_first_fond << endl;
212 m_is_fondamental[m_first_fond] = true;
214 LOG(cerr << "m_first_fond=" << m_first_fond << endl;)
217 MultiCumulativeDiffAlgo::~MultiCumulativeDiffAlgo()
219 for(size_t i=0; i<m_diffs.size(); i++)