mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
AudioDeviceManager: Move CallbackMaxSizeEnforcer from StandaloneFilterWindow
This commit is contained in:
parent
28a2700a28
commit
ee37564083
2 changed files with 100 additions and 97 deletions
|
|
@ -459,93 +459,6 @@ private:
|
|||
processor = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/* This class can be used to ensure that audio callbacks use buffers with a
|
||||
predictable maximum size.
|
||||
|
||||
On some platforms (such as iOS 10), the expected buffer size reported in
|
||||
audioDeviceAboutToStart may be smaller than the blocks passed to
|
||||
audioDeviceIOCallbackWithContext. This can lead to out-of-bounds reads if the render
|
||||
callback depends on additional buffers which were initialised using the
|
||||
smaller size.
|
||||
|
||||
As a workaround, this class will ensure that the render callback will
|
||||
only ever be called with a block with a length less than or equal to the
|
||||
expected block size.
|
||||
*/
|
||||
class CallbackMaxSizeEnforcer : public AudioIODeviceCallback
|
||||
{
|
||||
public:
|
||||
explicit CallbackMaxSizeEnforcer (AudioIODeviceCallback& callbackIn)
|
||||
: inner (callbackIn) {}
|
||||
|
||||
void audioDeviceAboutToStart (AudioIODevice* device) override
|
||||
{
|
||||
maximumSize = device->getCurrentBufferSizeSamples();
|
||||
storedInputChannels .resize ((size_t) device->getActiveInputChannels() .countNumberOfSetBits());
|
||||
storedOutputChannels.resize ((size_t) device->getActiveOutputChannels().countNumberOfSetBits());
|
||||
|
||||
inner.audioDeviceAboutToStart (device);
|
||||
}
|
||||
|
||||
void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,
|
||||
[[maybe_unused]] int numInputChannels,
|
||||
float* const* outputChannelData,
|
||||
[[maybe_unused]] int numOutputChannels,
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext& context) override
|
||||
{
|
||||
jassert ((int) storedInputChannels.size() == numInputChannels);
|
||||
jassert ((int) storedOutputChannels.size() == numOutputChannels);
|
||||
|
||||
int position = 0;
|
||||
|
||||
while (position < numSamples)
|
||||
{
|
||||
const auto blockLength = jmin (maximumSize, numSamples - position);
|
||||
|
||||
initChannelPointers (inputChannelData, storedInputChannels, position);
|
||||
initChannelPointers (outputChannelData, storedOutputChannels, position);
|
||||
|
||||
inner.audioDeviceIOCallbackWithContext (storedInputChannels.data(),
|
||||
(int) storedInputChannels.size(),
|
||||
storedOutputChannels.data(),
|
||||
(int) storedOutputChannels.size(),
|
||||
blockLength,
|
||||
context);
|
||||
|
||||
position += blockLength;
|
||||
}
|
||||
}
|
||||
|
||||
void audioDeviceStopped() override
|
||||
{
|
||||
inner.audioDeviceStopped();
|
||||
}
|
||||
|
||||
private:
|
||||
struct GetChannelWithOffset
|
||||
{
|
||||
int offset;
|
||||
|
||||
template <typename Ptr>
|
||||
auto operator() (Ptr ptr) const noexcept -> Ptr { return ptr + offset; }
|
||||
};
|
||||
|
||||
template <typename Ptr, typename Vector>
|
||||
void initChannelPointers (Ptr&& source, Vector&& target, int offset)
|
||||
{
|
||||
std::transform (source, source + target.size(), target.begin(), GetChannelWithOffset { offset });
|
||||
}
|
||||
|
||||
AudioIODeviceCallback& inner;
|
||||
int maximumSize = 0;
|
||||
std::vector<const float*> storedInputChannels;
|
||||
std::vector<float*> storedOutputChannels;
|
||||
};
|
||||
|
||||
CallbackMaxSizeEnforcer maxSizeEnforcer { *this };
|
||||
|
||||
//==============================================================================
|
||||
class SettingsComponent : public Component
|
||||
{
|
||||
|
|
@ -682,7 +595,7 @@ private:
|
|||
const String& preferredDefaultDeviceName,
|
||||
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions)
|
||||
{
|
||||
deviceManager.addAudioCallback (&maxSizeEnforcer);
|
||||
deviceManager.addAudioCallback (this);
|
||||
deviceManager.addMidiInputDeviceCallback ({}, &player);
|
||||
|
||||
reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions);
|
||||
|
|
@ -693,7 +606,7 @@ private:
|
|||
saveAudioDeviceState();
|
||||
|
||||
deviceManager.removeMidiInputDeviceCallback ({}, &player);
|
||||
deviceManager.removeAudioCallback (&maxSizeEnforcer);
|
||||
deviceManager.removeAudioCallback (this);
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue