bug 1391482 accept int16_t sample buffers in ConvolverNode r?padenot
MozReview-Commit-ID: LvYkiSvhQdP
--- a/dom/media/webaudio/ConvolverNode.cpp
+++ b/dom/media/webaudio/ConvolverNode.cpp
@@ -246,29 +246,55 @@ ConvolverNode::SetBuffer(JSContext* aCx,
// Supported number of channels
break;
default:
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
}
- mBuffer = aBuffer;
-
// Send the buffer to the stream
AudioNodeStream* ns = mStream;
MOZ_ASSERT(ns, "Why don't we have a stream here?");
- if (mBuffer) {
- AudioChunk data = mBuffer->GetThreadSharedChannelsForRate(aCx);
+ if (aBuffer) {
+ AudioChunk data = aBuffer->GetThreadSharedChannelsForRate(aCx);
+ if (data.mBufferFormat == AUDIO_FORMAT_S16) {
+ // Reverb expects data in float format.
+ // Convert on the main thread so as to minimize allocations on the audio
+ // thread.
+ // Reverb will dispose of the buffer once initialized, so convert here
+ // and leave the smaller arrays in the AudioBuffer.
+ // There is currently no value in providing 16/32-byte aligned data
+ // because PadAndMakeScaledDFT() will copy the data (without SIMD
+ // instructions) to aligned arrays for the FFT.
+ RefPtr<SharedBuffer> floatBuffer =
+ SharedBuffer::Create(sizeof(float) *
+ data.mDuration * data.ChannelCount());
+ if (!floatBuffer) {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ auto floatData = static_cast<float*>(floatBuffer->Data());
+ for (size_t i = 0; i < data.ChannelCount(); ++i) {
+ ConvertAudioSamples(data.ChannelData<int16_t>()[i],
+ floatData, data.mDuration);
+ data.mChannelData[i] = floatData;
+ floatData += data.mDuration;
+ }
+ data.mBuffer = Move(floatBuffer);
+ data.mBufferFormat = AUDIO_FORMAT_FLOAT32;
+ }
SendDoubleParameterToStream(ConvolverNodeEngine::SAMPLE_RATE,
- mBuffer->SampleRate());
+ aBuffer->SampleRate());
ns->SetBuffer(Move(data));
} else {
ns->SetBuffer(AudioChunk());
}
+
+ mBuffer = aBuffer;
}
void
ConvolverNode::SetNormalize(bool aNormalize)
{
mNormalize = aNormalize;
SendInt32ParameterToStream(ConvolverNodeEngine::NORMALIZE, aNormalize);
}