Browse Source

Fixed a threading problem in BufferingAudioSource.

tags/2021-05-28
Julian Storer 13 years ago
parent
commit
54eb263055
6 changed files with 37 additions and 22 deletions
  1. +5
    -5
      extras/JuceDemo/Source/demos/AudioDemoPlaybackPage.cpp
  2. +1
    -0
      modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp
  3. +29
    -14
      modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp
  4. +1
    -1
      modules/juce_audio_basics/sources/juce_BufferingAudioSource.h
  5. +1
    -1
      modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
  6. +0
    -1
      modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp

+ 5
- 5
extras/JuceDemo/Source/demos/AudioDemoPlaybackPage.cpp View File

@@ -186,8 +186,8 @@ AudioDemoPlaybackPage::AudioDemoPlaybackPage (AudioDeviceManager& deviceManager_
AudioDemoPlaybackPage::~AudioDemoPlaybackPage() AudioDemoPlaybackPage::~AudioDemoPlaybackPage()
{ {
//[Destructor_pre]. You can add your own custom destruction code here.. //[Destructor_pre]. You can add your own custom destruction code here..
transportSource.setSource (0);
audioSourcePlayer.setSource (0);
transportSource.setSource (nullptr);
audioSourcePlayer.setSource (nullptr);
deviceManager.removeAudioCallback (&audioSourcePlayer); deviceManager.removeAudioCallback (&audioSourcePlayer);
fileTreeComp->removeListener (this); fileTreeComp->removeListener (this);
@@ -285,8 +285,8 @@ void AudioDemoPlaybackPage::loadFileIntoTransport (const File& audioFile)
{ {
// unload the previous file source and delete it.. // unload the previous file source and delete it..
transportSource.stop(); transportSource.stop();
transportSource.setSource (0);
currentAudioFileSource = 0;
transportSource.setSource (nullptr);
currentAudioFileSource = nullptr;
// get a format manager and set it up with the basic types (wav and aiff). // get a format manager and set it up with the basic types (wav and aiff).
AudioFormatManager formatManager; AudioFormatManager formatManager;
@@ -294,7 +294,7 @@ void AudioDemoPlaybackPage::loadFileIntoTransport (const File& audioFile)
AudioFormatReader* reader = formatManager.createReaderFor (audioFile); AudioFormatReader* reader = formatManager.createReaderFor (audioFile);
if (reader != 0)
if (reader != nullptr)
{ {
currentAudioFileSource = new AudioFormatReaderSource (reader, true); currentAudioFileSource = new AudioFormatReaderSource (reader, true);


+ 1
- 0
modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp View File

@@ -153,6 +153,7 @@ void AudioSampleBuffer::setSize (const int newNumChannels,
const bool avoidReallocating) noexcept const bool avoidReallocating) noexcept
{ {
jassert (newNumChannels > 0); jassert (newNumChannels > 0);
jassert (newNumSamples >= 0);
if (newNumSamples != size || newNumChannels != numChannels) if (newNumSamples != size || newNumChannels != numChannels)
{ {


+ 29
- 14
modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp View File

@@ -39,7 +39,8 @@ BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_,
bufferValidStart (0), bufferValidStart (0),
bufferValidEnd (0), bufferValidEnd (0),
nextPlayPos (0), nextPlayPos (0),
wasSourceLooping (false)
wasSourceLooping (false),
isPrepared (false)
{ {
jassert (source_ != nullptr); jassert (source_ != nullptr);
@@ -55,28 +56,39 @@ BufferingAudioSource::~BufferingAudioSource()
//============================================================================== //==============================================================================
void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate_) void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate_)
{ {
source->prepareToPlay (samplesPerBlockExpected, sampleRate_);
const int bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);
sampleRate = sampleRate_;
if (sampleRate_ != sampleRate
|| bufferSizeNeeded != buffer.getNumSamples()
|| ! isPrepared)
{
backgroundThread.removeTimeSliceClient (this);
buffer.setSize (numberOfChannels, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer));
buffer.clear();
isPrepared = true;
sampleRate = sampleRate_;
bufferValidStart = 0;
bufferValidEnd = 0;
source->prepareToPlay (samplesPerBlockExpected, sampleRate_);
backgroundThread.addTimeSliceClient (this);
buffer.setSize (numberOfChannels, bufferSizeNeeded);
buffer.clear();
bufferValidStart = 0;
bufferValidEnd = 0;
while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4,
buffer.getNumSamples() / 2))
{
backgroundThread.addTimeSliceClient (this); backgroundThread.addTimeSliceClient (this);
Thread::sleep (5);
while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4,
buffer.getNumSamples() / 2))
{
backgroundThread.addTimeSliceClient (this);
Thread::sleep (5);
}
} }
} }
void BufferingAudioSource::releaseResources() void BufferingAudioSource::releaseResources()
{ {
isPrepared = false;
backgroundThread.removeTimeSliceClient (this); backgroundThread.removeTimeSliceClient (this);
buffer.setSize (numberOfChannels, 0); buffer.setSize (numberOfChannels, 0);
@@ -108,8 +120,9 @@ void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info
{ {
for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;) for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;)
{ {
jassert (buffer.getNumSamples() > 0);
const int startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples()); const int startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples());
const int endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples());
const int endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples());
if (startBufferIndex < endBufferIndex) if (startBufferIndex < endBufferIndex)
{ {
@@ -144,6 +157,7 @@ void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info
int64 BufferingAudioSource::getNextReadPosition() const int64 BufferingAudioSource::getNextReadPosition() const
{ {
jassert (source->getTotalLength() > 0);
return (source->isLooping() && nextPlayPos > 0) return (source->isLooping() && nextPlayPos > 0)
? nextPlayPos % source->getTotalLength() ? nextPlayPos % source->getTotalLength()
: nextPlayPos; : nextPlayPos;
@@ -204,8 +218,9 @@ bool BufferingAudioSource::readNextBufferChunk()
if (sectionToReadStart != sectionToReadEnd) if (sectionToReadStart != sectionToReadEnd)
{ {
jassert (buffer.getNumSamples() > 0);
const int bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples()); const int bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples());
const int bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples());
const int bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples());
if (bufferIndexStart < bufferIndexEnd) if (bufferIndexStart < bufferIndexEnd)
{ {


+ 1
- 1
modules/juce_audio_basics/sources/juce_BufferingAudioSource.h View File

@@ -101,7 +101,7 @@ private:
CriticalSection bufferStartPosLock; CriticalSection bufferStartPosLock;
int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos; int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos;
double volatile sampleRate; double volatile sampleRate;
bool wasSourceLooping;
bool wasSourceLooping, isPrepared;
friend class SharedBufferingAudioSourceThread; friend class SharedBufferingAudioSourceThread;
bool readNextBufferChunk(); bool readNextBufferChunk();


+ 1
- 1
modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp View File

@@ -63,7 +63,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
if (source == nullptr) if (source == nullptr)
return; return;
setSource (0, 0, 0); // deselect and reselect to avoid releasing resources wrongly
setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
} }
readAheadBufferSize = readAheadBufferSize_; readAheadBufferSize = readAheadBufferSize_;


+ 0
- 1
modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp View File

@@ -54,7 +54,6 @@ namespace
class CoreAudioReader : public AudioFormatReader class CoreAudioReader : public AudioFormatReader
{ {
public: public:
//==============================================================================
CoreAudioReader (InputStream* const inp) CoreAudioReader (InputStream* const inp)
: AudioFormatReader (inp, TRANS (coreAudioFormatName)), : AudioFormatReader (inp, TRANS (coreAudioFormatName)),
ok (false), lastReadPosition (0) ok (false), lastReadPosition (0)


Loading…
Cancel
Save