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 
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  {
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 
141 void 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 
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  inputStreamEOF = false;
228  isPrepared = true;
229 }
230 
231 void 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
juce::AudioTransportSource::AudioTransportSource
AudioTransportSource()
Creates an AudioTransportSource.
Definition: juce_AudioTransportSource.cpp:26
juce::AudioTransportSource::releaseResources
void releaseResources() override
Implementation of the AudioSource method.
Definition: juce_AudioTransportSource.cpp:241
juce::AudioSourceChannelInfo::clearActiveBufferRegion
void clearActiveBufferRegion() const
Convenient method to clear the buffer if the source is not producing any data.
Definition: juce_AudioSource.h:88
juce::PositionableAudioSource::getTotalLength
virtual int64 getTotalLength() const =0
Returns the total length of the stream (in samples).
juce::AudioTransportSource::setPosition
void setPosition(double newPosition)
Changes the current playback position in the source stream.
Definition: juce_AudioTransportSource.cpp:141
juce::AudioSource
Base class for objects that can produce a continuous stream of audio.
Definition: juce_AudioSource.h:113
juce::AudioTransportSource::setSource
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.
Definition: juce_AudioTransportSource.cpp:36
juce::PositionableAudioSource
A type of AudioSource which can be repositioned.
Definition: juce_PositionableAudioSource.h:42
juce::ResamplingAudioSource::flushBuffers
void flushBuffers()
Clears any buffers and filters that the resampler is using.
Definition: juce_ResamplingAudioSource.cpp:68
juce::ResamplingAudioSource
A type of AudioSource that takes an input source and changes its sample rate.
Definition: juce_ResamplingAudioSource.h:38
juce::AudioTransportSource::getNextReadPosition
int64 getNextReadPosition() const override
Implements the PositionableAudioSource method.
Definition: juce_AudioTransportSource.cpp:179
juce::AudioTransportSource::getCurrentPosition
double getCurrentPosition() const
Returns the position that the next data block will be read from This is a time in seconds.
Definition: juce_AudioTransportSource.cpp:147
juce::AudioSource::getNextAudioBlock
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
Called repeatedly to fetch subsequent blocks of audio data.
juce::AudioSource::prepareToPlay
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
Tells the source to prepare for playing.
juce::AudioTransportSource::getTotalLength
int64 getTotalLength() const override
Implements the PositionableAudioSource method.
Definition: juce_AudioTransportSource.cpp:190
juce::AudioSourceChannelInfo::startSample
int startSample
The first sample in the buffer from which the callback is expected to write data.
Definition: juce_AudioSource.h:81
juce::AudioSourceChannelInfo::numSamples
int numSamples
The number of samples in the buffer which the callback is expected to fill with data.
Definition: juce_AudioSource.h:85
juce::PositionableAudioSource::getNextReadPosition
virtual int64 getNextReadPosition() const =0
Returns the position from which the next block will be returned.
juce::PositionableAudioSource::setNextReadPosition
virtual void setNextReadPosition(int64 newPosition)=0
Tells the stream to move to a new position.
juce::TimeSliceThread
A thread that keeps a list of clients, and calls each one in turn, giving them all a chance to run so...
Definition: juce_TimeSliceThread.h:86
juce::AudioBuffer::getNumChannels
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
Definition: juce_AudioSampleBuffer.h:237
juce::AudioBuffer::applyGainRamp
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
Definition: juce_AudioSampleBuffer.h:648
juce::ChangeBroadcaster::sendChangeMessage
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Definition: juce_ChangeBroadcaster.cpp:62
juce::AudioSourceChannelInfo::buffer
AudioBuffer< float > * buffer
The destination buffer to fill with audio data.
Definition: juce_AudioSource.h:77
juce::AudioSourceChannelInfo
Used by AudioSource::getNextAudioBlock().
Definition: juce_AudioSource.h:36
juce::GenericScopedLock
Automatically locks and unlocks a mutex object.
Definition: juce_ScopedLock.h:58
juce::AudioTransportSource::~AudioTransportSource
~AudioTransportSource() override
Destructor.
Definition: juce_AudioTransportSource.cpp:30
juce::AudioTransportSource::prepareToPlay
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Implementation of the AudioSource method.
Definition: juce_AudioTransportSource.cpp:214
juce::PositionableAudioSource::isLooping
virtual bool isLooping() const =0
Returns true if this source is actually playing in a loop.
juce::AudioTransportSource::setNextReadPosition
void setNextReadPosition(int64 newPosition) override
Implements the PositionableAudioSource method.
Definition: juce_AudioTransportSource.cpp:163
juce::AudioTransportSource::start
void start()
Starts playing (if a source has been selected).
Definition: juce_AudioTransportSource.cpp:109
juce::BufferingAudioSource
An AudioSource which takes another source as input, and buffers it using a thread.
Definition: juce_BufferingAudioSource.h:42
juce::AudioSource::releaseResources
virtual void releaseResources()=0
Allows the source to release anything it no longer needs after playback has stopped.
juce::AudioTransportSource::getNextAudioBlock
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Implementation of the AudioSource method.
Definition: juce_AudioTransportSource.cpp:246
juce::AudioTransportSource::setGain
void setGain(float newGain) noexcept
Changes the gain to apply to the output.
Definition: juce_AudioTransportSource.cpp:209
juce::AudioTransportSource::stop
void stop()
Stops playing.
Definition: juce_AudioTransportSource.cpp:124
juce::AudioBuffer::clear
void clear() noexcept
Clears all the samples in all channels.
Definition: juce_AudioSampleBuffer.h:510
juce::AudioTransportSource::getLengthInSeconds
double getLengthInSeconds() const
Returns the stream's length in seconds.
Definition: juce_AudioTransportSource.cpp:155
juce::AudioTransportSource::isLooping
bool isLooping() const override
Implements the PositionableAudioSource method.
Definition: juce_AudioTransportSource.cpp:203
juce::Thread::sleep
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
juce::ResamplingAudioSource::setResamplingRatio
void setResamplingRatio(double samplesInPerOutputSample)
Changes the resampling ratio.
Definition: juce_ResamplingAudioSource.cpp:43