Mercurial > hg > sonic-visualiser
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 |