comparison audioio/AudioCallbackPlaySource.h @ 43:3c5756fb6a68

* Move some things around to facilitate plundering libraries for other applications without needing to duplicate so much code. sv/osc -> data/osc sv/audioio -> audioio sv/transform -> plugin/transform sv/document -> document (will rename to framework in next commit)
author Chris Cannam
date Wed, 24 Oct 2007 16:34:31 +0000
parents
children eb596ef12041
comparison
equal deleted inserted replaced
42:0619006a1ee3 43:3c5756fb6a68
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 <QObject>
25 #include <QMutex>
26 #include <QWaitCondition>
27
28 #include "base/Thread.h"
29
30 #include <samplerate.h>
31
32 #include <set>
33 #include <map>
34
35 class Model;
36 class ViewManager;
37 class AudioGenerator;
38 class PlayParameters;
39 class PhaseVocoderTimeStretcher;
40 class RealTimePluginInstance;
41
42 /**
43 * AudioCallbackPlaySource manages audio data supply to callback-based
44 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer
45 * per channel, filled during playback by a non-realtime thread, and
46 * provides a method for a realtime thread to pick up the latest
47 * available sample data from these buffers.
48 */
49 class AudioCallbackPlaySource : public virtual QObject,
50 public AudioPlaySource
51 {
52 Q_OBJECT
53
54 public:
55 AudioCallbackPlaySource(ViewManager *);
56 virtual ~AudioCallbackPlaySource();
57
58 /**
59 * Add a data model to be played from. The source can mix
60 * playback from a number of sources including dense and sparse
61 * models. The models must match in sample rate, but they don't
62 * have to have identical numbers of channels.
63 */
64 virtual void addModel(Model *model);
65
66 /**
67 * Remove a model.
68 */
69 virtual void removeModel(Model *model);
70
71 /**
72 * Remove all models. (Silence will ensue.)
73 */
74 virtual void clearModels();
75
76 /**
77 * Start making data available in the ring buffers for playback,
78 * from the given frame. If playback is already under way, reseek
79 * to the given frame and continue.
80 */
81 virtual void play(size_t startFrame);
82
83 /**
84 * Stop playback and ensure that no more data is returned.
85 */
86 virtual void stop();
87
88 /**
89 * Return whether playback is currently supposed to be happening.
90 */
91 virtual bool isPlaying() const { return m_playing; }
92
93 /**
94 * Return the frame number that is currently expected to be coming
95 * out of the speakers. (i.e. compensating for playback latency.)
96 */
97 virtual size_t getCurrentPlayingFrame();
98
99 /**
100 * Return the frame at which playback is expected to end (if not looping).
101 */
102 virtual size_t getPlayEndFrame() { return m_lastModelEndFrame; }
103
104 /**
105 * Set the block size of the target audio device. This should
106 * be called by the target class.
107 */
108 void setTargetBlockSize(size_t);
109
110 /**
111 * Get the block size of the target audio device.
112 */
113 size_t getTargetBlockSize() const;
114
115 /**
116 * Set the playback latency of the target audio device, in frames
117 * at the target sample rate. This is the difference between the
118 * frame currently "leaving the speakers" and the last frame (or
119 * highest last frame across all channels) requested via
120 * getSamples(). The default is zero.
121 */
122 void setTargetPlayLatency(size_t);
123
124 /**
125 * Get the playback latency of the target audio device.
126 */
127 size_t getTargetPlayLatency() const;
128
129 /**
130 * Specify that the target audio device has a fixed sample rate
131 * (i.e. cannot accommodate arbitrary sample rates based on the
132 * source). If the target sets this to something other than the
133 * source sample rate, this class will resample automatically to
134 * fit.
135 */
136 void setTargetSampleRate(size_t);
137
138 /**
139 * Return the sample rate set by the target audio device (or the
140 * source sample rate if the target hasn't set one).
141 */
142 virtual size_t getTargetSampleRate() const;
143
144 /**
145 * Set the current output levels for metering (for call from the
146 * target)
147 */
148 void setOutputLevels(float left, float right);
149
150 /**
151 * Return the current (or thereabouts) output levels in the range
152 * 0.0 -> 1.0, for metering purposes.
153 */
154 virtual bool getOutputLevels(float &left, float &right);
155
156 /**
157 * Get the number of channels of audio that in the source models.
158 * This may safely be called from a realtime thread. Returns 0 if
159 * there is no source yet available.
160 */
161 size_t getSourceChannelCount() const;
162
163 /**
164 * Get the number of channels of audio that will be provided
165 * to the play target. This may be more than the source channel
166 * count: for example, a mono source will provide 2 channels
167 * after pan.
168 * This may safely be called from a realtime thread. Returns 0 if
169 * there is no source yet available.
170 */
171 size_t getTargetChannelCount() const;
172
173 /**
174 * Get the actual sample rate of the source material. This may
175 * safely be called from a realtime thread. Returns 0 if there is
176 * no source yet available.
177 */
178 virtual size_t getSourceSampleRate() const;
179
180 /**
181 * Get "count" samples (at the target sample rate) of the mixed
182 * audio data, in all channels. This may safely be called from a
183 * realtime thread.
184 */
185 size_t getSourceSamples(size_t count, float **buffer);
186
187 /**
188 * Set the time stretcher factor (i.e. playback speed). Also
189 * specify whether the time stretcher will be variable rate
190 * (sharpening transients), and whether time stretching will be
191 * carried out on data mixed down to mono for speed.
192 */
193 void setTimeStretch(float factor, bool sharpen, bool mono);
194
195 /**
196 * Set the resampler quality, 0 - 2 where 0 is fastest and 2 is
197 * highest quality.
198 */
199 void setResampleQuality(int q);
200
201 /**
202 * Set a single real-time plugin as a processing effect for
203 * auditioning during playback.
204 *
205 * The plugin must have been initialised with
206 * getTargetChannelCount() channels and a getTargetBlockSize()
207 * sample frame processing block size.
208 *
209 * This playback source takes ownership of the plugin, which will
210 * be deleted at some point after the following call to
211 * setAuditioningPlugin (depending on real-time constraints).
212 *
213 * Pass a null pointer to remove the current auditioning plugin,
214 * if any.
215 */
216 void setAuditioningPlugin(RealTimePluginInstance *plugin);
217
218 /**
219 * Specify that only the given set of models should be played.
220 */
221 void setSoloModelSet(std::set<Model *>s);
222
223 /**
224 * Specify that all models should be played as normal (if not
225 * muted).
226 */
227 void clearSoloModelSet();
228
229 signals:
230 void modelReplaced();
231
232 void playStatusChanged(bool isPlaying);
233
234 void sampleRateMismatch(size_t requested, size_t available, bool willResample);
235
236 void audioOverloadPluginDisabled();
237
238 public slots:
239 void audioProcessingOverload();
240
241 protected slots:
242 void selectionChanged();
243 void playLoopModeChanged();
244 void playSelectionModeChanged();
245 void playParametersChanged(PlayParameters *);
246 void preferenceChanged(PropertyContainer::PropertyName);
247 void modelChanged(size_t startFrame, size_t endFrame);
248
249 protected:
250 ViewManager *m_viewManager;
251 AudioGenerator *m_audioGenerator;
252
253 class RingBufferVector : public std::vector<RingBuffer<float> *> {
254 public:
255 virtual ~RingBufferVector() {
256 while (!empty()) {
257 delete *begin();
258 erase(begin());
259 }
260 }
261 };
262
263 std::set<Model *> m_models;
264 RingBufferVector *m_readBuffers;
265 RingBufferVector *m_writeBuffers;
266 size_t m_readBufferFill;
267 size_t m_writeBufferFill;
268 Scavenger<RingBufferVector> m_bufferScavenger;
269 size_t m_sourceChannelCount;
270 size_t m_blockSize;
271 size_t m_sourceSampleRate;
272 size_t m_targetSampleRate;
273 size_t m_playLatency;
274 bool m_playing;
275 bool m_exiting;
276 size_t m_lastModelEndFrame;
277 static const size_t m_ringBufferSize;
278 float m_outputLeft;
279 float m_outputRight;
280 RealTimePluginInstance *m_auditioningPlugin;
281 bool m_auditioningPluginBypassed;
282 Scavenger<RealTimePluginInstance> m_pluginScavenger;
283
284 RingBuffer<float> *getWriteRingBuffer(size_t c) {
285 if (m_writeBuffers && c < m_writeBuffers->size()) {
286 return (*m_writeBuffers)[c];
287 } else {
288 return 0;
289 }
290 }
291
292 RingBuffer<float> *getReadRingBuffer(size_t c) {
293 RingBufferVector *rb = m_readBuffers;
294 if (rb && c < rb->size()) {
295 return (*rb)[c];
296 } else {
297 return 0;
298 }
299 }
300
301 void clearRingBuffers(bool haveLock = false, size_t count = 0);
302 void unifyRingBuffers();
303
304 PhaseVocoderTimeStretcher *m_timeStretcher;
305 Scavenger<PhaseVocoderTimeStretcher> m_timeStretcherScavenger;
306
307 // Called from fill thread, m_playing true, mutex held
308 // Return true if work done
309 bool fillBuffers();
310
311 // Called from fillBuffers. Return the number of frames written,
312 // which will be count or fewer. Return in the frame argument the
313 // new buffered frame position (which may be earlier than the
314 // frame argument passed in, in the case of looping).
315 size_t mixModels(size_t &frame, size_t count, float **buffers);
316
317 // Called from getSourceSamples.
318 void applyAuditioningEffect(size_t count, float **buffers);
319
320 class FillThread : public Thread
321 {
322 public:
323 FillThread(AudioCallbackPlaySource &source) :
324 Thread(Thread::NonRTThread),
325 m_source(source) { }
326
327 virtual void run();
328
329 protected:
330 AudioCallbackPlaySource &m_source;
331 };
332
333 QMutex m_mutex;
334 QWaitCondition m_condition;
335 FillThread *m_fillThread;
336 SRC_STATE *m_converter;
337 SRC_STATE *m_crapConverter; // for use when playing very fast
338 int m_resampleQuality;
339 void initialiseConverter();
340 };
341
342 #endif
343
344