Bug 890716. Fix race in Reverb::Reverb. r=padenot

--HG--
extra : rebase_source : 65af577f5ffcf7f7a0b650f1693f4159ddac4ac6
This commit is contained in:
Robert O'Callahan 2013-07-26 13:35:22 +12:00
parent d7f169426c
commit bb4a03e7ad
4 changed files with 42 additions and 18 deletions

View File

@ -39,6 +39,20 @@ WriteZeroesToAudioBlock(AudioChunk* aChunk, uint32_t aStart, uint32_t aLength)
} }
} }
void AudioBufferCopyWithScale(const float* aInput,
float aScale,
float* aOutput,
uint32_t aSize)
{
if (aScale == 1.0f) {
PodCopy(aOutput, aInput, aSize);
} else {
for (uint32_t i = 0; i < aSize; ++i) {
aOutput[i] = aInput[i]*aScale;
}
}
}
void AudioBufferAddWithScale(const float* aInput, void AudioBufferAddWithScale(const float* aInput,
float aScale, float aScale,
float* aOutput, float* aOutput,

View File

@ -87,6 +87,14 @@ void AllocateAudioBlock(uint32_t aChannelCount, AudioChunk* aChunk);
*/ */
void WriteZeroesToAudioBlock(AudioChunk* aChunk, uint32_t aStart, uint32_t aLength); void WriteZeroesToAudioBlock(AudioChunk* aChunk, uint32_t aStart, uint32_t aLength);
/**
* Copy with scale. aScale == 1.0f should be optimized.
*/
void AudioBufferCopyWithScale(const float* aInput,
float aScale,
float* aOutput,
uint32_t aSize);
/** /**
* Pointwise multiply-add operation. aScale == 1.0f should be optimized. * Pointwise multiply-add operation. aScale == 1.0f should be optimized.
*/ */

View File

@ -80,41 +80,43 @@ Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulse
{ {
float scale = 1; float scale = 1;
nsAutoTArray<const float*,4> irChannels;
for (size_t i = 0; i < impulseResponse->GetChannels(); ++i) {
irChannels.AppendElement(impulseResponse->GetData(i));
}
nsAutoTArray<float,1024> tempBuf;
if (normalize) { if (normalize) {
scale = calculateNormalizationScale(impulseResponse, impulseResponseBufferLength, sampleRate); scale = calculateNormalizationScale(impulseResponse, impulseResponseBufferLength, sampleRate);
if (scale) { if (scale) {
for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) { tempBuf.SetLength(irChannels.Length()*impulseResponseBufferLength);
AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)), for (uint32_t i = 0; i < irChannels.Length(); ++i) {
1, scale, impulseResponseBufferLength); float* buf = &tempBuf[i*impulseResponseBufferLength];
AudioBufferCopyWithScale(irChannels[i], scale, buf,
impulseResponseBufferLength);
irChannels[i] = buf;
} }
} }
} }
initialize(impulseResponse, impulseResponseBufferLength, renderSliceSize, maxFFTSize, numberOfChannels, useBackgroundThreads); initialize(irChannels, impulseResponseBufferLength, renderSliceSize,
maxFFTSize, numberOfChannels, useBackgroundThreads);
// Undo scaling since this shouldn't be a destructive operation on impulseResponse.
// FIXME: What about roundoff? Perhaps consider making a temporary scaled copy
// instead of scaling and unscaling in place.
if (normalize && scale) {
for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) {
AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)),
1, 1 / scale, impulseResponseBufferLength);
}
}
} }
void Reverb::initialize(ThreadSharedFloatArrayBufferList* impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads) void Reverb::initialize(const nsTArray<const float*>& impulseResponseBuffer,
size_t impulseResponseBufferLength, size_t renderSliceSize,
size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads)
{ {
m_impulseResponseLength = impulseResponseBufferLength; m_impulseResponseLength = impulseResponseBufferLength;
// The reverb can handle a mono impulse response and still do stereo processing // The reverb can handle a mono impulse response and still do stereo processing
size_t numResponseChannels = impulseResponseBuffer->GetChannels(); size_t numResponseChannels = impulseResponseBuffer.Length();
m_convolvers.SetCapacity(numberOfChannels); m_convolvers.SetCapacity(numberOfChannels);
int convolverRenderPhase = 0; int convolverRenderPhase = 0;
for (size_t i = 0; i < numResponseChannels; ++i) { for (size_t i = 0; i < numResponseChannels; ++i) {
const float* channel = impulseResponseBuffer->GetData(i); const float* channel = impulseResponseBuffer[i];
size_t length = impulseResponseBufferLength; size_t length = impulseResponseBufferLength;
nsAutoPtr<ReverbConvolver> convolver(new ReverbConvolver(channel, length, renderSliceSize, maxFFTSize, convolverRenderPhase, useBackgroundThreads)); nsAutoPtr<ReverbConvolver> convolver(new ReverbConvolver(channel, length, renderSliceSize, maxFFTSize, convolverRenderPhase, useBackgroundThreads));

View File

@ -55,7 +55,7 @@ public:
size_t latencyFrames() const; size_t latencyFrames() const;
private: private:
void initialize(mozilla::ThreadSharedFloatArrayBufferList* impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads); void initialize(const nsTArray<const float*>& impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads);
size_t m_impulseResponseLength; size_t m_impulseResponseLength;