Loading...
Searching...
No Matches
juce_AudioTransportSource.cpp
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioTransportSource::AudioTransportSource()
{
}
AudioTransportSource::~AudioTransportSource()
{
setSource (nullptr);
releaseMasterResources();
}
void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
int readAheadSize, TimeSliceThread* readAheadThread,
double sourceSampleRateToCorrectFor, int maxNumChannels)
{
if (source == newSource)
{
if (source == nullptr)
return;
setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
}
ResamplingAudioSource* newResamplerSource = nullptr;
BufferingAudioSource* newBufferingSource = nullptr;
PositionableAudioSource* newPositionableSource = nullptr;
AudioSource* newMasterSource = nullptr;
std::unique_ptr<ResamplingAudioSource> oldResamplerSource (resamplerSource);
std::unique_ptr<BufferingAudioSource> oldBufferingSource (bufferingSource);
AudioSource* oldMasterSource = masterSource;
if (newSource != nullptr)
{
newPositionableSource = newSource;
if (readAheadSize > 0)
{
// If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
// for it to use!
jassert (readAheadThread != nullptr);
newPositionableSource = newBufferingSource
= new BufferingAudioSource (newPositionableSource, *readAheadThread,
false, readAheadSize, maxNumChannels);
}
newPositionableSource->setNextReadPosition (0);
if (sourceSampleRateToCorrectFor > 0)
newMasterSource = newResamplerSource
= new ResamplingAudioSource (newPositionableSource, false, maxNumChannels);
else
newMasterSource = newPositionableSource;
if (isPrepared)
{
if (newResamplerSource != nullptr && sourceSampleRateToCorrectFor > 0 && sampleRate > 0)
newResamplerSource->setResamplingRatio (sourceSampleRateToCorrectFor / sampleRate);
newMasterSource->prepareToPlay (blockSize, sampleRate);
}
}
{
const ScopedLock sl (callbackLock);
source = newSource;
resamplerSource = newResamplerSource;
bufferingSource = newBufferingSource;
masterSource = newMasterSource;
positionableSource = newPositionableSource;
readAheadBufferSize = readAheadSize;
sourceSampleRate = sourceSampleRateToCorrectFor;
playing = false;
}
if (oldMasterSource != nullptr)
oldMasterSource->releaseResources();
}
void AudioTransportSource::start()
{
if ((! playing) && masterSource != nullptr)
{
{
const ScopedLock sl (callbackLock);
playing = true;
stopped = false;
}
sendChangeMessage();
}
}
void AudioTransportSource::stop()
{
if (playing)
{
playing = false;
int n = 500;
while (--n >= 0 && ! stopped)
Thread::sleep (2);
sendChangeMessage();
}
}
void AudioTransportSource::setPosition (double newPosition)
{
if (sampleRate > 0.0)
setNextReadPosition ((int64) (newPosition * sampleRate));
}
double AudioTransportSource::getCurrentPosition() const
{
if (sampleRate > 0.0)
return (double) getNextReadPosition() / sampleRate;
return 0.0;
}
double AudioTransportSource::getLengthInSeconds() const
{
if (sampleRate > 0.0)
return (double) getTotalLength() / sampleRate;
return 0.0;
}
bool AudioTransportSource::hasStreamFinished() const noexcept
{
return positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
&& ! positionableSource->isLooping();
}
void AudioTransportSource::setNextReadPosition (int64 newPosition)
{
if (positionableSource != nullptr)
{
if (sampleRate > 0 && sourceSampleRate > 0)
newPosition = (int64) ((double) newPosition * sourceSampleRate / sampleRate);
positionableSource->setNextReadPosition (newPosition);
if (resamplerSource != nullptr)
resamplerSource->flushBuffers();
}
}
int64 AudioTransportSource::getNextReadPosition() const
{
const ScopedLock sl (callbackLock);
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) ((double) positionableSource->getNextReadPosition() * ratio);
}
return 0;
}
int64 AudioTransportSource::getTotalLength() const
{
const ScopedLock sl (callbackLock);
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) ((double) positionableSource->getTotalLength() * ratio);
}
return 0;
}
bool AudioTransportSource::isLooping() const
{
const ScopedLock sl (callbackLock);
return positionableSource != nullptr && positionableSource->isLooping();
}
void AudioTransportSource::setGain (const float newGain) noexcept
{
gain = newGain;
}
void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, double newSampleRate)
{
const ScopedLock sl (callbackLock);
sampleRate = newSampleRate;
blockSize = samplesPerBlockExpected;
if (masterSource != nullptr)
masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate);
if (resamplerSource != nullptr && sourceSampleRate > 0)
resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
isPrepared = true;
}
void AudioTransportSource::releaseMasterResources()
{
const ScopedLock sl (callbackLock);
if (masterSource != nullptr)
masterSource->releaseResources();
isPrepared = false;
}
void AudioTransportSource::releaseResources()
{
releaseMasterResources();
}
void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (callbackLock);
if (masterSource != nullptr && ! stopped)
{
masterSource->getNextAudioBlock (info);
if (! playing)
{
// just stopped playing, so fade out the last block..
for (int i = info.buffer->getNumChannels(); --i >= 0;)
info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f);
if (info.numSamples > 256)
info.buffer->clear (info.startSample + 256, info.numSamples - 256);
}
if (hasStreamFinished())
{
playing = false;
sendChangeMessage();
}
stopped = ! playing;
for (int i = info.buffer->getNumChannels(); --i >= 0;)
info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
}
else
{
info.clearActiveBufferRegion();
stopped = true;
}
lastGain = gain;
}
} // namespace juce
juce::AudioBuffer::getNumChannels
int getNumChannels() const noexcept
Definition juce_AudioSampleBuffer.h:236
juce::AudioBuffer::clear
void clear() noexcept
Definition juce_AudioSampleBuffer.h:556
juce::AudioBuffer::applyGainRamp
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Definition juce_AudioSampleBuffer.h:726
juce::AudioSource
Definition juce_AudioSource.h:110
juce::AudioSource::releaseResources
virtual void releaseResources()=0
juce::AudioSource::prepareToPlay
virtual void prepareToPlay(int samplesPerBlockExpected, double sampleRate)=0
juce::AudioTransportSource::stop
void stop()
Definition juce_AudioTransportSource.cpp:121
juce::AudioTransportSource::hasStreamFinished
bool hasStreamFinished() const noexcept
Definition juce_AudioTransportSource.cpp:157
juce::AudioTransportSource::prepareToPlay
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Definition juce_AudioTransportSource.cpp:214
juce::AudioTransportSource::getNextReadPosition
int64 getNextReadPosition() const override
Definition juce_AudioTransportSource.cpp:177
juce::AudioTransportSource::getCurrentPosition
double getCurrentPosition() const
Definition juce_AudioTransportSource.cpp:141
juce::AudioTransportSource::releaseResources
void releaseResources() override
Definition juce_AudioTransportSource.cpp:240
juce::AudioTransportSource::getNextAudioBlock
void getNextAudioBlock(const AudioSourceChannelInfo &) override
Definition juce_AudioTransportSource.cpp:245
juce::AudioTransportSource::getTotalLength
int64 getTotalLength() const override
Definition juce_AudioTransportSource.cpp:190
juce::AudioTransportSource::~AudioTransportSource
~AudioTransportSource() override
Definition juce_AudioTransportSource.cpp:30
juce::AudioTransportSource::setPosition
void setPosition(double newPosition)
Definition juce_AudioTransportSource.cpp:135
juce::AudioTransportSource::getLengthInSeconds
double getLengthInSeconds() const
Definition juce_AudioTransportSource.cpp:149
juce::AudioTransportSource::setGain
void setGain(float newGain) noexcept
Definition juce_AudioTransportSource.cpp:209
juce::AudioTransportSource::setSource
void setSource(PositionableAudioSource *newSource, int readAheadBufferSize=0, TimeSliceThread *readAheadThread=nullptr, double sourceSampleRateToCorrectFor=0.0, int maxNumChannels=2)
Definition juce_AudioTransportSource.cpp:36
juce::AudioTransportSource::isLooping
bool isLooping() const override
Definition juce_AudioTransportSource.cpp:203
juce::AudioTransportSource::AudioTransportSource
AudioTransportSource()
Definition juce_AudioTransportSource.cpp:26
juce::AudioTransportSource::start
void start()
Definition juce_AudioTransportSource.cpp:107
juce::AudioTransportSource::setNextReadPosition
void setNextReadPosition(int64 newPosition) override
Definition juce_AudioTransportSource.cpp:163
juce::BufferingAudioSource
Definition juce_BufferingAudioSource.h:40
juce::ChangeBroadcaster::sendChangeMessage
void sendChangeMessage()
Definition juce_ChangeBroadcaster.cpp:65
juce::PositionableAudioSource::PositionableAudioSource
PositionableAudioSource()=default
juce::PositionableAudioSource::setNextReadPosition
virtual void setNextReadPosition(int64 newPosition)=0
juce::ResamplingAudioSource
Definition juce_ResamplingAudioSource.h:35
juce::ResamplingAudioSource::setResamplingRatio
void setResamplingRatio(double samplesInPerOutputSample)
Definition juce_ResamplingAudioSource.cpp:38
juce::Thread::sleep
static void JUCE_CALLTYPE sleep(int milliseconds)
juce::TimeSliceThread
Definition juce_TimeSliceThread.h:83
juce::AudioSourceChannelInfo
Definition juce_AudioSource.h:33
juce::AudioSourceChannelInfo::numSamples
int numSamples
Definition juce_AudioSource.h:81
juce::AudioSourceChannelInfo::clearActiveBufferRegion
void clearActiveBufferRegion() const
Definition juce_AudioSource.h:84
juce::AudioSourceChannelInfo::buffer
AudioBuffer< float > * buffer
Definition juce_AudioSource.h:73
juce::AudioSourceChannelInfo::startSample
int startSample
Definition juce_AudioSource.h:77