comparison audio/AudioCallbackPlaySource.h @ 468:56acd9368532 bqaudioio

Initial work toward switching to bqaudioio library (so as to get I/O, not just O)
author Chris Cannam
date Tue, 04 Aug 2015 13:27:42 +0100
parents audioio/AudioCallbackPlaySource.h@72c662fe7ea3
children 0d725dd7f99c
comparison
equal deleted inserted replaced
466:45054b36ddbf 468:56acd9368532
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam and QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #ifndef _AUDIO_CALLBACK_PLAY_SOURCE_H_
17 #define _AUDIO_CALLBACK_PLAY_SOURCE_H_
18
19 #include "base/RingBuffer.h"
20 #include "base/AudioPlaySource.h"
21 #include "base/PropertyContainer.h"
22 #include "base/Scavenger.h"
23
24 #include <bqaudioio/ApplicationPlaybackSource.h>
25
26 #include <QObject>
27 #include <QMutex>
28 #include <QWaitCondition>
29
30 #include "base/Thread.h"
31 #include "base/RealTime.h"
32
33 #include <samplerate.h>
34
35 #include <set>
36 #include <map>
37
38 namespace RubberBand {
39 class RubberBandStretcher;
40 }
41
42 class Model;
43 class ViewManagerBase;
44 class AudioGenerator;
45 class PlayParameters;
46 class RealTimePluginInstance;
47 class AudioCallbackPlayTarget;
48
49 /**
50 * AudioCallbackPlaySource manages audio data supply to callback-based
51 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer
52 * per channel, filled during playback by a non-realtime thread, and
53 * provides a method for a realtime thread to pick up the latest
54 * available sample data from these buffers.
55 */
56 class AudioCallbackPlaySource : public QObject,
57 public AudioPlaySource,
58 public breakfastquay::ApplicationPlaybackSource
59 {
60 Q_OBJECT
61
62 public:
63 AudioCallbackPlaySource(ViewManagerBase *, QString clientName);
64 virtual ~AudioCallbackPlaySource();
65
66 /**
67 * Add a data model to be played from. The source can mix
68 * playback from a number of sources including dense and sparse
69 * models. The models must match in sample rate, but they don't
70 * have to have identical numbers of channels.
71 */
72 virtual void addModel(Model *model);
73
74 /**
75 * Remove a model.
76 */
77 virtual void removeModel(Model *model);
78
79 /**
80 * Remove all models. (Silence will ensue.)
81 */
82 virtual void clearModels();
83
84 /**
85 * Start making data available in the ring buffers for playback,
86 * from the given frame. If playback is already under way, reseek
87 * to the given frame and continue.
88 */
89 virtual void play(sv_frame_t startFrame);
90
91 /**
92 * Stop playback and ensure that no more data is returned.
93 */
94 virtual void stop();
95
96 /**
97 * Return whether playback is currently supposed to be happening.
98 */
99 virtual bool isPlaying() const { return m_playing; }
100
101 /**
102 * Return the frame number that is currently expected to be coming
103 * out of the speakers. (i.e. compensating for playback latency.)
104 */
105 virtual sv_frame_t getCurrentPlayingFrame();
106
107 /**
108 * Return the last frame that would come out of the speakers if we
109 * stopped playback right now.
110 */
111 virtual sv_frame_t getCurrentBufferedFrame();
112
113 /**
114 * Return the frame at which playback is expected to end (if not looping).
115 */
116 virtual sv_frame_t getPlayEndFrame() { return m_lastModelEndFrame; }
117
118 /**
119 * Set the playback target. This should be called by the target
120 * class.
121 */
122 virtual void setSystemPlaybackTarget(breakfastquay::SystemPlaybackTarget *);
123
124 /**
125 * Set the block size of the target audio device. This should be
126 * called by the target class.
127 */
128 virtual void setSystemPlaybackBlockSize(int blockSize);
129
130 /**
131 * Get the block size of the target audio device. This may be an
132 * estimate or upper bound, if the target has a variable block
133 * size; the source should behave itself even if this value turns
134 * out to be inaccurate.
135 */
136 int getTargetBlockSize() const;
137
138 /**
139 * Set the playback latency of the target audio device, in frames
140 * at the target sample rate. This is the difference between the
141 * frame currently "leaving the speakers" and the last frame (or
142 * highest last frame across all channels) requested via
143 * getSamples(). The default is zero.
144 */
145 void setSystemPlaybackLatency(int);
146
147 /**
148 * Get the playback latency of the target audio device.
149 */
150 sv_frame_t getTargetPlayLatency() const;
151
152 /**
153 * Specify that the target audio device has a fixed sample rate
154 * (i.e. cannot accommodate arbitrary sample rates based on the
155 * source). If the target sets this to something other than the
156 * source sample rate, this class will resample automatically to
157 * fit.
158 */
159 void setSystemPlaybackSampleRate(int);
160
161 /**
162 * Return the sample rate set by the target audio device (or the
163 * source sample rate if the target hasn't set one).
164 */
165 virtual sv_samplerate_t getTargetSampleRate() const;
166
167 /**
168 * Set the current output levels for metering (for call from the
169 * target)
170 */
171 void setOutputLevels(float left, float right);
172
173 /**
174 * Return the current (or thereabouts) output levels in the range
175 * 0.0 -> 1.0, for metering purposes.
176 */
177 virtual bool getOutputLevels(float &left, float &right);
178
179 /**
180 * Get the number of channels of audio that in the source models.
181 * This may safely be called from a realtime thread. Returns 0 if
182 * there is no source yet available.
183 */
184 int getSourceChannelCount() const;
185
186 /**
187 * Get the number of channels of audio that will be provided
188 * to the play target. This may be more than the source channel
189 * count: for example, a mono source will provide 2 channels
190 * after pan.
191 * This may safely be called from a realtime thread. Returns 0 if
192 * there is no source yet available.
193 */
194 int getTargetChannelCount() const;
195
196 /**
197 * ApplicationPlaybackSource equivalent of the above.
198 */
199 virtual int getApplicationChannelCount() const {
200 return getTargetChannelCount();
201 }
202
203 /**
204 * Get the actual sample rate of the source material. This may
205 * safely be called from a realtime thread. Returns 0 if there is
206 * no source yet available.
207 */
208 virtual sv_samplerate_t getSourceSampleRate() const;
209
210 /**
211 * ApplicationPlaybackSource equivalent of the above.
212 */
213 virtual int getApplicationSampleRate() const {
214 return int(round(getSourceSampleRate()));
215 }
216
217 /**
218 * Get "count" samples (at the target sample rate) of the mixed
219 * audio data, in all channels. This may safely be called from a
220 * realtime thread.
221 */
222 virtual void getSourceSamples(int count, float **buffer);
223
224 /**
225 * Set the time stretcher factor (i.e. playback speed).
226 */
227 void setTimeStretch(double factor);
228
229 /**
230 * Set the resampler quality, 0 - 2 where 0 is fastest and 2 is
231 * highest quality.
232 */
233 void setResampleQuality(int q);
234
235 /**
236 * Set a single real-time plugin as a processing effect for
237 * auditioning during playback.
238 *
239 * The plugin must have been initialised with
240 * getTargetChannelCount() channels and a getTargetBlockSize()
241 * sample frame processing block size.
242 *
243 * This playback source takes ownership of the plugin, which will
244 * be deleted at some point after the following call to
245 * setAuditioningEffect (depending on real-time constraints).
246 *
247 * Pass a null pointer to remove the current auditioning plugin,
248 * if any.
249 */
250 void setAuditioningEffect(Auditionable *plugin);
251
252 /**
253 * Specify that only the given set of models should be played.
254 */
255 void setSoloModelSet(std::set<Model *>s);
256
257 /**
258 * Specify that all models should be played as normal (if not
259 * muted).
260 */
261 void clearSoloModelSet();
262
263 std::string getClientName() const { return m_clientName; }
264
265 signals:
266 void modelReplaced();
267
268 void playStatusChanged(bool isPlaying);
269
270 void sampleRateMismatch(sv_samplerate_t requested,
271 sv_samplerate_t available,
272 bool willResample);
273
274 void audioOverloadPluginDisabled();
275 void audioTimeStretchMultiChannelDisabled();
276
277 void activity(QString);
278
279 public slots:
280 void audioProcessingOverload();
281
282 protected slots:
283 void selectionChanged();
284 void playLoopModeChanged();
285 void playSelectionModeChanged();
286 void playParametersChanged(PlayParameters *);
287 void preferenceChanged(PropertyContainer::PropertyName);
288 void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame);
289
290 protected:
291 ViewManagerBase *m_viewManager;
292 AudioGenerator *m_audioGenerator;
293 std::string m_clientName;
294
295 class RingBufferVector : public std::vector<RingBuffer<float> *> {
296 public:
297 virtual ~RingBufferVector() {
298 while (!empty()) {
299 delete *begin();
300 erase(begin());
301 }
302 }
303 };
304
305 std::set<Model *> m_models;
306 RingBufferVector *m_readBuffers;
307 RingBufferVector *m_writeBuffers;
308 sv_frame_t m_readBufferFill;
309 sv_frame_t m_writeBufferFill;
310 Scavenger<RingBufferVector> m_bufferScavenger;
311 int m_sourceChannelCount;
312 sv_frame_t m_blockSize;
313 sv_samplerate_t m_sourceSampleRate;
314 sv_samplerate_t m_targetSampleRate;
315 sv_frame_t m_playLatency;
316 breakfastquay::SystemPlaybackTarget *m_target;
317 double m_lastRetrievalTimestamp;
318 sv_frame_t m_lastRetrievedBlockSize;
319 bool m_trustworthyTimestamps;
320 sv_frame_t m_lastCurrentFrame;
321 bool m_playing;
322 bool m_exiting;
323 sv_frame_t m_lastModelEndFrame;
324 int m_ringBufferSize;
325 float m_outputLeft;
326 float m_outputRight;
327 RealTimePluginInstance *m_auditioningPlugin;
328 bool m_auditioningPluginBypassed;
329 Scavenger<RealTimePluginInstance> m_pluginScavenger;
330 sv_frame_t m_playStartFrame;
331 bool m_playStartFramePassed;
332 RealTime m_playStartedAt;
333
334 RingBuffer<float> *getWriteRingBuffer(int c) {
335 if (m_writeBuffers && c < (int)m_writeBuffers->size()) {
336 return (*m_writeBuffers)[c];
337 } else {
338 return 0;
339 }
340 }
341
342 RingBuffer<float> *getReadRingBuffer(int c) {
343 RingBufferVector *rb = m_readBuffers;
344 if (rb && c < (int)rb->size()) {
345 return (*rb)[c];
346 } else {
347 return 0;
348 }
349 }
350
351 void clearRingBuffers(bool haveLock = false, int count = 0);
352 void unifyRingBuffers();
353
354 RubberBand::RubberBandStretcher *m_timeStretcher;
355 RubberBand::RubberBandStretcher *m_monoStretcher;
356 double m_stretchRatio;
357 bool m_stretchMono;
358
359 int m_stretcherInputCount;
360 float **m_stretcherInputs;
361 sv_frame_t *m_stretcherInputSizes;
362
363 // Called from fill thread, m_playing true, mutex held
364 // Return true if work done
365 bool fillBuffers();
366
367 // Called from fillBuffers. Return the number of frames written,
368 // which will be count or fewer. Return in the frame argument the
369 // new buffered frame position (which may be earlier than the
370 // frame argument passed in, in the case of looping).
371 sv_frame_t mixModels(sv_frame_t &frame, sv_frame_t count, float **buffers);
372
373 // Called from getSourceSamples.
374 void applyAuditioningEffect(sv_frame_t count, float **buffers);
375
376 // Ranges of current selections, if play selection is active
377 std::vector<RealTime> m_rangeStarts;
378 std::vector<RealTime> m_rangeDurations;
379 void rebuildRangeLists();
380
381 sv_frame_t getCurrentFrame(RealTime outputLatency);
382
383 class FillThread : public Thread
384 {
385 public:
386 FillThread(AudioCallbackPlaySource &source) :
387 Thread(Thread::NonRTThread),
388 m_source(source) { }
389
390 virtual void run();
391
392 protected:
393 AudioCallbackPlaySource &m_source;
394 };
395
396 QMutex m_mutex;
397 QWaitCondition m_condition;
398 FillThread *m_fillThread;
399 SRC_STATE *m_converter;
400 SRC_STATE *m_crapConverter; // for use when playing very fast
401 int m_resampleQuality;
402 void initialiseConverter();
403 };
404
405 #endif
406
407