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