comparison data/model/FFTModel.cpp @ 1527:710e6250a401 zoom

Merge from default branch
author Chris Cannam
date Mon, 17 Sep 2018 13:51:14 +0100
parents 0925b37a3ed1
children 36b4872e894a
comparison
equal deleted inserted replaced
1324:d4a28d1479a8 1527:710e6250a401
17 #include "DenseTimeValueModel.h" 17 #include "DenseTimeValueModel.h"
18 18
19 #include "base/Profiler.h" 19 #include "base/Profiler.h"
20 #include "base/Pitch.h" 20 #include "base/Pitch.h"
21 #include "base/HitCount.h" 21 #include "base/HitCount.h"
22 #include "base/Debug.h"
22 23
23 #include <algorithm> 24 #include <algorithm>
24 25
25 #include <cassert> 26 #include <cassert>
26 #include <deque> 27 #include <deque>
42 m_windowSize(windowSize), 43 m_windowSize(windowSize),
43 m_windowIncrement(windowIncrement), 44 m_windowIncrement(windowIncrement),
44 m_fftSize(fftSize), 45 m_fftSize(fftSize),
45 m_windower(windowType, windowSize), 46 m_windower(windowType, windowSize),
46 m_fft(fftSize), 47 m_fft(fftSize),
48 m_cacheWriteIndex(0),
47 m_cacheSize(3) 49 m_cacheSize(3)
48 { 50 {
51 while (m_cached.size() < m_cacheSize) {
52 m_cached.push_back({ -1, cvec(m_fftSize / 2 + 1) });
53 }
54
49 if (m_windowSize > m_fftSize) { 55 if (m_windowSize > m_fftSize) {
50 cerr << "ERROR: FFTModel::FFTModel: window size (" << m_windowSize 56 SVCERR << "ERROR: FFTModel::FFTModel: window size (" << m_windowSize
51 << ") must be at least FFT size (" << m_fftSize << ")" << endl; 57 << ") must be at least FFT size (" << m_fftSize << ")" << endl;
52 throw invalid_argument("FFTModel window size must be at least FFT size"); 58 throw invalid_argument("FFTModel window size must be at least FFT size");
53 } 59 }
54 60
55 m_fft.initFloat(); 61 m_fft.initFloat();
56 62
65 71
66 void 72 void
67 FFTModel::sourceModelAboutToBeDeleted() 73 FFTModel::sourceModelAboutToBeDeleted()
68 { 74 {
69 if (m_model) { 75 if (m_model) {
70 cerr << "FFTModel[" << this << "]::sourceModelAboutToBeDeleted(" << m_model << ")" << endl; 76 SVDEBUG << "FFTModel[" << this << "]::sourceModelAboutToBeDeleted(" << m_model << ")" << endl;
71 m_model = 0; 77 m_model = 0;
72 } 78 }
73 } 79 }
74 80
75 int 81 int
186 imags[i] = col[minbin + i].imag(); 192 imags[i] = col[minbin + i].imag();
187 } 193 }
188 return true; 194 return true;
189 } 195 }
190 196
191 vector<float> 197 FFTModel::fvec
192 FFTModel::getSourceSamples(int column) const 198 FFTModel::getSourceSamples(int column) const
193 { 199 {
194 // m_fftSize may be greater than m_windowSize, but not the reverse 200 // m_fftSize may be greater than m_windowSize, but not the reverse
195 201
196 // cerr << "getSourceSamples(" << column << ")" << endl; 202 // cerr << "getSourceSamples(" << column << ")" << endl;
202 208
203 if (off == 0) { 209 if (off == 0) {
204 return data; 210 return data;
205 } else { 211 } else {
206 vector<float> pad(off, 0.f); 212 vector<float> pad(off, 0.f);
207 vector<float> padded; 213 fvec padded;
208 padded.reserve(m_fftSize); 214 padded.reserve(m_fftSize);
209 padded.insert(padded.end(), pad.begin(), pad.end()); 215 padded.insert(padded.end(), pad.begin(), pad.end());
210 padded.insert(padded.end(), data.begin(), data.end()); 216 padded.insert(padded.end(), data.begin(), data.end());
211 padded.insert(padded.end(), pad.begin(), pad.end()); 217 padded.insert(padded.end(), pad.begin(), pad.end());
212 return padded; 218 return padded;
213 } 219 }
214 } 220 }
215 221
216 vector<float> 222 FFTModel::fvec
217 FFTModel::getSourceData(pair<sv_frame_t, sv_frame_t> range) const 223 FFTModel::getSourceData(pair<sv_frame_t, sv_frame_t> range) const
218 { 224 {
219 // cerr << "getSourceData(" << range.first << "," << range.second 225 // cerr << "getSourceData(" << range.first << "," << range.second
220 // << "): saved range is (" << m_savedData.range.first 226 // << "): saved range is (" << m_savedData.range.first
221 // << "," << m_savedData.range.second << ")" << endl; 227 // << "," << m_savedData.range.second << ")" << endl;
233 239
234 inSourceCache.partial(); 240 inSourceCache.partial();
235 241
236 sv_frame_t discard = range.first - m_savedData.range.first; 242 sv_frame_t discard = range.first - m_savedData.range.first;
237 243
238 vector<float> acc(m_savedData.data.begin() + discard, 244 fvec data;
239 m_savedData.data.end()); 245 data.reserve(range.second - range.first);
240 246
241 vector<float> rest = 247 data.insert(data.end(),
242 getSourceDataUncached({ m_savedData.range.second, range.second }); 248 m_savedData.data.begin() + discard,
243 249 m_savedData.data.end());
244 acc.insert(acc.end(), rest.begin(), rest.end()); 250
251 fvec rest = getSourceDataUncached
252 ({ m_savedData.range.second, range.second });
253
254 data.insert(data.end(), rest.begin(), rest.end());
245 255
246 m_savedData = { range, acc }; 256 m_savedData = { range, data };
247 return acc; 257 return data;
248 258
249 } else { 259 } else {
250 260
251 inSourceCache.miss(); 261 inSourceCache.miss();
252 262
254 m_savedData = { range, data }; 264 m_savedData = { range, data };
255 return data; 265 return data;
256 } 266 }
257 } 267 }
258 268
259 vector<float> 269 FFTModel::fvec
260 FFTModel::getSourceDataUncached(pair<sv_frame_t, sv_frame_t> range) const 270 FFTModel::getSourceDataUncached(pair<sv_frame_t, sv_frame_t> range) const
261 { 271 {
272 Profiler profiler("FFTModel::getSourceDataUncached");
273
262 decltype(range.first) pfx = 0; 274 decltype(range.first) pfx = 0;
263 if (range.first < 0) { 275 if (range.first < 0) {
264 pfx = -range.first; 276 pfx = -range.first;
265 range = { 0, range.second }; 277 range = { 0, range.second };
266 } 278 }
282 vector<float> pad(pfx, 0.f); 294 vector<float> pad(pfx, 0.f);
283 data.insert(data.begin(), pad.begin(), pad.end()); 295 data.insert(data.begin(), pad.begin(), pad.end());
284 } 296 }
285 297
286 if (m_channel == -1) { 298 if (m_channel == -1) {
287 int channels = m_model->getChannelCount(); 299 int channels = m_model->getChannelCount();
288 if (channels > 1) { 300 if (channels > 1) {
289 int n = int(data.size()); 301 int n = int(data.size());
290 float factor = 1.f / float(channels); 302 float factor = 1.f / float(channels);
291 // use mean instead of sum for fft model input 303 // use mean instead of sum for fft model input
292 for (int i = 0; i < n; ++i) { 304 for (int i = 0; i < n; ++i) {
293 data[i] *= factor; 305 data[i] *= factor;
294 } 306 }
295 } 307 }
296 } 308 }
297 309
298 return data; 310 return data;
299 } 311 }
300 312
301 vector<complex<float>> 313 const FFTModel::cvec &
302 FFTModel::getFFTColumn(int n) const 314 FFTModel::getFFTColumn(int n) const
303 { 315 {
304 // The small cache (i.e. the m_cached deque) is for cases where 316 // The small cache (i.e. the m_cached deque) is for cases where
305 // values are looked up individually, and for e.g. peak-frequency 317 // values are looked up individually, and for e.g. peak-frequency
306 // spectrograms where values from two consecutive columns are 318 // spectrograms where values from two consecutive columns are
319 331
320 auto samples = getSourceSamples(n); 332 auto samples = getSourceSamples(n);
321 m_windower.cut(samples.data()); 333 m_windower.cut(samples.data());
322 breakfastquay::v_fftshift(samples.data(), m_fftSize); 334 breakfastquay::v_fftshift(samples.data(), m_fftSize);
323 335
324 vector<complex<float>> col(m_fftSize/2 + 1); 336 cvec &col = m_cached[m_cacheWriteIndex].col;
325 337
326 m_fft.forwardInterleaved(samples.data(), 338 m_fft.forwardInterleaved(samples.data(),
327 reinterpret_cast<float *>(col.data())); 339 reinterpret_cast<float *>(col.data()));
328 340
329 SavedColumn sc { n, col }; 341 m_cached[m_cacheWriteIndex].n = n;
330 if (m_cached.size() >= m_cacheSize) { 342
331 m_cached.pop_front(); 343 m_cacheWriteIndex = (m_cacheWriteIndex + 1) % m_cacheSize;
332 }
333 m_cached.push_back(sc);
334 344
335 return col; 345 return col;
336 } 346 }
337 347
338 bool 348 bool