Mercurial > hg > sonic-visualiser
comparison audioio/PhaseVocoderTimeStretcher.cpp @ 21:7da85e0b85e9
* Add some internal feedback to the time stretcher to try to make it maintain
tempo within variable timestretching situations -- not ideal but perhaps
better than nothing.
* Better tooltip text for play speeed control; make play sharpening control
remember its last state
author | Chris Cannam |
---|---|
date | Thu, 14 Sep 2006 16:08:23 +0000 |
parents | e125f0dde7a3 |
children | 80126455d169 |
comparison
equal
deleted
inserted
replaced
20:e125f0dde7a3 | 21:7da85e0b85e9 |
---|---|
24 float ratio, | 24 float ratio, |
25 bool sharpen, | 25 bool sharpen, |
26 size_t maxProcessInputBlockSize) : | 26 size_t maxProcessInputBlockSize) : |
27 m_channels(channels), | 27 m_channels(channels), |
28 m_ratio(ratio), | 28 m_ratio(ratio), |
29 m_sharpen(sharpen) | 29 m_sharpen(sharpen), |
30 m_totalCount(0), | |
31 m_transientCount(0), | |
32 m_n2sum(0) | |
30 { | 33 { |
31 m_wlen = 1024; | 34 m_wlen = 1024; |
35 | |
36 //!!! In transient sharpening mode, we need to pick the window | |
37 //length so as to be more or less fixed in audio duration (i.e. we | |
38 //need to know the sample rate) | |
32 | 39 |
33 if (ratio < 1) { | 40 if (ratio < 1) { |
34 if (ratio < 0.4) { | 41 if (ratio < 0.4) { |
35 m_n1 = 1024; | 42 m_n1 = 1024; |
36 m_wlen = 2048; | 43 m_wlen = 2048; |
38 m_n1 = 512; | 45 m_n1 = 512; |
39 } else { | 46 } else { |
40 m_n1 = 256; | 47 m_n1 = 256; |
41 } | 48 } |
42 if (m_sharpen) { | 49 if (m_sharpen) { |
43 // m_n1 /= 2; | |
44 m_wlen = 2048; | 50 m_wlen = 2048; |
45 } | 51 } |
46 m_n2 = m_n1 * ratio; | 52 m_n2 = m_n1 * ratio; |
47 } else { | 53 } else { |
48 if (ratio > 2) { | 54 if (ratio > 2) { |
53 m_wlen = 2048; | 59 m_wlen = 2048; |
54 } else { | 60 } else { |
55 m_n2 = 256; | 61 m_n2 = 256; |
56 } | 62 } |
57 if (m_sharpen) { | 63 if (m_sharpen) { |
58 // m_n2 /= 2; | |
59 if (m_wlen < 2048) m_wlen = 2048; | 64 if (m_wlen < 2048) m_wlen = 2048; |
60 } | 65 } |
61 m_n1 = m_n2 / ratio; | 66 m_n1 = m_n2 / ratio; |
62 } | 67 } |
63 | 68 |
66 | 71 |
67 m_prevPhase = new float *[m_channels]; | 72 m_prevPhase = new float *[m_channels]; |
68 m_prevAdjustedPhase = new float *[m_channels]; | 73 m_prevAdjustedPhase = new float *[m_channels]; |
69 | 74 |
70 m_prevTransientMag = (float *)fftwf_malloc(sizeof(float) * (m_wlen / 2 + 1)); | 75 m_prevTransientMag = (float *)fftwf_malloc(sizeof(float) * (m_wlen / 2 + 1)); |
71 m_prevTransientCount = 0; | 76 m_prevTransientScore = 0; |
72 m_prevTransient = false; | 77 m_prevTransient = false; |
73 | 78 |
74 m_tempbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen); | 79 m_tempbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen); |
75 | 80 |
76 m_time = new float *[m_channels]; | 81 m_time = new float *[m_channels]; |
247 | 252 |
248 if (transient) { | 253 if (transient) { |
249 n2 = m_n1; | 254 n2 = m_n1; |
250 } | 255 } |
251 | 256 |
257 ++m_totalCount; | |
258 if (transient) ++m_transientCount; | |
259 m_n2sum += n2; | |
260 | |
261 // std::cerr << "ratio for last 10: " <<last10num << "/" << (10 * m_n1) << " = " << float(last10num) / float(10 * m_n1) << " (should be " << m_ratio << ")" << std::endl; | |
262 | |
263 if (m_totalCount > 50 && m_transientCount < m_totalCount) { | |
264 | |
265 int fixed = lrintf(m_transientCount * m_n1); | |
266 int squashy = m_n2sum - fixed; | |
267 | |
268 int idealTotal = lrintf(m_totalCount * m_n1 * m_ratio); | |
269 int idealSquashy = idealTotal - fixed; | |
270 | |
271 int squashyCount = m_totalCount - m_transientCount; | |
272 | |
273 n2 = lrintf(idealSquashy / squashyCount); | |
274 | |
275 if (n2 != m_n2) { | |
276 std::cerr << m_n2 << " -> " << n2 << std::endl; | |
277 } | |
278 } | |
279 | |
252 for (size_t c = 0; c < m_channels; ++c) { | 280 for (size_t c = 0; c < m_channels; ++c) { |
253 | 281 |
254 synthesiseBlock(c, m_mashbuf[c], | 282 synthesiseBlock(c, m_mashbuf[c], |
255 c == 0 ? m_modulationbuf : 0, | 283 c == 0 ? m_modulationbuf : 0, |
256 m_prevTransient ? m_n1 : m_n2); | 284 m_prevTransient ? m_n1 : m_n2); |
285 } | 313 } |
286 | 314 |
287 for (size_t i = m_wlen - n2; i < m_wlen; ++i) { | 315 for (size_t i = m_wlen - n2; i < m_wlen; ++i) { |
288 m_modulationbuf[i] = 0.0f; | 316 m_modulationbuf[i] = 0.0f; |
289 } | 317 } |
318 | |
319 if (!transient) m_n2 = n2; | |
290 } | 320 } |
291 | 321 |
292 | 322 |
293 #ifdef DEBUG_PHASE_VOCODER_TIME_STRETCHER | 323 #ifdef DEBUG_PHASE_VOCODER_TIME_STRETCHER |
294 std::cerr << "loop ended: inbuf read space " << m_inbuf[0]->getReadSpace() << ", outbuf write space " << m_outbuf[0]->getWriteSpace() << std::endl; | 324 std::cerr << "loop ended: inbuf read space " << m_inbuf[0]->getReadSpace() << ", outbuf write space " << m_outbuf[0]->getWriteSpace() << std::endl; |
296 } | 326 } |
297 | 327 |
298 #ifdef DEBUG_PHASE_VOCODER_TIME_STRETCHER | 328 #ifdef DEBUG_PHASE_VOCODER_TIME_STRETCHER |
299 std::cerr << "PhaseVocoderTimeStretcher::putInput returning" << std::endl; | 329 std::cerr << "PhaseVocoderTimeStretcher::putInput returning" << std::endl; |
300 #endif | 330 #endif |
331 | |
332 // std::cerr << "ratio: nominal: " << getRatio() << " actual: " | |
333 // << m_total2 << "/" << m_total1 << " = " << float(m_total2) / float(m_total1) << " ideal: " << m_ratio << std::endl; | |
301 } | 334 } |
302 | 335 |
303 size_t | 336 size_t |
304 PhaseVocoderTimeStretcher::getAvailableOutputSamples() const | 337 PhaseVocoderTimeStretcher::getAvailableOutputSamples() const |
305 { | 338 { |
383 } | 416 } |
384 | 417 |
385 bool isTransient = false; | 418 bool isTransient = false; |
386 | 419 |
387 if (count > m_wlen / 4.5 && //!!! | 420 if (count > m_wlen / 4.5 && //!!! |
388 count > m_prevTransientCount * 1.2) { | 421 count > m_prevTransientScore * 1.2) { |
389 isTransient = true; | 422 isTransient = true; |
390 std::cerr << "isTransient (count = " << count << ", prev = " << m_prevTransientCount << ")" << std::endl; | 423 std::cerr << "isTransient (count = " << count << ", prev = " << m_prevTransientScore << ")" << std::endl; |
391 } | 424 } |
392 | 425 |
393 m_prevTransientCount = count; | 426 m_prevTransientScore = count; |
394 | 427 |
395 return isTransient; | 428 return isTransient; |
396 } | 429 } |
397 | 430 |
398 void | 431 void |