comparison audioio/AudioCallbackPlaySource.h @ 0:cd5d7ff8ef38

* Reorganising code base. This revision will not compile.
author Chris Cannam
date Mon, 31 Jul 2006 12:03:45 +0000
parents
children ee967635c728
comparison
equal deleted inserted replaced
-1:000000000000 0:cd5d7ff8ef38
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.
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/Scavenger.h"
22
23 #include <QObject>
24 #include <QMutex>
25 #include <QWaitCondition>
26
27 #include "base/Thread.h"
28
29 #include <samplerate.h>
30
31 #include <set>
32 #include <map>
33
34 class Model;
35 class ViewManager;
36 class AudioGenerator;
37 class PlayParameters;
38 class IntegerTimeStretcher;
39
40 /**
41 * AudioCallbackPlaySource manages audio data supply to callback-based
42 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer
43 * per channel, filled during playback by a non-realtime thread, and
44 * provides a method for a realtime thread to pick up the latest
45 * available sample data from these buffers.
46 */
47 class AudioCallbackPlaySource : public virtual QObject,
48 public AudioPlaySource
49 {
50 Q_OBJECT
51
52 public:
53 AudioCallbackPlaySource(ViewManager *);
54 virtual ~AudioCallbackPlaySource();
55
56 /**
57 * Add a data model to be played from. The source can mix
58 * playback from a number of sources including dense and sparse
59 * models. The models must match in sample rate, but they don't
60 * have to have identical numbers of channels.
61 */
62 virtual void addModel(Model *model);
63
64 /**
65 * Remove a model.
66 */
67 virtual void removeModel(Model *model);
68
69 /**
70 * Remove all models. (Silence will ensue.)
71 */
72 virtual void clearModels();
73
74 /**
75 * Start making data available in the ring buffers for playback,
76 * from the given frame. If playback is already under way, reseek
77 * to the given frame and continue.
78 */
79 virtual void play(size_t startFrame);
80
81 /**
82 * Stop playback and ensure that no more data is returned.
83 */
84 virtual void stop();
85
86 /**
87 * Return whether playback is currently supposed to be happening.
88 */
89 virtual bool isPlaying() const { return m_playing; }
90
91 /**
92 * Return the frame number that is currently expected to be coming
93 * out of the speakers. (i.e. compensating for playback latency.)
94 */
95 virtual size_t getCurrentPlayingFrame();
96
97 /**
98 * Set the block size of the target audio device. This should
99 * be called by the target class.
100 */
101 void setTargetBlockSize(size_t);
102
103 /**
104 * Get the block size of the target audio device.
105 */
106 size_t getTargetBlockSize() const;
107
108 /**
109 * Set the playback latency of the target audio device, in frames
110 * at the target sample rate. This is the difference between the
111 * frame currently "leaving the speakers" and the last frame (or
112 * highest last frame across all channels) requested via
113 * getSamples(). The default is zero.
114 */
115 void setTargetPlayLatency(size_t);
116
117 /**
118 * Get the playback latency of the target audio device.
119 */
120 size_t getTargetPlayLatency() const;
121
122 /**
123 * Specify that the target audio device has a fixed sample rate
124 * (i.e. cannot accommodate arbitrary sample rates based on the
125 * source). If the target sets this to something other than the
126 * source sample rate, this class will resample automatically to
127 * fit.
128 */
129 void setTargetSampleRate(size_t);
130
131 /**
132 * Return the sample rate set by the target audio device (or the
133 * source sample rate if the target hasn't set one).
134 */
135 virtual size_t getTargetSampleRate() const;
136
137 /**
138 * Set the current output levels for metering (for call from the
139 * target)
140 */
141 void setOutputLevels(float left, float right);
142
143 /**
144 * Return the current (or thereabouts) output levels in the range
145 * 0.0 -> 1.0, for metering purposes.
146 */
147 virtual bool getOutputLevels(float &left, float &right);
148
149 /**
150 * Get the number of channels of audio that in the source models.
151 * This may safely be called from a realtime thread. Returns 0 if
152 * there is no source yet available.
153 */
154 size_t getSourceChannelCount() const;
155
156 /**
157 * Get the number of channels of audio that will be provided
158 * to the play target. This may be more than the source channel
159 * count: for example, a mono source will provide 2 channels
160 * after pan.
161 * This may safely be called from a realtime thread. Returns 0 if
162 * there is no source yet available.
163 */
164 size_t getTargetChannelCount() const;
165
166 /**
167 * Get the actual sample rate of the source material. This may
168 * safely be called from a realtime thread. Returns 0 if there is
169 * no source yet available.
170 */
171 size_t getSourceSampleRate() const;
172
173 /**
174 * Get "count" samples (at the target sample rate) of the mixed
175 * audio data, in all channels. This may safely be called from a
176 * realtime thread.
177 */
178 size_t getSourceSamples(size_t count, float **buffer);
179
180 void setSlowdownFactor(size_t factor);
181
182 signals:
183 void modelReplaced();
184
185 void playStatusChanged(bool isPlaying);
186
187 void sampleRateMismatch(size_t requested, size_t available, bool willResample);
188
189 protected slots:
190 void selectionChanged();
191 void playLoopModeChanged();
192 void playSelectionModeChanged();
193 void playParametersChanged(PlayParameters *);
194
195 protected:
196 ViewManager *m_viewManager;
197 AudioGenerator *m_audioGenerator;
198
199 class RingBufferVector : public std::vector<RingBuffer<float> *> {
200 public:
201 virtual ~RingBufferVector() {
202 while (!empty()) {
203 delete *begin();
204 erase(begin());
205 }
206 }
207 };
208
209 std::set<Model *> m_models;
210 RingBufferVector *m_readBuffers;
211 RingBufferVector *m_writeBuffers;
212 size_t m_readBufferFill;
213 size_t m_writeBufferFill;
214 Scavenger<RingBufferVector> m_bufferScavenger;
215 size_t m_sourceChannelCount;
216 size_t m_blockSize;
217 size_t m_sourceSampleRate;
218 size_t m_targetSampleRate;
219 size_t m_playLatency;
220 bool m_playing;
221 bool m_exiting;
222 size_t m_lastModelEndFrame;
223 static const size_t m_ringBufferSize;
224 float m_outputLeft;
225 float m_outputRight;
226
227 RingBuffer<float> *getWriteRingBuffer(size_t c) {
228 if (m_writeBuffers && c < m_writeBuffers->size()) {
229 return (*m_writeBuffers)[c];
230 } else {
231 return 0;
232 }
233 }
234
235 RingBuffer<float> *getReadRingBuffer(size_t c) {
236 RingBufferVector *rb = m_readBuffers;
237 if (rb && c < rb->size()) {
238 return (*rb)[c];
239 } else {
240 return 0;
241 }
242 }
243
244 void clearRingBuffers(bool haveLock = false, size_t count = 0);
245 void unifyRingBuffers();
246
247 class TimeStretcherData
248 {
249 public:
250 TimeStretcherData(size_t channels, size_t factor, size_t blockSize);
251 ~TimeStretcherData();
252
253 size_t getFactor() const { return m_factor; }
254 IntegerTimeStretcher *getStretcher(size_t channel);
255 float *getOutputBuffer(size_t channel);
256 float *getInputBuffer();
257
258 void run(size_t channel);
259
260 protected:
261 TimeStretcherData(const TimeStretcherData &); // not provided
262 TimeStretcherData &operator=(const TimeStretcherData &); // not provided
263
264 typedef std::pair<IntegerTimeStretcher *, float *> StretcherBuffer;
265 std::map<size_t, StretcherBuffer> m_stretcher;
266 float *m_stretchInputBuffer;
267 size_t m_factor;
268 size_t m_blockSize;
269 };
270
271 size_t m_slowdownCounter;
272 TimeStretcherData *m_timeStretcher;
273 Scavenger<TimeStretcherData> m_timeStretcherScavenger;
274
275 // Called from fill thread, m_playing true, mutex held
276 // Return true if work done
277 bool fillBuffers();
278
279 // Called from fillBuffers. Return the number of frames written,
280 // which will be count or fewer. Return in the frame argument the
281 // new buffered frame position (which may be earlier than the
282 // frame argument passed in, in the case of looping).
283 size_t mixModels(size_t &frame, size_t count, float **buffers);
284
285 class AudioCallbackPlaySourceFillThread : public Thread
286 {
287 public:
288 AudioCallbackPlaySourceFillThread(AudioCallbackPlaySource &source) :
289 Thread(Thread::NonRTThread),
290 m_source(source) { }
291
292 virtual void run();
293
294 protected:
295 AudioCallbackPlaySource &m_source;
296 };
297
298 QMutex m_mutex;
299 QWaitCondition m_condition;
300 AudioCallbackPlaySourceFillThread *m_fillThread;
301 SRC_STATE *m_converter;
302 };
303
304 #endif
305
306