annotate audio/TimeStretchWrapper.h @ 738:48001ed9143b audio-source-refactor

Introduce TimeStretchWrapper; some work towards making the AudioCallbackPlaySource not actually try to be an ApplicationPlaybackSource itself but only return one that is constructed from wrappers that it controls the lifespan of
author Chris Cannam
date Wed, 18 Mar 2020 12:51:41 +0000
parents
children 846970dbef17
rev   line source
Chris@738 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@738 2
Chris@738 3 /*
Chris@738 4 Sonic Visualiser
Chris@738 5 An audio file viewer and annotation editor.
Chris@738 6 Centre for Digital Music, Queen Mary, University of London.
Chris@738 7
Chris@738 8 This program is free software; you can redistribute it and/or
Chris@738 9 modify it under the terms of the GNU General Public License as
Chris@738 10 published by the Free Software Foundation; either version 2 of the
Chris@738 11 License, or (at your option) any later version. See the file
Chris@738 12 COPYING included with this distribution for more information.
Chris@738 13 */
Chris@738 14
Chris@738 15 #ifndef SV_TIME_STRETCH_WRAPPER_H
Chris@738 16 #define SV_TIME_STRETCH_WRAPPER_H
Chris@738 17
Chris@738 18 #include "bqaudioio/ApplicationPlaybackSource.h"
Chris@738 19
Chris@738 20 #include "base/BaseTypes.h"
Chris@738 21
Chris@738 22 #include <vector>
Chris@738 23 #include <mutex>
Chris@738 24
Chris@738 25 namespace RubberBand {
Chris@738 26 class RubberBandStretcher;
Chris@738 27 }
Chris@738 28
Chris@738 29 /**
Chris@738 30 * A breakfastquay::ApplicationPlaybackSource wrapper that implements
Chris@738 31 * time-stretching using Rubber Band. Note that the stretcher is
Chris@738 32 * bypassed entirely when a ratio of 1.0 is set; this means it's
Chris@738 33 * (almost) free to use one of these wrappers normally, but it also
Chris@738 34 * means you can't switch from 1.0 to another ratio (or back again)
Chris@738 35 * without some audible artifacts.
Chris@738 36 *
Chris@738 37 * This is real-time safe while the ratio is fixed, and may perform
Chris@738 38 * reallocations when the ratio changes.
Chris@738 39 */
Chris@738 40 class TimeStretchWrapper : public breakfastquay::ApplicationPlaybackSource
Chris@738 41 {
Chris@738 42 public:
Chris@738 43 /**
Chris@738 44 * Create a wrapper around the given ApplicationPlaybackSource,
Chris@738 45 * implementing another ApplicationPlaybackSource interface that
Chris@738 46 * draws from the same source data but with a time-stretcher
Chris@738 47 * optionally applied.
Chris@738 48 *
Chris@738 49 * The wrapper does not take ownership of the wrapped
Chris@738 50 * ApplicationPlaybackSource, whose lifespan must exceed that of
Chris@738 51 * this object.
Chris@738 52 */
Chris@738 53 TimeStretchWrapper(ApplicationPlaybackSource *source);
Chris@738 54 ~TimeStretchWrapper();
Chris@738 55
Chris@738 56 /**
Chris@738 57 * Set a time stretch factor, i.e. playback speed, where 1.0 is
Chris@738 58 * normal speed
Chris@738 59 */
Chris@738 60 void setTimeStretchRatio(double ratio);
Chris@738 61
Chris@738 62 /**
Chris@738 63 * Clear stretcher buffers.
Chris@738 64 */
Chris@738 65 void reset();
Chris@738 66
Chris@738 67 // These functions are passed through to the wrapped
Chris@738 68 // ApplicationPlaybackSource
Chris@738 69
Chris@738 70 std::string getClientName() const override;
Chris@738 71 int getApplicationSampleRate() const override;
Chris@738 72 int getApplicationChannelCount() const override;
Chris@738 73
Chris@738 74 void setSystemPlaybackBlockSize(int) override;
Chris@738 75 void setSystemPlaybackSampleRate(int) override;
Chris@738 76 void setSystemPlaybackChannelCount(int) override;
Chris@738 77 void setSystemPlaybackLatency(int) override;
Chris@738 78
Chris@738 79 void setOutputLevels(float peakLeft, float peakRight) override;
Chris@738 80 void audioProcessingOverload() override;
Chris@738 81
Chris@738 82 /**
Chris@738 83 * Request some samples from the wrapped
Chris@738 84 * ApplicationPlaybackSource, time-stretch if appropriate, and
Chris@738 85 * return them to the target
Chris@738 86 */
Chris@738 87 int getSourceSamples(float *const *samples, int nchannels, int nframes)
Chris@738 88 override;
Chris@738 89
Chris@738 90 private:
Chris@738 91 ApplicationPlaybackSource *m_source;
Chris@738 92 RubberBand::RubberBandStretcher *m_stretcher;
Chris@738 93 double m_timeRatio;
Chris@738 94 std::vector<std::vector<float>> m_inputs;
Chris@738 95 std::mutex m_mutex;
Chris@738 96 sv_frame_t m_stretcherInputSize;
Chris@738 97 int m_channelCount;
Chris@738 98 sv_samplerate_t m_sampleRate;
Chris@738 99
Chris@738 100 void checkStretcher(); // call without m_mutex held
Chris@738 101
Chris@738 102 TimeStretchWrapper(const TimeStretchWrapper &)=delete;
Chris@738 103 TimeStretchWrapper &operator=(const TimeStretchWrapper &)=delete;
Chris@738 104 };
Chris@738 105
Chris@738 106 #endif
Chris@738 107
Chris@738 108