Chris@738: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@738: Chris@738: /* Chris@738: Sonic Visualiser Chris@738: An audio file viewer and annotation editor. Chris@738: Centre for Digital Music, Queen Mary, University of London. Chris@738: Chris@738: This program is free software; you can redistribute it and/or Chris@738: modify it under the terms of the GNU General Public License as Chris@738: published by the Free Software Foundation; either version 2 of the Chris@738: License, or (at your option) any later version. See the file Chris@738: COPYING included with this distribution for more information. Chris@738: */ Chris@738: Chris@738: #ifndef SV_TIME_STRETCH_WRAPPER_H Chris@738: #define SV_TIME_STRETCH_WRAPPER_H Chris@738: Chris@738: #include "bqaudioio/ApplicationPlaybackSource.h" Chris@738: Chris@738: #include "base/BaseTypes.h" Chris@738: Chris@738: #include Chris@738: #include Chris@738: Chris@738: namespace RubberBand { Chris@738: class RubberBandStretcher; Chris@738: } Chris@738: Chris@738: /** Chris@738: * A breakfastquay::ApplicationPlaybackSource wrapper that implements Chris@738: * time-stretching using Rubber Band. Note that the stretcher is Chris@738: * bypassed entirely when a ratio of 1.0 is set; this means it's Chris@738: * (almost) free to use one of these wrappers normally, but it also Chris@738: * means you can't switch from 1.0 to another ratio (or back again) Chris@738: * without some audible artifacts. Chris@738: * Chris@738: * This is real-time safe while the ratio is fixed, and may perform Chris@738: * reallocations when the ratio changes. Chris@738: */ Chris@738: class TimeStretchWrapper : public breakfastquay::ApplicationPlaybackSource Chris@738: { Chris@738: public: Chris@738: /** Chris@738: * Create a wrapper around the given ApplicationPlaybackSource, Chris@738: * implementing another ApplicationPlaybackSource interface that Chris@738: * draws from the same source data but with a time-stretcher Chris@738: * optionally applied. Chris@738: * Chris@738: * The wrapper does not take ownership of the wrapped Chris@738: * ApplicationPlaybackSource, whose lifespan must exceed that of Chris@738: * this object. Chris@738: */ Chris@738: TimeStretchWrapper(ApplicationPlaybackSource *source); Chris@738: ~TimeStretchWrapper(); Chris@738: Chris@738: /** Chris@738: * Set a time stretch factor, i.e. playback speed, where 1.0 is Chris@738: * normal speed Chris@738: */ Chris@738: void setTimeStretchRatio(double ratio); Chris@738: Chris@738: /** Chris@738: * Clear stretcher buffers. Chris@738: */ Chris@738: void reset(); Chris@738: Chris@738: // These functions are passed through to the wrapped Chris@738: // ApplicationPlaybackSource Chris@738: Chris@738: std::string getClientName() const override; Chris@738: int getApplicationSampleRate() const override; Chris@738: int getApplicationChannelCount() const override; Chris@738: Chris@738: void setSystemPlaybackBlockSize(int) override; Chris@738: void setSystemPlaybackSampleRate(int) override; Chris@738: void setSystemPlaybackChannelCount(int) override; Chris@738: void setSystemPlaybackLatency(int) override; Chris@738: Chris@738: void setOutputLevels(float peakLeft, float peakRight) override; Chris@738: void audioProcessingOverload() override; Chris@738: Chris@738: /** Chris@738: * Request some samples from the wrapped Chris@738: * ApplicationPlaybackSource, time-stretch if appropriate, and Chris@738: * return them to the target Chris@738: */ Chris@738: int getSourceSamples(float *const *samples, int nchannels, int nframes) Chris@738: override; Chris@738: Chris@738: private: Chris@738: ApplicationPlaybackSource *m_source; Chris@738: RubberBand::RubberBandStretcher *m_stretcher; Chris@738: double m_timeRatio; Chris@738: std::vector> m_inputs; Chris@738: std::mutex m_mutex; Chris@740: int m_stretcherInputSize; Chris@738: int m_channelCount; Chris@738: sv_samplerate_t m_sampleRate; Chris@738: Chris@738: void checkStretcher(); // call without m_mutex held Chris@738: Chris@738: TimeStretchWrapper(const TimeStretchWrapper &)=delete; Chris@738: TimeStretchWrapper &operator=(const TimeStretchWrapper &)=delete; Chris@738: }; Chris@738: Chris@738: #endif Chris@738: Chris@738: