Browse Source

Fixed some data races in the CoreAudio audio device

tags/2021-05-28
Tom Poole 8 years ago
parent
commit
ceb0afd861
4 changed files with 29 additions and 17 deletions
  1. +24
    -12
      modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  2. +1
    -1
      modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  3. +2
    -2
      modules/juce_core/threads/juce_Thread.cpp
  4. +2
    -2
      modules/juce_core/threads/juce_Thread.h

+ 24
- 12
modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp View File

@@ -1292,8 +1292,11 @@ public:
} }
fifos.setSize (chanIndex, fifoSize); fifos.setSize (chanIndex, fifoSize);
fifoReadPointers = fifos.getArrayOfReadPointers();
fifoWritePointers = fifos.getArrayOfWritePointers();
fifos.clear(); fifos.clear();
startThread (9); startThread (9);
threadInitialised.wait();
return {}; return {};
} }
@@ -1401,6 +1404,9 @@ private:
bool active = false; bool active = false;
String lastError; String lastError;
AudioBuffer<float> fifos; AudioBuffer<float> fifos;
const float** fifoReadPointers = nullptr;
float** fifoWritePointers = nullptr;
WaitableEvent threadInitialised;
void run() override void run() override
{ {
@@ -1428,6 +1434,8 @@ private:
jassert (numInputChans + numOutputChans == buffer.getNumChannels()); jassert (numInputChans + numOutputChans == buffer.getNumChannels());
threadInitialised.signal();
while (! threadShouldExit()) while (! threadShouldExit())
{ {
readInput (buffer, numSamples, blockSizeMs); readInput (buffer, numSamples, blockSizeMs);
@@ -1679,7 +1687,7 @@ private:
{ {
auto index = inputIndex + i; auto index = inputIndex + i;
auto dest = destBuffer.getWritePointer (index); auto dest = destBuffer.getWritePointer (index);
auto src = owner.fifos.getReadPointer (index);
auto src = owner.fifoReadPointers[index];
if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1); if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1);
if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2); if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2);
@@ -1704,7 +1712,7 @@ private:
for (int i = 0; i < numOutputChans; ++i) for (int i = 0; i < numOutputChans; ++i)
{ {
auto index = outputIndex + i; auto index = outputIndex + i;
auto dest = owner.fifos.getWritePointer (index);
auto dest = owner.fifoWritePointers[index];
auto src = srcBuffer.getReadPointer (index); auto src = srcBuffer.getReadPointer (index);
if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1); if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1);
@@ -1718,8 +1726,6 @@ private:
float** outputChannelData, int numOutputChannels, float** outputChannelData, int numOutputChannels,
int numSamples) override int numSamples) override
{ {
auto& buf = owner.fifos;
if (numInputChannels > 0) if (numInputChannels > 0)
{ {
int start1, size1, start2, size2; int start1, size1, start2, size2;
@@ -1733,19 +1739,22 @@ private:
for (int i = 0; i < numInputChannels; ++i) for (int i = 0; i < numInputChannels; ++i)
{ {
auto dest = buf.getWritePointer (inputIndex + i);
auto dest = owner.fifoWritePointers[inputIndex + i];
auto src = inputChannelData[i]; auto src = inputChannelData[i];
if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1); if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1);
if (size2 > 0) FloatVectorOperations::copy (dest + start2, src + size1, size2); if (size2 > 0) FloatVectorOperations::copy (dest + start2, src + size1, size2);
} }
inputFifo.finishedWrite (size1 + size2);
auto totalSize = size1 + size2;
inputFifo.finishedWrite (totalSize);
if (numSamples > size1 + size2)
if (numSamples > totalSize)
{ {
auto samplesRemaining = numSamples - totalSize;
for (int i = 0; i < numInputChans; ++i) for (int i = 0; i < numInputChans; ++i)
buf.clear (inputIndex + i, size1 + size2, numSamples - (size1 + size2));
FloatVectorOperations::clear (owner.fifoWritePointers[inputIndex + i] + totalSize, samplesRemaining);
owner.underrun(); owner.underrun();
} }
@@ -1765,18 +1774,21 @@ private:
for (int i = 0; i < numOutputChannels; ++i) for (int i = 0; i < numOutputChannels; ++i)
{ {
auto dest = outputChannelData[i]; auto dest = outputChannelData[i];
auto src = buf.getReadPointer (outputIndex + i);
auto src = owner.fifoReadPointers[outputIndex + i];
if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1); if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1);
if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2); if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2);
} }
outputFifo.finishedRead (size1 + size2);
auto totalSize = size1 + size2;
outputFifo.finishedRead (totalSize);
if (numSamples > size1 + size2)
if (numSamples > totalSize)
{ {
auto samplesRemaining = numSamples - totalSize;
for (int i = 0; i < numOutputChannels; ++i) for (int i = 0; i < numOutputChannels; ++i)
FloatVectorOperations::clear (outputChannelData[i] + (size1 + size2), numSamples - (size1 + size2));
FloatVectorOperations::clear (outputChannelData[i] + totalSize, samplesRemaining);
owner.underrun(); owner.underrun();
} }


+ 1
- 1
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h View File

@@ -295,7 +295,7 @@ public:
if (settings != nullptr) if (settings != nullptr)
{ {
savedState = settings->getXmlValue ("audioSetup");
savedState = settings->getXmlValue ("audioSetup");
#if ! (JUCE_IOS || JUCE_ANDROID) #if ! (JUCE_IOS || JUCE_ANDROID)
shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true)); shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true));


+ 2
- 2
modules/juce_core/threads/juce_Thread.cpp View File

@@ -123,7 +123,7 @@ void Thread::startThread()
{ {
const ScopedLock sl (startStopLock); const ScopedLock sl (startStopLock);
shouldExit = false;
shouldExit = 0;
if (threadHandle.get() == nullptr) if (threadHandle.get() == nullptr)
{ {
@@ -170,7 +170,7 @@ Thread* JUCE_CALLTYPE Thread::getCurrentThread()
//============================================================================== //==============================================================================
void Thread::signalThreadShouldExit() void Thread::signalThreadShouldExit()
{ {
shouldExit = true;
shouldExit = 1;
listeners.call ([] (Listener& l) { l.exitSignalSent(); }); listeners.call ([] (Listener& l) { l.exitSignalSent(); });
} }


+ 2
- 2
modules/juce_core/threads/juce_Thread.h View File

@@ -153,7 +153,7 @@ public:
@see signalThreadShouldExit, currentThreadShouldExit @see signalThreadShouldExit, currentThreadShouldExit
*/ */
bool threadShouldExit() const { return shouldExit; }
bool threadShouldExit() const { return shouldExit.get() != 0; }
/** Checks whether the current thread has been told to stop running. /** Checks whether the current thread has been told to stop running.
On the message thread, this will always return false, otherwise On the message thread, this will always return false, otherwise
@@ -333,7 +333,7 @@ private:
size_t threadStackSize; size_t threadStackSize;
uint32 affinityMask = 0; uint32 affinityMask = 0;
bool deleteOnThreadEnd = false; bool deleteOnThreadEnd = false;
bool volatile shouldExit = false;
Atomic<int32> shouldExit { 0 };
ListenerList<Listener, Array<Listener*, CriticalSection>> listeners; ListenerList<Listener, Array<Listener*, CriticalSection>> listeners;
#if JUCE_ANDROID #if JUCE_ANDROID


Loading…
Cancel
Save