OpenShot Audio Library | OpenShotAudio 0.4.0
juce_AudioTransportSource.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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 ResamplingAudioSource* newResamplerSource = nullptr;
49 BufferingAudioSource* newBufferingSource = nullptr;
50 PositionableAudioSource* newPositionableSource = nullptr;
51 AudioSource* newMasterSource = nullptr;
52
53 std::unique_ptr<ResamplingAudioSource> oldResamplerSource (resamplerSource);
54 std::unique_ptr<BufferingAudioSource> oldBufferingSource (bufferingSource);
55 AudioSource* oldMasterSource = masterSource;
56
57 if (newSource != nullptr)
58 {
59 newPositionableSource = newSource;
60
61 if (readAheadSize > 0)
62 {
63 // If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
64 // for it to use!
65 jassert (readAheadThread != nullptr);
66
67 newPositionableSource = newBufferingSource
68 = new BufferingAudioSource (newPositionableSource, *readAheadThread,
69 false, readAheadSize, maxNumChannels);
70 }
71
72 newPositionableSource->setNextReadPosition (0);
73
74 if (sourceSampleRateToCorrectFor > 0)
75 newMasterSource = newResamplerSource
76 = new ResamplingAudioSource (newPositionableSource, false, maxNumChannels);
77 else
78 newMasterSource = newPositionableSource;
79
80 if (isPrepared)
81 {
82 if (newResamplerSource != nullptr && sourceSampleRateToCorrectFor > 0 && sampleRate > 0)
83 newResamplerSource->setResamplingRatio (sourceSampleRateToCorrectFor / sampleRate);
84
85 newMasterSource->prepareToPlay (blockSize, sampleRate);
86 }
87 }
88
89 {
90 const ScopedLock sl (callbackLock);
91
92 source = newSource;
93 resamplerSource = newResamplerSource;
94 bufferingSource = newBufferingSource;
95 masterSource = newMasterSource;
96 positionableSource = newPositionableSource;
97 readAheadBufferSize = readAheadSize;
98 sourceSampleRate = sourceSampleRateToCorrectFor;
99
100 playing = false;
101 }
102
103 if (oldMasterSource != nullptr)
104 oldMasterSource->releaseResources();
105}
106
108{
109 if ((! playing) && masterSource != nullptr)
110 {
111 {
112 const ScopedLock sl (callbackLock);
113 playing = true;
114 stopped = false;
115 }
116
118 }
119}
120
122{
123 if (playing)
124 {
125 playing = false;
126
127 int n = 500;
128 while (--n >= 0 && ! stopped)
129 Thread::sleep (2);
130
132 }
133}
134
135void AudioTransportSource::setPosition (double newPosition)
136{
137 if (sampleRate > 0.0)
138 setNextReadPosition ((int64) (newPosition * sampleRate));
139}
140
142{
143 if (sampleRate > 0.0)
144 return (double) getNextReadPosition() / sampleRate;
145
146 return 0.0;
147}
148
150{
151 if (sampleRate > 0.0)
152 return (double) getTotalLength() / sampleRate;
153
154 return 0.0;
155}
156
158{
159 return positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
160 && ! positionableSource->isLooping();
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}
176
178{
179 const ScopedLock sl (callbackLock);
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 isPrepared = true;
228}
229
230void AudioTransportSource::releaseMasterResources()
231{
232 const ScopedLock sl (callbackLock);
233
234 if (masterSource != nullptr)
235 masterSource->releaseResources();
236
237 isPrepared = false;
238}
239
241{
242 releaseMasterResources();
243}
244
246{
247 const ScopedLock sl (callbackLock);
248
249 if (masterSource != nullptr && ! stopped)
250 {
251 masterSource->getNextAudioBlock (info);
252
253 if (! playing)
254 {
255 // just stopped playing, so fade out the last block..
256 for (int i = info.buffer->getNumChannels(); --i >= 0;)
257 info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f);
258
259 if (info.numSamples > 256)
260 info.buffer->clear (info.startSample + 256, info.numSamples - 256);
261 }
262
263 if (hasStreamFinished())
264 {
265 playing = false;
267 }
268
269 stopped = ! playing;
270
271 for (int i = info.buffer->getNumChannels(); --i >= 0;)
272 info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
273 }
274 else
275 {
277 stopped = true;
278 }
279
280 lastGain = gain;
281}
282
283} // namespace juce
int getNumChannels() const noexcept
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
virtual void releaseResources()=0
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
int64 getNextReadPosition() const override
void getNextAudioBlock(const AudioSourceChannelInfo &) override
void setPosition(double newPosition)
void setGain(float newGain) noexcept
void setSource(PositionableAudioSource *newSource, int readAheadBufferSize=0, TimeSliceThread *readAheadThread=nullptr, double sourceSampleRateToCorrectFor=0.0, int maxNumChannels=2)
void setNextReadPosition(int64 newPosition) override
virtual bool isLooping() const =0
virtual int64 getNextReadPosition() const =0
virtual int64 getTotalLength() const =0
virtual void setNextReadPosition(int64 newPosition)=0
void setResamplingRatio(double samplesInPerOutputSample)
static void JUCE_CALLTYPE sleep(int milliseconds)
AudioBuffer< float > * buffer