comparison audioio/AudioCallbackPlaySource.h @ 91:9fc4b256c283

* PortAudio driver: do not specify frames per buffer, let PA decide * Remove old non-RubberBand time stretcher -- it doesn't work with varying buffer sizes such as the PA driver may now be using * Rewrite getCurrentPlayingFrame for greater correctness when using long buffer sizes (interpolating according to audio stream timestamp) * Several changes to make the timestretch management RT safe(r)
author Chris Cannam
date Fri, 08 Feb 2008 17:51:15 +0000
parents ae2627ac7db2
children 737b373246b5
comparison
equal deleted inserted replaced
90:db267a315058 91:9fc4b256c283
30 #include <samplerate.h> 30 #include <samplerate.h>
31 31
32 #include <set> 32 #include <set>
33 #include <map> 33 #include <map>
34 34
35 #ifdef HAVE_RUBBERBAND 35 namespace RubberBand {
36 #include <rubberband/RubberBandStretcher.h> 36 class RubberBandStretcher;
37 #else 37 }
38 class PhaseVocoderTimeStretcher;
39 #endif
40 38
41 class Model; 39 class Model;
42 class ViewManager; 40 class ViewManager;
43 class AudioGenerator; 41 class AudioGenerator;
44 class PlayParameters; 42 class PlayParameters;
45 class RealTimePluginInstance; 43 class RealTimePluginInstance;
44 class AudioCallbackPlayTarget;
46 45
47 /** 46 /**
48 * AudioCallbackPlaySource manages audio data supply to callback-based 47 * AudioCallbackPlaySource manages audio data supply to callback-based
49 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer 48 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer
50 * per channel, filled during playback by a non-realtime thread, and 49 * per channel, filled during playback by a non-realtime thread, and
105 * Return the frame at which playback is expected to end (if not looping). 104 * Return the frame at which playback is expected to end (if not looping).
106 */ 105 */
107 virtual size_t getPlayEndFrame() { return m_lastModelEndFrame; } 106 virtual size_t getPlayEndFrame() { return m_lastModelEndFrame; }
108 107
109 /** 108 /**
110 * Set the block size of the target audio device. This should 109 * Set the target and the block size of the target audio device.
111 * be called by the target class. 110 * This should be called by the target class.
112 */ 111 */
113 void setTargetBlockSize(size_t); 112 void setTarget(AudioCallbackPlayTarget *, size_t blockSize);
114 113
115 /** 114 /**
116 * Get the block size of the target audio device. 115 * Get the block size of the target audio device. This may be an
116 * estimate or upper bound, if the target has a variable block
117 * size; the source should behave itself even if this value turns
118 * out to be inaccurate.
117 */ 119 */
118 size_t getTargetBlockSize() const; 120 size_t getTargetBlockSize() const;
119 121
120 /** 122 /**
121 * Set the playback latency of the target audio device, in frames 123 * Set the playback latency of the target audio device, in frames
188 * realtime thread. 190 * realtime thread.
189 */ 191 */
190 size_t getSourceSamples(size_t count, float **buffer); 192 size_t getSourceSamples(size_t count, float **buffer);
191 193
192 /** 194 /**
193 * Set the time stretcher factor (i.e. playback speed). Also 195 * Set the time stretcher factor (i.e. playback speed).
194 * specify whether the time stretcher will be variable rate 196 */
195 * (sharpening transients), and whether time stretching will be 197 void setTimeStretch(float factor);
196 * carried out on data mixed down to mono for speed.
197 */
198 void setTimeStretch(float factor, bool sharpen, bool mono);
199 198
200 /** 199 /**
201 * Set the resampler quality, 0 - 2 where 0 is fastest and 2 is 200 * Set the resampler quality, 0 - 2 where 0 is fastest and 2 is
202 * highest quality. 201 * highest quality.
203 */ 202 */
277 size_t m_sourceChannelCount; 276 size_t m_sourceChannelCount;
278 size_t m_blockSize; 277 size_t m_blockSize;
279 size_t m_sourceSampleRate; 278 size_t m_sourceSampleRate;
280 size_t m_targetSampleRate; 279 size_t m_targetSampleRate;
281 size_t m_playLatency; 280 size_t m_playLatency;
281 AudioCallbackPlayTarget *m_target;
282 double m_lastRetrievalTimestamp;
283 size_t m_lastRetrievedBlockSize;
282 bool m_playing; 284 bool m_playing;
283 bool m_exiting; 285 bool m_exiting;
284 size_t m_lastModelEndFrame; 286 size_t m_lastModelEndFrame;
285 static const size_t m_ringBufferSize; 287 static const size_t m_ringBufferSize;
286 float m_outputLeft; 288 float m_outputLeft;
307 } 309 }
308 310
309 void clearRingBuffers(bool haveLock = false, size_t count = 0); 311 void clearRingBuffers(bool haveLock = false, size_t count = 0);
310 void unifyRingBuffers(); 312 void unifyRingBuffers();
311 313
312 #ifdef HAVE_RUBBERBAND
313 RubberBand::RubberBandStretcher *m_timeStretcher; 314 RubberBand::RubberBandStretcher *m_timeStretcher;
314 QMutex m_timeStretchRatioMutex; 315 float m_stretchRatio;
315 #else 316
316 PhaseVocoderTimeStretcher *m_timeStretcher; 317 size_t m_stretcherInputCount;
317 Scavenger<PhaseVocoderTimeStretcher> m_timeStretcherScavenger; 318 float **m_stretcherInputs;
318 #endif 319 size_t *m_stretcherInputSizes;
319 320
320 // Called from fill thread, m_playing true, mutex held 321 // Called from fill thread, m_playing true, mutex held
321 // Return true if work done 322 // Return true if work done
322 bool fillBuffers(); 323 bool fillBuffers();
323 324