Mercurial > hg > svapp
comparison audioio/AudioCallbackPlaySource.h @ 0:db6fcbd4405c
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | df5923e33d01 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:db6fcbd4405c |
---|---|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 A waveform viewer and audio annotation editor. | |
5 Chris Cannam, Queen Mary University of London, 2005 | |
6 | |
7 This is experimental software. Not for distribution. | |
8 */ | |
9 | |
10 #ifndef _AUDIO_CALLBACK_PLAY_SOURCE_H_ | |
11 #define _AUDIO_CALLBACK_PLAY_SOURCE_H_ | |
12 | |
13 #include "base/RingBuffer.h" | |
14 #include "base/AudioPlaySource.h" | |
15 #include "base/Scavenger.h" | |
16 | |
17 #include <QObject> | |
18 #include <QMutex> | |
19 #include <QWaitCondition> | |
20 #include <QThread> | |
21 | |
22 #include <samplerate.h> | |
23 | |
24 #include <set> | |
25 #include <map> | |
26 | |
27 class Model; | |
28 class ViewManager; | |
29 class AudioGenerator; | |
30 class IntegerTimeStretcher; | |
31 | |
32 /** | |
33 * AudioCallbackPlaySource manages audio data supply to callback-based | |
34 * audio APIs such as JACK or CoreAudio. It maintains one ring buffer | |
35 * per channel, filled during playback by a non-realtime thread, and | |
36 * provides a method for a realtime thread to pick up the latest | |
37 * available sample data from these buffers. | |
38 */ | |
39 class AudioCallbackPlaySource : public virtual QObject, | |
40 public AudioPlaySource | |
41 { | |
42 Q_OBJECT | |
43 | |
44 public: | |
45 AudioCallbackPlaySource(ViewManager *); | |
46 virtual ~AudioCallbackPlaySource(); | |
47 | |
48 /** | |
49 * Add a data model to be played from. The source can mix | |
50 * playback from a number of sources including dense and sparse | |
51 * models. The models must match in sample rate, but they don't | |
52 * have to have identical numbers of channels. | |
53 */ | |
54 virtual void addModel(Model *model); | |
55 | |
56 /** | |
57 * Remove a model. | |
58 */ | |
59 virtual void removeModel(Model *model); | |
60 | |
61 /** | |
62 * Remove all models. (Silence will ensue.) | |
63 */ | |
64 virtual void clearModels(); | |
65 | |
66 /** | |
67 * Start making data available in the ring buffers for playback, | |
68 * from the given frame. If playback is already under way, reseek | |
69 * to the given frame and continue. | |
70 */ | |
71 virtual void play(size_t startFrame); | |
72 | |
73 /** | |
74 * Stop playback and ensure that no more data is returned. | |
75 */ | |
76 virtual void stop(); | |
77 | |
78 /** | |
79 * Return whether playback is currently supposed to be happening. | |
80 */ | |
81 virtual bool isPlaying() const { return m_playing; } | |
82 | |
83 /** | |
84 * Return the frame number that is currently expected to be coming | |
85 * out of the speakers. (i.e. compensating for playback latency.) | |
86 */ | |
87 virtual size_t getCurrentPlayingFrame(); | |
88 | |
89 /** | |
90 * Set the block size of the target audio device. This should | |
91 * be called by the target class. | |
92 */ | |
93 void setTargetBlockSize(size_t); | |
94 | |
95 /** | |
96 * Get the block size of the target audio device. | |
97 */ | |
98 size_t getTargetBlockSize() const; | |
99 | |
100 /** | |
101 * Set the playback latency of the target audio device, in frames | |
102 * at the target sample rate. This is the difference between the | |
103 * frame currently "leaving the speakers" and the last frame (or | |
104 * highest last frame across all channels) requested via | |
105 * getSamples(). The default is zero. | |
106 */ | |
107 void setTargetPlayLatency(size_t); | |
108 | |
109 /** | |
110 * Get the playback latency of the target audio device. | |
111 */ | |
112 size_t getTargetPlayLatency() const; | |
113 | |
114 /** | |
115 * Specify that the target audio device has a fixed sample rate | |
116 * (i.e. cannot accommodate arbitrary sample rates based on the | |
117 * source). If the target sets this to something other than the | |
118 * source sample rate, this class will resample automatically to | |
119 * fit. | |
120 */ | |
121 void setTargetSampleRate(size_t); | |
122 | |
123 /** | |
124 * Return the sample rate set by the target audio device (or the | |
125 * source sample rate if the target hasn't set one). | |
126 */ | |
127 size_t getTargetSampleRate() const; | |
128 | |
129 /** | |
130 * Set the current output levels for metering (for call from the | |
131 * target) | |
132 */ | |
133 void setOutputLevels(float left, float right); | |
134 | |
135 /** | |
136 * Return the current (or thereabouts) output levels in the range | |
137 * 0.0 -> 1.0, for metering purposes. | |
138 */ | |
139 virtual bool getOutputLevels(float &left, float &right); | |
140 | |
141 /** | |
142 * Get the number of channels of audio that will be available. | |
143 * This may safely be called from a realtime thread. Returns 0 if | |
144 * there is no source yet available. | |
145 */ | |
146 size_t getSourceChannelCount() const; | |
147 | |
148 /** | |
149 * Get the actual sample rate of the source material. This may | |
150 * safely be called from a realtime thread. Returns 0 if there is | |
151 * no source yet available. | |
152 */ | |
153 size_t getSourceSampleRate() const; | |
154 | |
155 /** | |
156 * Get "count" samples (at the target sample rate) of the mixed | |
157 * audio data, in all channels. This may safely be called from a | |
158 * realtime thread. | |
159 */ | |
160 size_t getSourceSamples(size_t count, float **buffer); | |
161 | |
162 void setSlowdownFactor(size_t factor); | |
163 | |
164 signals: | |
165 void modelReplaced(); | |
166 | |
167 /// Just a warning | |
168 void sampleRateMismatch(size_t requested, size_t available); | |
169 | |
170 protected: | |
171 ViewManager *m_viewManager; | |
172 AudioGenerator *m_audioGenerator; | |
173 | |
174 std::set<Model *> m_models; | |
175 std::vector<RingBuffer<float> *> m_buffers; | |
176 size_t m_bufferCount; | |
177 size_t m_blockSize; | |
178 size_t m_sourceSampleRate; | |
179 size_t m_targetSampleRate; | |
180 size_t m_playLatency; | |
181 bool m_playing; | |
182 bool m_exiting; | |
183 size_t m_bufferedToFrame; | |
184 static const size_t m_ringBufferSize; | |
185 float m_outputLeft; | |
186 float m_outputRight; | |
187 | |
188 RingBuffer<float> &getRingBuffer(size_t c) { | |
189 return *m_buffers[c]; | |
190 } | |
191 | |
192 class TimeStretcherData | |
193 { | |
194 public: | |
195 TimeStretcherData(size_t channels, size_t factor, size_t blockSize); | |
196 ~TimeStretcherData(); | |
197 | |
198 size_t getFactor() const { return m_factor; } | |
199 IntegerTimeStretcher *getStretcher(size_t channel); | |
200 double *getOutputBuffer(size_t channel); | |
201 double *getInputBuffer(); | |
202 | |
203 void run(size_t channel); | |
204 | |
205 protected: | |
206 TimeStretcherData(const TimeStretcherData &); // not provided | |
207 TimeStretcherData &operator=(const TimeStretcherData &); // not provided | |
208 | |
209 typedef std::pair<IntegerTimeStretcher *, double *> StretcherBuffer; | |
210 std::map<size_t, StretcherBuffer> m_stretcher; | |
211 double *m_stretchInputBuffer; | |
212 size_t m_factor; | |
213 size_t m_blockSize; | |
214 }; | |
215 | |
216 size_t m_slowdownCounter; | |
217 TimeStretcherData *m_timeStretcher; | |
218 Scavenger<TimeStretcherData> m_timeStretcherScavenger; | |
219 | |
220 void fillBuffers(); // Called from fill thread, m_playing true, mutex held | |
221 | |
222 class AudioCallbackPlaySourceFillThread : public QThread | |
223 { | |
224 public: | |
225 AudioCallbackPlaySourceFillThread(AudioCallbackPlaySource &source) : | |
226 m_source(source) { } | |
227 | |
228 virtual void run(); | |
229 | |
230 protected: | |
231 AudioCallbackPlaySource &m_source; | |
232 }; | |
233 | |
234 QMutex m_mutex; | |
235 QWaitCondition m_condition; | |
236 AudioCallbackPlaySourceFillThread *m_fillThread; | |
237 SRC_STATE *m_converter; | |
238 }; | |
239 | |
240 #endif | |
241 | |
242 |