Mercurial > hg > svcore
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 |