OpenShot Audio Library | OpenShotAudio  0.6.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 
23 namespace 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 
135 void 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 
209 void AudioTransportSource::setGain (const float newGain) noexcept
210 {
211  gain = newGain;
212 }
213 
214 void 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 
230 void 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