git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
180
deps/juce/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp
vendored
Normal file
180
deps/juce/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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
|
||||
{
|
||||
|
||||
AudioSourcePlayer::AudioSourcePlayer()
|
||||
{
|
||||
}
|
||||
|
||||
AudioSourcePlayer::~AudioSourcePlayer()
|
||||
{
|
||||
setSource (nullptr);
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::setSource (AudioSource* newSource)
|
||||
{
|
||||
if (source != newSource)
|
||||
{
|
||||
auto* oldSource = source;
|
||||
|
||||
if (newSource != nullptr && bufferSize > 0 && sampleRate > 0)
|
||||
newSource->prepareToPlay (bufferSize, sampleRate);
|
||||
|
||||
{
|
||||
const ScopedLock sl (readLock);
|
||||
source = newSource;
|
||||
}
|
||||
|
||||
if (oldSource != nullptr)
|
||||
oldSource->releaseResources();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::setGain (const float newGain) noexcept
|
||||
{
|
||||
gain = newGain;
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,
|
||||
int totalNumInputChannels,
|
||||
float** outputChannelData,
|
||||
int totalNumOutputChannels,
|
||||
int numSamples)
|
||||
{
|
||||
// these should have been prepared by audioDeviceAboutToStart()...
|
||||
jassert (sampleRate > 0 && bufferSize > 0);
|
||||
|
||||
const ScopedLock sl (readLock);
|
||||
|
||||
if (source != nullptr)
|
||||
{
|
||||
int numActiveChans = 0, numInputs = 0, numOutputs = 0;
|
||||
|
||||
// messy stuff needed to compact the channels down into an array
|
||||
// of non-zero pointers..
|
||||
for (int i = 0; i < totalNumInputChannels; ++i)
|
||||
{
|
||||
if (inputChannelData[i] != nullptr)
|
||||
{
|
||||
inputChans [numInputs++] = inputChannelData[i];
|
||||
if (numInputs >= numElementsInArray (inputChans))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < totalNumOutputChannels; ++i)
|
||||
{
|
||||
if (outputChannelData[i] != nullptr)
|
||||
{
|
||||
outputChans [numOutputs++] = outputChannelData[i];
|
||||
if (numOutputs >= numElementsInArray (outputChans))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numInputs > numOutputs)
|
||||
{
|
||||
// if there aren't enough output channels for the number of
|
||||
// inputs, we need to create some temporary extra ones (can't
|
||||
// use the input data in case it gets written to)
|
||||
tempBuffer.setSize (numInputs - numOutputs, numSamples,
|
||||
false, false, true);
|
||||
|
||||
for (int i = 0; i < numOutputs; ++i)
|
||||
{
|
||||
channels[numActiveChans] = outputChans[i];
|
||||
memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
|
||||
++numActiveChans;
|
||||
}
|
||||
|
||||
for (int i = numOutputs; i < numInputs; ++i)
|
||||
{
|
||||
channels[numActiveChans] = tempBuffer.getWritePointer (i - numOutputs);
|
||||
memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
|
||||
++numActiveChans;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numInputs; ++i)
|
||||
{
|
||||
channels[numActiveChans] = outputChans[i];
|
||||
memcpy (channels[numActiveChans], inputChans[i], (size_t) numSamples * sizeof (float));
|
||||
++numActiveChans;
|
||||
}
|
||||
|
||||
for (int i = numInputs; i < numOutputs; ++i)
|
||||
{
|
||||
channels[numActiveChans] = outputChans[i];
|
||||
zeromem (channels[numActiveChans], (size_t) numSamples * sizeof (float));
|
||||
++numActiveChans;
|
||||
}
|
||||
}
|
||||
|
||||
AudioBuffer<float> buffer (channels, numActiveChans, numSamples);
|
||||
|
||||
AudioSourceChannelInfo info (&buffer, 0, numSamples);
|
||||
source->getNextAudioBlock (info);
|
||||
|
||||
for (int i = info.buffer->getNumChannels(); --i >= 0;)
|
||||
buffer.applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
|
||||
|
||||
lastGain = gain;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < totalNumOutputChannels; ++i)
|
||||
if (outputChannelData[i] != nullptr)
|
||||
zeromem (outputChannelData[i], (size_t) numSamples * sizeof (float));
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device)
|
||||
{
|
||||
prepareToPlay (device->getCurrentSampleRate(),
|
||||
device->getCurrentBufferSizeSamples());
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::prepareToPlay (double newSampleRate, int newBufferSize)
|
||||
{
|
||||
sampleRate = newSampleRate;
|
||||
bufferSize = newBufferSize;
|
||||
zeromem (channels, sizeof (channels));
|
||||
|
||||
if (source != nullptr)
|
||||
source->prepareToPlay (bufferSize, sampleRate);
|
||||
}
|
||||
|
||||
void AudioSourcePlayer::audioDeviceStopped()
|
||||
{
|
||||
if (source != nullptr)
|
||||
source->releaseResources();
|
||||
|
||||
sampleRate = 0.0;
|
||||
bufferSize = 0;
|
||||
|
||||
tempBuffer.setSize (2, 8);
|
||||
}
|
||||
|
||||
} // namespace juce
|
114
deps/juce/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
vendored
Normal file
114
deps/juce/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Wrapper class to continuously stream audio from an audio source to an
|
||||
AudioIODevice.
|
||||
|
||||
This object acts as an AudioIODeviceCallback, so can be attached to an
|
||||
output device, and will stream audio from an AudioSource.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioSourcePlayer : public AudioIODeviceCallback
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty AudioSourcePlayer. */
|
||||
AudioSourcePlayer();
|
||||
|
||||
/** Destructor.
|
||||
|
||||
Make sure this object isn't still being used by an AudioIODevice before
|
||||
deleting it!
|
||||
*/
|
||||
~AudioSourcePlayer() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the current audio source to play from.
|
||||
|
||||
If the source passed in is already being used, this method will do nothing.
|
||||
If the source is not null, its prepareToPlay() method will be called
|
||||
before it starts being used for playback.
|
||||
|
||||
If there's another source currently playing, its releaseResources() method
|
||||
will be called after it has been swapped for the new one.
|
||||
|
||||
@param newSource the new source to use - this will NOT be deleted
|
||||
by this object when no longer needed, so it's the
|
||||
caller's responsibility to manage it.
|
||||
*/
|
||||
void setSource (AudioSource* newSource);
|
||||
|
||||
/** Returns the source that's playing.
|
||||
May return nullptr if there's no source.
|
||||
*/
|
||||
AudioSource* getCurrentSource() const noexcept { return source; }
|
||||
|
||||
/** Sets a gain to apply to the audio data.
|
||||
@see getGain
|
||||
*/
|
||||
void setGain (float newGain) noexcept;
|
||||
|
||||
/** Returns the current gain.
|
||||
@see setGain
|
||||
*/
|
||||
float getGain() const noexcept { return gain; }
|
||||
|
||||
//==============================================================================
|
||||
/** Implementation of the AudioIODeviceCallback method. */
|
||||
void audioDeviceIOCallback (const float** inputChannelData,
|
||||
int totalNumInputChannels,
|
||||
float** outputChannelData,
|
||||
int totalNumOutputChannels,
|
||||
int numSamples) override;
|
||||
|
||||
/** Implementation of the AudioIODeviceCallback method. */
|
||||
void audioDeviceAboutToStart (AudioIODevice* device) override;
|
||||
|
||||
/** Implementation of the AudioIODeviceCallback method. */
|
||||
void audioDeviceStopped() override;
|
||||
|
||||
/** An alternative method for initialising the source without an AudioIODevice. */
|
||||
void prepareToPlay (double sampleRate, int blockSize);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
CriticalSection readLock;
|
||||
AudioSource* source = nullptr;
|
||||
double sampleRate = 0;
|
||||
int bufferSize = 0;
|
||||
float* channels[128];
|
||||
float* outputChans[128];
|
||||
const float* inputChans[128];
|
||||
AudioBuffer<float> tempBuffer;
|
||||
float lastGain = 1.0f;
|
||||
std::atomic<float> gain { 1.0f };
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSourcePlayer)
|
||||
};
|
||||
|
||||
} // namespace juce
|
326
deps/juce/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
vendored
Normal file
326
deps/juce/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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
|
||||
}
|
||||
|
||||
readAheadBufferSize = readAheadSize;
|
||||
sourceSampleRate = sourceSampleRateToCorrectFor;
|
||||
|
||||
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 && sourceSampleRate > 0 && sampleRate > 0)
|
||||
newResamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
|
||||
|
||||
newMasterSource->prepareToPlay (blockSize, sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
||||
source = newSource;
|
||||
resamplerSource = newResamplerSource;
|
||||
bufferingSource = newBufferingSource;
|
||||
masterSource = newMasterSource;
|
||||
positionableSource = newPositionableSource;
|
||||
|
||||
inputStreamEOF = false;
|
||||
playing = false;
|
||||
}
|
||||
|
||||
if (oldMasterSource != nullptr)
|
||||
oldMasterSource->releaseResources();
|
||||
}
|
||||
|
||||
void AudioTransportSource::start()
|
||||
{
|
||||
if ((! playing) && masterSource != nullptr)
|
||||
{
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
playing = true;
|
||||
stopped = false;
|
||||
inputStreamEOF = 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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
inputStreamEOF = false;
|
||||
}
|
||||
}
|
||||
|
||||
int64 AudioTransportSource::getNextReadPosition() const
|
||||
{
|
||||
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::setLooping(bool shouldLoop)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
if (positionableSource != nullptr) {
|
||||
positionableSource->setLooping(shouldLoop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AudioTransportSource::getLoopRange (int64 & loopStart, int64 & loopLength) const
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
if (positionableSource != nullptr) {
|
||||
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
|
||||
|
||||
positionableSource->getLoopRange(loopStart, loopLength);
|
||||
loopStart = (int64) (loopStart * ratio);
|
||||
loopLength = (int64) (loopLength * ratio);
|
||||
}
|
||||
else {
|
||||
loopStart = 0;
|
||||
loopLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioTransportSource::setLoopRange (int64 loopStart, int64 loopLength)
|
||||
{
|
||||
if (positionableSource != nullptr)
|
||||
{
|
||||
if (sampleRate > 0 && sourceSampleRate > 0) {
|
||||
loopStart = (int64) (loopStart * sourceSampleRate / sampleRate);
|
||||
loopLength = (int64) (loopLength * sourceSampleRate / sampleRate);
|
||||
}
|
||||
|
||||
positionableSource->setLoopRange(loopStart, loopLength);
|
||||
|
||||
if (resamplerSource != nullptr)
|
||||
resamplerSource->flushBuffers();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
inputStreamEOF = false;
|
||||
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 (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
|
||||
&& ! positionableSource->isLooping())
|
||||
{
|
||||
playing = false;
|
||||
inputStreamEOF = true;
|
||||
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
|
190
deps/juce/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
vendored
Normal file
190
deps/juce/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An AudioSource that takes a PositionableAudioSource and allows it to be
|
||||
played, stopped, started, etc.
|
||||
|
||||
This can also be told use a buffer and background thread to read ahead, and
|
||||
if can correct for different sample-rates.
|
||||
|
||||
You may want to use one of these along with an AudioSourcePlayer and AudioIODevice
|
||||
to control playback of an audio file.
|
||||
|
||||
@see AudioSource, AudioSourcePlayer
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioTransportSource : public PositionableAudioSource,
|
||||
public ChangeBroadcaster
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an AudioTransportSource.
|
||||
After creating one of these, use the setSource() method to select an input source.
|
||||
*/
|
||||
AudioTransportSource();
|
||||
|
||||
/** Destructor. */
|
||||
~AudioTransportSource() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the reader that is being used as the input source.
|
||||
|
||||
This will stop playback, reset the position to 0 and change to the new reader.
|
||||
|
||||
The source passed in will not be deleted by this object, so must be managed by
|
||||
the caller.
|
||||
|
||||
@param newSource the new input source to use. This may be a nullptr
|
||||
@param readAheadBufferSize a size of buffer to use for reading ahead. If this
|
||||
is zero, no reading ahead will be done; if it's
|
||||
greater than zero, a BufferingAudioSource will be used
|
||||
to do the reading-ahead. If you set a non-zero value here,
|
||||
you'll also need to set the readAheadThread parameter.
|
||||
@param readAheadThread if you set readAheadBufferSize to a non-zero value, then
|
||||
you'll also need to supply this TimeSliceThread object for
|
||||
the background reader to use. The thread object must not be
|
||||
deleted while the AudioTransport source is still using it.
|
||||
@param sourceSampleRateToCorrectFor if this is non-zero, it specifies the sample
|
||||
rate of the source, and playback will be sample-rate
|
||||
adjusted to maintain playback at the correct pitch. If
|
||||
this is 0, no sample-rate adjustment will be performed
|
||||
@param maxNumChannels the maximum number of channels that may need to be played
|
||||
*/
|
||||
void setSource (PositionableAudioSource* newSource,
|
||||
int readAheadBufferSize = 0,
|
||||
TimeSliceThread* readAheadThread = nullptr,
|
||||
double sourceSampleRateToCorrectFor = 0.0,
|
||||
int maxNumChannels = 2);
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the current playback position in the source stream.
|
||||
|
||||
The next time the getNextAudioBlock() method is called, this
|
||||
is the time from which it'll read data.
|
||||
|
||||
@param newPosition the new playback position in seconds
|
||||
|
||||
@see getCurrentPosition
|
||||
*/
|
||||
void setPosition (double newPosition);
|
||||
|
||||
/** Returns the position that the next data block will be read from
|
||||
This is a time in seconds.
|
||||
*/
|
||||
double getCurrentPosition() const;
|
||||
|
||||
/** Returns the stream's length in seconds. */
|
||||
double getLengthInSeconds() const;
|
||||
|
||||
/** Returns true if the player has stopped because its input stream ran out of data. */
|
||||
bool hasStreamFinished() const noexcept { return inputStreamEOF; }
|
||||
|
||||
//==============================================================================
|
||||
/** Starts playing (if a source has been selected).
|
||||
|
||||
If it starts playing, this will send a message to any ChangeListeners
|
||||
that are registered with this object.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/** Stops playing.
|
||||
|
||||
If it's actually playing, this will send a message to any ChangeListeners
|
||||
that are registered with this object.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/** Returns true if it's currently playing. */
|
||||
bool isPlaying() const noexcept { return playing; }
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the gain to apply to the output.
|
||||
@param newGain a factor by which to multiply the outgoing samples,
|
||||
so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc.
|
||||
*/
|
||||
void setGain (float newGain) noexcept;
|
||||
|
||||
/** Returns the current gain setting.
|
||||
@see setGain
|
||||
*/
|
||||
float getGain() const noexcept { return gain; }
|
||||
|
||||
//==============================================================================
|
||||
/** Implementation of the AudioSource method. */
|
||||
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
|
||||
|
||||
/** Implementation of the AudioSource method. */
|
||||
void releaseResources() override;
|
||||
|
||||
/** Implementation of the AudioSource method. */
|
||||
void getNextAudioBlock (const AudioSourceChannelInfo&) override;
|
||||
|
||||
//==============================================================================
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
void setNextReadPosition (int64 newPosition) override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
int64 getNextReadPosition() const override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
int64 getTotalLength() const override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
bool isLooping() const override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
void setLooping(bool shouldLoop) override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
void setLoopRange (int64 loopStart, int64 loopLength) override;
|
||||
|
||||
/** Implements the PositionableAudioSource method. */
|
||||
void getLoopRange (int64 & loopStart, int64 & loopLength) const override;
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
PositionableAudioSource* source = nullptr;
|
||||
ResamplingAudioSource* resamplerSource = nullptr;
|
||||
BufferingAudioSource* bufferingSource = nullptr;
|
||||
PositionableAudioSource* positionableSource = nullptr;
|
||||
AudioSource* masterSource = nullptr;
|
||||
|
||||
CriticalSection callbackLock;
|
||||
float gain = 1.0f, lastGain = 1.0f;
|
||||
std::atomic<bool> playing { false }, stopped { true };
|
||||
double sampleRate = 44100.0, sourceSampleRate = 0;
|
||||
int blockSize = 128, readAheadBufferSize = 0;
|
||||
bool isPrepared = false, inputStreamEOF = false;
|
||||
|
||||
void releaseMasterResources();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioTransportSource)
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user