comparison audioio/IntegerTimeStretcher.cpp @ 12:ee967635c728

* Some work on making the time stretcher squash as well as stretch
author Chris Cannam
date Tue, 12 Sep 2006 16:43:00 +0000
parents cd5d7ff8ef38
children 00ed645f4175
comparison
equal deleted inserted replaced
11:0dbd08e365ce 12:ee967635c728
18 #include <iostream> 18 #include <iostream>
19 #include <cassert> 19 #include <cassert>
20 20
21 //#define DEBUG_INTEGER_TIME_STRETCHER 1 21 //#define DEBUG_INTEGER_TIME_STRETCHER 1
22 22
23 IntegerTimeStretcher::IntegerTimeStretcher(size_t ratio, 23 IntegerTimeStretcher::IntegerTimeStretcher(float ratio,
24 size_t maxProcessInputBlockSize, 24 size_t maxProcessInputBlockSize,
25 size_t inputIncrement, 25 size_t inputIncrement,
26 size_t windowSize, 26 size_t windowSize,
27 WindowType windowType) : 27 WindowType windowType) :
28 m_ratio(ratio), 28 m_ratio(ratio),
29 m_n1(inputIncrement), 29 m_n1(inputIncrement),
30 m_n2(m_n1 * ratio), 30 m_n2(lrintf(m_n1 * ratio)),
31 m_wlen(std::max(windowSize, m_n2 * 2)), 31 m_wlen(std::max(windowSize, m_n2 * 2)),
32 m_inbuf(m_wlen), 32 m_inbuf(m_wlen),
33 m_outbuf(maxProcessInputBlockSize * ratio) 33 m_outbuf(maxProcessInputBlockSize * ratio + 1024) //!!!
34 { 34 {
35 m_window = new Window<float>(windowType, m_wlen), 35 m_window = new Window<float>(windowType, m_wlen),
36 36
37 m_time = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen); 37 m_time = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen);
38 m_freq = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen); 38 m_freq = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen);
39 m_dbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen); 39 m_dbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen);
40 m_mashbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen);
41 m_prevPhase = (float *)fftwf_malloc(sizeof(float) * m_wlen);
42 m_prevAdjustedPhase = (float *)fftwf_malloc(sizeof(float) * m_wlen);
40 43
41 m_plan = fftwf_plan_dft_1d(m_wlen, m_time, m_freq, FFTW_FORWARD, FFTW_ESTIMATE); 44 m_plan = fftwf_plan_dft_1d(m_wlen, m_time, m_freq, FFTW_FORWARD, FFTW_ESTIMATE);
42 m_iplan = fftwf_plan_dft_c2r_1d(m_wlen, m_freq, m_dbuf, FFTW_ESTIMATE); 45 m_iplan = fftwf_plan_dft_c2r_1d(m_wlen, m_freq, m_dbuf, FFTW_ESTIMATE);
43 46
44 m_mashbuf = new float[m_wlen];
45 for (int i = 0; i < m_wlen; ++i) { 47 for (int i = 0; i < m_wlen; ++i) {
46 m_mashbuf[i] = 0.0; 48 m_mashbuf[i] = 0.0;
49 m_prevPhase[i] = 0.0;
50 m_prevAdjustedPhase[i] = 0.0;
47 } 51 }
48 } 52 }
49 53
50 IntegerTimeStretcher::~IntegerTimeStretcher() 54 IntegerTimeStretcher::~IntegerTimeStretcher()
51 { 55 {
55 fftwf_destroy_plan(m_iplan); 59 fftwf_destroy_plan(m_iplan);
56 60
57 fftwf_free(m_time); 61 fftwf_free(m_time);
58 fftwf_free(m_freq); 62 fftwf_free(m_freq);
59 fftwf_free(m_dbuf); 63 fftwf_free(m_dbuf);
64 fftwf_free(m_mashbuf);
65 fftwf_free(m_prevPhase);
66 fftwf_free(m_prevAdjustedPhase);
60 67
61 delete m_window; 68 delete m_window;
62 delete m_mashbuf;
63 } 69 }
64 70
65 size_t 71 size_t
66 IntegerTimeStretcher::getProcessingLatency() const 72 IntegerTimeStretcher::getProcessingLatency() const
67 { 73 {
141 #ifdef DEBUG_INTEGER_TIME_STRETCHER 147 #ifdef DEBUG_INTEGER_TIME_STRETCHER
142 std::cerr << "loop ended: inbuf read space " << m_inbuf.getReadSpace() << ", outbuf write space " << m_outbuf.getWriteSpace() << std::endl; 148 std::cerr << "loop ended: inbuf read space " << m_inbuf.getReadSpace() << ", outbuf write space " << m_outbuf.getWriteSpace() << std::endl;
143 #endif 149 #endif
144 } 150 }
145 151
146 if (m_outbuf.getReadSpace() < samples * m_ratio) { 152 size_t toRead = lrintf(samples * m_ratio);
147 std::cerr << "WARNING: IntegerTimeStretcher::process: not enough data (yet?) (" << m_outbuf.getReadSpace() << " < " << (samples * m_ratio) << ")" << std::endl; 153
148 size_t fill = samples * m_ratio - m_outbuf.getReadSpace(); 154 if (m_outbuf.getReadSpace() < toRead) {
155 std::cerr << "WARNING: IntegerTimeStretcher::process: not enough data (yet?) (" << m_outbuf.getReadSpace() << " < " << toRead << ")" << std::endl;
156 size_t fill = toRead - m_outbuf.getReadSpace();
149 for (size_t i = 0; i < fill; ++i) { 157 for (size_t i = 0; i < fill; ++i) {
150 output[i] = 0.0; 158 output[i] = 0.0;
151 } 159 }
152 m_outbuf.read(output + fill, m_outbuf.getReadSpace()); 160 m_outbuf.read(output + fill, m_outbuf.getReadSpace());
153 } else { 161 } else {
154 #ifdef DEBUG_INTEGER_TIME_STRETCHER 162 #ifdef DEBUG_INTEGER_TIME_STRETCHER
155 std::cerr << "enough data - writing " << samples * m_ratio << " from outbuf" << std::endl; 163 std::cerr << "enough data - writing " << toRead << " from outbuf" << std::endl;
156 #endif 164 #endif
157 m_outbuf.read(output, samples * m_ratio); 165 m_outbuf.read(output, toRead);
158 } 166 }
159 167
160 #ifdef DEBUG_INTEGER_TIME_STRETCHER 168 #ifdef DEBUG_INTEGER_TIME_STRETCHER
161 std::cerr << "IntegerTimeStretcher::process returning" << std::endl; 169 std::cerr << "IntegerTimeStretcher::process returning" << std::endl;
162 #endif 170 #endif
192 for (i = 0; i < m_wlen; ++i) { 200 for (i = 0; i < m_wlen; ++i) {
193 201
194 float mag = sqrtf(m_freq[i][0] * m_freq[i][0] + 202 float mag = sqrtf(m_freq[i][0] * m_freq[i][0] +
195 m_freq[i][1] * m_freq[i][1]); 203 m_freq[i][1] * m_freq[i][1]);
196 204
197 float phase = atan2f(m_freq[i][1], m_freq[i][0]); 205 float phase = princargf(atan2f(m_freq[i][1], m_freq[i][0]));
206
207 float omega = (2 * M_PI * m_n1 * i) / m_wlen;
198 208
199 phase = phase * m_ratio; 209 float expectedPhase = m_prevPhase[i] + omega;
210
211 float phaseError = princargf(phase - expectedPhase);
212
213 float phaseIncrement = (omega + phaseError) / m_n1;
214
215 float adjustedPhase = m_prevAdjustedPhase[i] + m_n2 * phaseIncrement;
200 216
201 float real = mag * cosf(phase); 217 float real = mag * cosf(adjustedPhase);
202 float imag = mag * sinf(phase); 218 float imag = mag * sinf(adjustedPhase);
203 m_freq[i][0] = real; 219 m_freq[i][0] = real;
204 m_freq[i][1] = imag; 220 m_freq[i][1] = imag;
221
222 m_prevPhase[i] = phase;
223 m_prevAdjustedPhase[i] = adjustedPhase;
205 } 224 }
206 225
207 fftwf_execute(m_iplan); // m_freq -> in, inverse fft 226 fftwf_execute(m_iplan); // m_freq -> in, inverse fft
208 227
209 for (i = 0; i < m_wlen/2; ++i) { 228 for (i = 0; i < m_wlen/2; ++i) {