1 // Copyright 2007 "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
27 #include "FreqAnalysis.h"
33 m_use_audibility_treshold = false;
37 m_window_factor = 1.0;
41 void CombedFT::setZeroPaddingFactor(double zp)
49 void CombedFT::setWindowFactor(double wf)
51 if(wf!=m_window_factor)
60 if(GetSamplingRate()<=0) return;
64 int win_size = int(m_window_factor*GetSamplingRate()/h2f(GetSemitoneMin()));// at least m_window_factor period of the lowest freq
67 while(best_size<int(win_size))
70 m_win = hann(best_size);
72 while(best_size<int(m_zp_factor*win_size))
75 cerr << "CombedFT: INFO: window size=" << win_size << " FFT size=" << best_size << " window size factor=" << m_window_factor << " zero padding factor=" << m_zp_factor << endl;
77 m_plan.resize(best_size);
78 m_components.resize(m_plan.size()/2);
79 m_comb.resize(m_plan.size()/2);
81 int CombedFT::getSampleAlgoLatency() const
83 return 1000*m_win.size()/GetSamplingRate();
85 int CombedFT::getMinSize() const
89 double CombedFT::getFondamentalFreq() const
94 void CombedFT::apply(const deque<double>& buff)
96 // cerr << getAmplitudeTreshold() << " " << getComponentTreshold() << " " << m_audib_ratio << endl;
98 if(int(buff.size())<getMinSize() || m_win.empty()) return;
100 m_max_amplitude = 0.0;
101 for(size_t i=0; i<m_win.size(); i++)
103 m_plan.in[i] = buff[i]*m_win[i];
105 if(abs(buff[i])>m_max_amplitude)
106 m_max_amplitude = abs(buff[i]);
108 for(int i=m_win.size(); i<m_plan.size(); i++) // padd with zeros
113 for(size_t i=0; i<m_comb.in.size() && i<m_plan.out.size(); i++)
114 m_comb.in[i] = mod(m_plan.out[i]);
116 // compute max with respect of the bounds
117 m_components_max = 0.0;
119 double fmin = h2f(GetSemitoneMin());
120 double fmax = h2f(GetSemitoneMax());
121 for(size_t i=0; i<m_components.size(); i++)
123 double fi = i*double(GetSamplingRate())/m_plan.size();
124 if(fmin<=fi && fi<=fmax
125 && m_comb.in[i]>m_components_max)
128 m_components_max = m_comb.in[i];
134 if(m_components_max>getComponentTreshold())
136 m_f0 = PeakRefinementLogParabola(m_plan.out, max_index)*double(GetSamplingRate())/m_plan.size();
138 // TODO TEST *win[i]; // me semble qu'une trans de harm signal n'est pas trop discontinue aux extrémités
141 for(size_t i=0; i<m_components.size(); i++)
142 m_components[i] = 0.0;
144 for(size_t i=0; i<m_comb.out.size()/2; i++)
145 m_components[i] = real(m_comb.out[i]);
147 // avg is not interesting
148 m_components[0] = 0.0;
150 // frequencies between 1 and g_res_factor are virtuals
151 // for(int i=m_comb.out.size()-(g_res_factor-1); i<m_comb.out.size(); i++)
152 // m_components[i] = 0.0;
154 double step = (m_plan.size()/max_index)/2;
155 // hyp: the fund freq is not greater than the max amplitude harmonic
156 // keep only multiples of the max amplitude harmonic
157 for(int i=1; i<int(m_components.size())/step; i++)
158 m_components[i] = m_components[int(step*i)];
159 for(int i=int(m_components.size()/step); i<int(m_components.size()); i++)
160 m_components[i] = 0.0;
162 if(m_use_audibility_treshold)
164 for(int i=1; i<int(m_components.size()/step); i++)
165 m_components[i] /= (1+m_audib_ratio*(i-1));
169 vector<double> temp_comp(int(m_components.size()/step), 0.0);
170 for(int i=1; i<int(temp_comp.size()); i++)
171 temp_comp[i] = (m_components[i]-m_components[i-1]) +
172 (m_components[i]-m_components[i+1]);
173 for(int i=1; i<int(temp_comp.size()); i++)
174 m_components[i] = temp_comp[i];
178 double max_amp = 0.0;
180 for(size_t i=0; i<m_components.size(); i++)
182 // double fi = i*double(GetSamplingRate())/m_win.size();
183 if(m_components[i]>max_amp)
186 max_amp = m_components[i];
194 // cerr << " final: " << GetSamplingRate() << ":" << m_f0 << endl;
196 CombedFT::~CombedFT()