OpenShot Library | OpenShotAudio  0.2.2
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 
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  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  playing = false;
129 
130  int n = 500;
131  while (--n >= 0 && ! stopped)
132  Thread::sleep (2);
133 
135  }
136 }
137 
138 void AudioTransportSource::setPosition (double newPosition)
139 {
140  if (sampleRate > 0.0)
141  setNextReadPosition ((int64) (newPosition * sampleRate));
142 }
143 
145 {
146  if (sampleRate > 0.0)
147  return (double) getNextReadPosition() / sampleRate;
148 
149  return 0.0;
150 }
151 
153 {
154  if (sampleRate > 0.0)
155  return (double) getTotalLength() / sampleRate;
156 
157  return 0.0;
158 }
159 
161 {
162  if (positionableSource != nullptr)
163  {
164  if (sampleRate > 0 && sourceSampleRate > 0)
165  newPosition = (int64) ((double) newPosition * sourceSampleRate / sampleRate);
166 
167  positionableSource->setNextReadPosition (newPosition);
168 
169  if (resamplerSource != nullptr)
170  resamplerSource->flushBuffers();
171 
172  inputStreamEOF = false;
173  }
174 }
175 
177 {
178  if (positionableSource != nullptr)
179  {
180  const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
181  return (int64) ((double) positionableSource->getNextReadPosition() * ratio);
182  }
183 
184  return 0;
185 }
186 
188 {
189  const ScopedLock sl (callbackLock);
190 
191  if (positionableSource != nullptr)
192  {
193  const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
194  return (int64) ((double) positionableSource->getTotalLength() * ratio);
195  }
196 
197  return 0;
198 }
199 
201 {
202  const ScopedLock sl (callbackLock);
203  return positionableSource != nullptr && positionableSource->isLooping();
204 }
205 
206 void AudioTransportSource::setGain (const float newGain) noexcept
207 {
208  gain = newGain;
209 }
210 
211 void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate)
212 {
213  const ScopedLock sl (callbackLock);
214 
215  sampleRate = newSampleRate;
216  blockSize = samplesPerBlockExpected;
217 
218  if (masterSource != nullptr)
219  masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate);
220 
221  if (resamplerSource != nullptr && sourceSampleRate > 0)
222  resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
223 
224  inputStreamEOF = false;
225  isPrepared = true;
226 }
227 
228 void AudioTransportSource::releaseMasterResources()
229 {
230  const ScopedLock sl (callbackLock);
231 
232  if (masterSource != nullptr)
233  masterSource->releaseResources();
234 
235  isPrepared = false;
236 }
237 
239 {
240  releaseMasterResources();
241 }
242 
244 {
245  const ScopedLock sl (callbackLock);
246 
247  if (masterSource != nullptr && ! stopped)
248  {
249  masterSource->getNextAudioBlock (info);
250 
251  if (! playing)
252  {
253  // just stopped playing, so fade out the last block..
254  for (int i = info.buffer->getNumChannels(); --i >= 0;)
255  info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f);
256 
257  if (info.numSamples > 256)
258  info.buffer->clear (info.startSample + 256, info.numSamples - 256);
259  }
260 
261  if (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
262  && ! positionableSource->isLooping())
263  {
264  playing = false;
265  inputStreamEOF = true;
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
void clearActiveBufferRegion() const
Convenient method to clear the buffer if the source is not producing any data.
void setGain(float newGain) noexcept
Changes the gain to apply to the output.
double getCurrentPosition() const
Returns the position that the next data block will be read from This is a time in seconds...
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
Called repeatedly to fetch subsequent blocks of audio data.
int numSamples
The number of samples in the buffer which the callback is expected to fill with data.
~AudioTransportSource() override
Destructor.
int64 getTotalLength() const override
Implements the PositionableAudioSource method.
virtual void releaseResources()=0
Allows the source to release anything it no longer needs after playback has stopped.
virtual int64 getTotalLength() const =0
Returns the total length of the stream (in samples).
virtual int64 getNextReadPosition() const =0
Returns the position from which the next block will be returned.
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Implementation of the AudioSource method.
void start()
Starts playing (if a source has been selected).
A type of AudioSource that takes an input source and changes its sample rate.
void releaseResources() override
Implementation of the AudioSource method.
void flushBuffers()
Clears any buffers and filters that the resampler is using.
Base class for objects that can produce a continuous stream of audio.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
void setNextReadPosition(int64 newPosition) override
Implements the PositionableAudioSource method.
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
Tells the source to prepare for playing.
bool isLooping() const override
Implements the PositionableAudioSource method.
virtual void setNextReadPosition(int64 newPosition)=0
Tells the stream to move to a new position.
void setPosition(double newPosition)
Changes the current playback position in the source stream.
An AudioSource which takes another source as input, and buffers it using a thread.
A thread that keeps a list of clients, and calls each one in turn, giving them all a chance to run so...
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.
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
int startSample
The first sample in the buffer from which the callback is expected to write data. ...
virtual bool isLooping() const =0
Returns true if this source is actually playing in a loop.
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners. ...
A type of AudioSource which can be repositioned.
AudioTransportSource()
Creates an AudioTransportSource.
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Implementation of the AudioSource method.
AudioBuffer< float > * buffer
The destination buffer to fill with audio data.
double getLengthInSeconds() const
Returns the stream&#39;s length in seconds.
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...
Used by AudioSource::getNextAudioBlock().
int64 getNextReadPosition() const override
Implements the PositionableAudioSource method.
Automatically locks and unlocks a mutex object.
void clear() noexcept
Clears all the samples in all channels.