annotate audioio/AudioCallbackPlaySource.h @ 451:dc1a360f2b69

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