OpenShot Library | libopenshot-audio 0.2.0
juce_AudioTransportSource.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
27{
28}
29
31{
32 setSource (nullptr);
33 releaseMasterResources();
34}
35
37 int readAheadSize, TimeSliceThread* readAheadThread,
38 double sourceSampleRateToCorrectFor, int maxNumChannels)
39{
40 if (source == newSource)
41 {
42 if (source == nullptr)
43 return;
44
45 setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
46 }
47
48 readAheadBufferSize = readAheadSize;
49 sourceSampleRate = sourceSampleRateToCorrectFor;
50
51 ResamplingAudioSource* newResamplerSource = nullptr;
52 BufferingAudioSource* newBufferingSource = nullptr;
53 PositionableAudioSource* newPositionableSource = nullptr;
54 AudioSource* newMasterSource = nullptr;
55
56 std::unique_ptr<ResamplingAudioSource> oldResamplerSource (resamplerSource);
57 std::unique_ptr<BufferingAudioSource> oldBufferingSource (bufferingSource);
58 AudioSource* oldMasterSource = masterSource;
59
60 if (newSource != nullptr)
61 {
62 newPositionableSource = newSource;
63
64 if (readAheadSize > 0)
65 {
66 // If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
67 // for it to use!
68 jassert (readAheadThread != nullptr);
69
70 newPositionableSource = newBufferingSource
71 = new BufferingAudioSource (newPositionableSource, *readAheadThread,
72 false, readAheadSize, maxNumChannels);
73 }
74
75 newPositionableSource->setNextReadPosition (0);
76
77 if (sourceSampleRateToCorrectFor > 0)
78 newMasterSource = newResamplerSource
79 = new ResamplingAudioSource (newPositionableSource, false, maxNumChannels);
80 else
81 newMasterSource = newPositionableSource;
82
83 if (isPrepared)
84 {
85 if (newResamplerSource != nullptr && sourceSampleRate > 0 && sampleRate > 0)
86 newResamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
87
88 newMasterSource->prepareToPlay (blockSize, sampleRate);
89 }
90 }
91
92 {
93 const ScopedLock sl (callbackLock);
94
95 source = newSource;
96 resamplerSource = newResamplerSource;
97 bufferingSource = newBufferingSource;
98 masterSource = newMasterSource;
99 positionableSource = newPositionableSource;
100
101 inputStreamEOF = false;
102 playing = false;
103 }
104
105 if (oldMasterSource != nullptr)
106 oldMasterSource->releaseResources();
107}
108
110{
111 if ((! playing) && masterSource != nullptr)
112 {
113 {
114 const ScopedLock sl (callbackLock);
115 playing = true;
116 stopped = false;
117 inputStreamEOF = false;
118 }
119
121 }
122}
123
125{
126 if (playing)
127 {
128 {
129 const ScopedLock sl (callbackLock);
130 playing = false;
131 }
132
133 int n = 500;
134 while (--n >= 0 && ! stopped)
135 Thread::sleep (2);
136
138 }
139}
140
141void AudioTransportSource::setPosition (double newPosition)
142{
143 if (sampleRate > 0.0)
144 setNextReadPosition ((int64) (newPosition * sampleRate));
145}
146
148{
149 if (sampleRate > 0.0)
150 return (double) getNextReadPosition() / sampleRate;
151
152 return 0.0;
153}
154
156{
157 if (sampleRate > 0.0)
158 return (double) getTotalLength() / sampleRate;
159
160 return 0.0;
161}
162
164{
165 if (positionableSource != nullptr)
166 {
167 if (sampleRate > 0 && sourceSampleRate > 0)
168 newPosition = (int64) ((double) newPosition * sourceSampleRate / sampleRate);
169
170 positionableSource->setNextReadPosition (newPosition);
171
172 if (resamplerSource != nullptr)
173 resamplerSource->flushBuffers();
174
175 inputStreamEOF = false;
176 }
177}
178
180{
181 if (positionableSource != nullptr)
182 {
183 const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
184 return (int64) ((double) positionableSource->getNextReadPosition() * ratio);
185 }
186
187 return 0;
188}
189
191{
192 const ScopedLock sl (callbackLock);
193
194 if (positionableSource != nullptr)
195 {
196 const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
197 return (int64) ((double) positionableSource->getTotalLength() * ratio);
198 }
199
200 return 0;
201}
202
204{
205 const ScopedLock sl (callbackLock);
206 return positionableSource != nullptr && positionableSource->isLooping();
207}
208
209void AudioTransportSource::setGain (const float newGain) noexcept
210{
211 gain = newGain;
212}
213
214void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate)
215{
216 const ScopedLock sl (callbackLock);
217
218 sampleRate = newSampleRate;
219 blockSize = samplesPerBlockExpected;
220
221 if (masterSource != nullptr)
222 masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate);
223
224 if (resamplerSource != nullptr && sourceSampleRate > 0)
225 resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
226
227 inputStreamEOF = false;
228 isPrepared = true;
229}
230
231void AudioTransportSource::releaseMasterResources()
232{
233 const ScopedLock sl (callbackLock);
234
235 if (masterSource != nullptr)
236 masterSource->releaseResources();
237
238 isPrepared = false;
239}
240
242{
243 releaseMasterResources();
244}
245
247{
248 const ScopedLock sl (callbackLock);
249
250 if (masterSource != nullptr && ! stopped)
251 {
252 masterSource->getNextAudioBlock (info);
253
254 if (! playing)
255 {
256 // just stopped playing, so fade out the last block..
257 for (int i = info.buffer->getNumChannels(); --i >= 0;)
258 info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f);
259
260 if (info.numSamples > 256)
261 info.buffer->clear (info.startSample + 256, info.numSamples - 256);
262 }
263
264 if (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
265 && ! positionableSource->isLooping())
266 {
267 playing = false;
268 inputStreamEOF = true;
270 }
271
272 stopped = ! playing;
273
274 for (int i = info.buffer->getNumChannels(); --i >= 0;)
275 info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
276 }
277 else
278 {
280 stopped = true;
281 }
282
283 lastGain = gain;
284}
285
286} // namespace juce
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
void clear() noexcept
Clears all the samples in all channels.
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
Base class for objects that can produce a continuous stream of audio.
virtual void releaseResources()=0
Allows the source to release anything it no longer needs after playback has stopped.
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
Tells the source to prepare for playing.
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
Called repeatedly to fetch subsequent blocks of audio data.
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Implementation of the AudioSource method.
int64 getNextReadPosition() const override
Implements the PositionableAudioSource method.
double getCurrentPosition() const
Returns the position that the next data block will be read from This is a time in seconds.
void releaseResources() override
Implementation of the AudioSource method.
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Implementation of the AudioSource method.
int64 getTotalLength() const override
Implements the PositionableAudioSource method.
~AudioTransportSource() override
Destructor.
void setPosition(double newPosition)
Changes the current playback position in the source stream.
double getLengthInSeconds() const
Returns the stream's length in seconds.
void setGain(float newGain) noexcept
Changes the gain to apply to the output.
void setSource(PositionableAudioSource *newSource, int readAheadBufferSize=0, TimeSliceThread *readAheadThread=nullptr, double sourceSampleRateToCorrectFor=0.0, int maxNumChannels=2)
Sets the reader that is being used as the input source.
bool isLooping() const override
Implements the PositionableAudioSource method.
AudioTransportSource()
Creates an AudioTransportSource.
void start()
Starts playing (if a source has been selected).
void setNextReadPosition(int64 newPosition) override
Implements the PositionableAudioSource method.
An AudioSource which takes another source as input, and buffers it using a thread.
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Automatically locks and unlocks a mutex object.
A type of AudioSource which can be repositioned.
virtual bool isLooping() const =0
Returns true if this source is actually playing in a loop.
virtual int64 getNextReadPosition() const =0
Returns the position from which the next block will be returned.
virtual int64 getTotalLength() const =0
Returns the total length of the stream (in samples).
virtual void setNextReadPosition(int64 newPosition)=0
Tells the stream to move to a new position.
A type of AudioSource that takes an input source and changes its sample rate.
void flushBuffers()
Clears any buffers and filters that the resampler is using.
void setResamplingRatio(double samplesInPerOutputSample)
Changes the resampling ratio.
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
A thread that keeps a list of clients, and calls each one in turn, giving them all a chance to run so...
Used by AudioSource::getNextAudioBlock().
int numSamples
The number of samples in the buffer which the callback is expected to fill with data.
void clearActiveBufferRegion() const
Convenient method to clear the buffer if the source is not producing any data.
AudioBuffer< float > * buffer
The destination buffer to fill with audio data.
int startSample
The first sample in the buffer from which the callback is expected to write data.