svapp  1.9
AudioCallbackPlaySource.h
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #ifndef _AUDIO_CALLBACK_PLAY_SOURCE_H_
00017 #define _AUDIO_CALLBACK_PLAY_SOURCE_H_
00018 
00019 #include "base/RingBuffer.h"
00020 #include "base/AudioPlaySource.h"
00021 #include "base/PropertyContainer.h"
00022 #include "base/Scavenger.h"
00023 
00024 #include <QObject>
00025 #include <QMutex>
00026 #include <QWaitCondition>
00027 
00028 #include "base/Thread.h"
00029 #include "base/RealTime.h"
00030 
00031 #include <samplerate.h>
00032 
00033 #include <set>
00034 #include <map>
00035 
00036 namespace RubberBand {
00037     class RubberBandStretcher;
00038 }
00039 
00040 class Model;
00041 class ViewManagerBase;
00042 class AudioGenerator;
00043 class PlayParameters;
00044 class RealTimePluginInstance;
00045 class AudioCallbackPlayTarget;
00046 
00054 class AudioCallbackPlaySource : public QObject,
00055                                 public AudioPlaySource
00056 {
00057     Q_OBJECT
00058 
00059 public:
00060     AudioCallbackPlaySource(ViewManagerBase *, QString clientName);
00061     virtual ~AudioCallbackPlaySource();
00062     
00069     virtual void addModel(Model *model);
00070 
00074     virtual void removeModel(Model *model);
00075 
00079     virtual void clearModels();
00080 
00086     virtual void play(int startFrame);
00087 
00091     virtual void stop();
00092 
00096     virtual bool isPlaying() const { return m_playing; }
00097 
00102     virtual int getCurrentPlayingFrame();
00103     
00108     virtual int getCurrentBufferedFrame();
00109 
00113     virtual int getPlayEndFrame() { return m_lastModelEndFrame; }
00114 
00119     void setTarget(AudioCallbackPlayTarget *, int blockSize);
00120 
00127     int getTargetBlockSize() const;
00128 
00136     void setTargetPlayLatency(int);
00137 
00141     int getTargetPlayLatency() const;
00142 
00150     void setTargetSampleRate(int);
00151 
00156     virtual int getTargetSampleRate() const;
00157 
00162     void setOutputLevels(float left, float right);
00163 
00168     virtual bool getOutputLevels(float &left, float &right);
00169 
00175     int getSourceChannelCount() const;
00176 
00185     int getTargetChannelCount() const;
00186 
00192     virtual int getSourceSampleRate() const;
00193 
00199     int getSourceSamples(int count, float **buffer);
00200 
00204     void setTimeStretch(float factor);
00205 
00210     void setResampleQuality(int q);
00211 
00227     void setAuditioningEffect(Auditionable *plugin);
00228 
00232     void setSoloModelSet(std::set<Model *>s);
00233 
00238     void clearSoloModelSet();
00239 
00240     QString getClientName() const { return m_clientName; }
00241 
00242 signals:
00243     void modelReplaced();
00244 
00245     void playStatusChanged(bool isPlaying);
00246 
00247     void sampleRateMismatch(int requested, int available, bool willResample);
00248 
00249     void audioOverloadPluginDisabled();
00250     void audioTimeStretchMultiChannelDisabled();
00251 
00252     void activity(QString);
00253 
00254 public slots:
00255     void audioProcessingOverload();
00256 
00257 protected slots:
00258     void selectionChanged();
00259     void playLoopModeChanged();
00260     void playSelectionModeChanged();
00261     void playParametersChanged(PlayParameters *);
00262     void preferenceChanged(PropertyContainer::PropertyName);
00263     void modelChangedWithin(int startFrame, int endFrame);
00264 
00265 protected:
00266     ViewManagerBase                  *m_viewManager;
00267     AudioGenerator                   *m_audioGenerator;
00268     QString                           m_clientName;
00269 
00270     class RingBufferVector : public std::vector<RingBuffer<float> *> {
00271     public:
00272         virtual ~RingBufferVector() {
00273             while (!empty()) {
00274                 delete *begin();
00275                 erase(begin());
00276             }
00277         }
00278     };
00279 
00280     std::set<Model *>                 m_models;
00281     RingBufferVector                 *m_readBuffers;
00282     RingBufferVector                 *m_writeBuffers;
00283     int                               m_readBufferFill;
00284     int                               m_writeBufferFill;
00285     Scavenger<RingBufferVector>       m_bufferScavenger;
00286     int                               m_sourceChannelCount;
00287     int                               m_blockSize;
00288     int                               m_sourceSampleRate;
00289     int                               m_targetSampleRate;
00290     int                               m_playLatency;
00291     AudioCallbackPlayTarget          *m_target;
00292     double                            m_lastRetrievalTimestamp;
00293     int                               m_lastRetrievedBlockSize;
00294     bool                              m_trustworthyTimestamps;
00295     int                               m_lastCurrentFrame;
00296     bool                              m_playing;
00297     bool                              m_exiting;
00298     int                               m_lastModelEndFrame;
00299     int                               m_ringBufferSize;
00300     float                             m_outputLeft;
00301     float                             m_outputRight;
00302     RealTimePluginInstance           *m_auditioningPlugin;
00303     bool                              m_auditioningPluginBypassed;
00304     Scavenger<RealTimePluginInstance> m_pluginScavenger;
00305     int                               m_playStartFrame;
00306     bool                              m_playStartFramePassed;
00307     RealTime                          m_playStartedAt;
00308 
00309     RingBuffer<float> *getWriteRingBuffer(int c) {
00310         if (m_writeBuffers && c < (int)m_writeBuffers->size()) {
00311             return (*m_writeBuffers)[c];
00312         } else {
00313             return 0;
00314         }
00315     }
00316 
00317     RingBuffer<float> *getReadRingBuffer(int c) {
00318         RingBufferVector *rb = m_readBuffers;
00319         if (rb && c < (int)rb->size()) {
00320             return (*rb)[c];
00321         } else {
00322             return 0;
00323         }
00324     }
00325 
00326     void clearRingBuffers(bool haveLock = false, int count = 0);
00327     void unifyRingBuffers();
00328 
00329     RubberBand::RubberBandStretcher *m_timeStretcher;
00330     RubberBand::RubberBandStretcher *m_monoStretcher;
00331     float m_stretchRatio;
00332     bool m_stretchMono;
00333     
00334     int  m_stretcherInputCount;
00335     float **m_stretcherInputs;
00336     int *m_stretcherInputSizes;
00337 
00338     // Called from fill thread, m_playing true, mutex held
00339     // Return true if work done
00340     bool fillBuffers();
00341     
00342     // Called from fillBuffers.  Return the number of frames written,
00343     // which will be count or fewer.  Return in the frame argument the
00344     // new buffered frame position (which may be earlier than the
00345     // frame argument passed in, in the case of looping).
00346     int mixModels(int &frame, int count, float **buffers);
00347 
00348     // Called from getSourceSamples.
00349     void applyAuditioningEffect(int count, float **buffers);
00350 
00351     // Ranges of current selections, if play selection is active
00352     std::vector<RealTime> m_rangeStarts;
00353     std::vector<RealTime> m_rangeDurations;
00354     void rebuildRangeLists();
00355 
00356     int getCurrentFrame(RealTime outputLatency);
00357 
00358     class FillThread : public Thread
00359     {
00360     public:
00361         FillThread(AudioCallbackPlaySource &source) :
00362             Thread(Thread::NonRTThread),
00363             m_source(source) { }
00364 
00365         virtual void run();
00366 
00367     protected:
00368         AudioCallbackPlaySource &m_source;
00369     };
00370 
00371     QMutex m_mutex;
00372     QWaitCondition m_condition;
00373     FillThread *m_fillThread;
00374     SRC_STATE *m_converter;
00375     SRC_STATE *m_crapConverter; // for use when playing very fast
00376     int m_resampleQuality;
00377     void initialiseConverter();
00378 };
00379 
00380 #endif
00381 
00382