Bug 1472550 - Add Audio{Buffer,Block}InPlaceScale that takes an array of gain values, with SSE and NEON variants. r=dminor
MozReview-Commit-ID: FzfDObKCrEd
--- a/dom/media/webaudio/AudioNodeEngine.cpp
+++ b/dom/media/webaudio/AudioNodeEngine.cpp
@@ -224,16 +224,23 @@ AudioBlockCopyChannelWithScale(const flo
void
AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
float aScale)
{
AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
}
void
+AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
+ float aScale[WEBAUDIO_BLOCK_SIZE])
+{
+ AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
+}
+
+void
AudioBufferInPlaceScale(float* aBlock,
float aScale,
uint32_t aSize)
{
if (aScale == 1.0f) {
return;
}
#ifdef BUILD_ARM_NEON
@@ -251,16 +258,40 @@ AudioBufferInPlaceScale(float* aBlock,
#endif
for (uint32_t i = 0; i < aSize; ++i) {
*aBlock++ *= aScale;
}
}
void
+AudioBufferInPlaceScale(float* aBlock,
+ float* aScale,
+ uint32_t aSize)
+{
+#ifdef BUILD_ARM_NEON
+ if (mozilla::supports_neon()) {
+ AudioBufferInPlaceScale_NEON(aBlock, aScale, aSize);
+ return;
+ }
+#endif
+
+#ifdef USE_SSE2
+ if (mozilla::supports_sse2()) {
+ AudioBufferInPlaceScale_SSE(aBlock, aScale, aSize);
+ return;
+ }
+#endif
+
+ for (uint32_t i = 0; i < aSize; ++i) {
+ *aBlock++ *= *aScale++;
+ }
+}
+
+void
AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
float aGainL[WEBAUDIO_BLOCK_SIZE],
float aGainR[WEBAUDIO_BLOCK_SIZE],
float aOutputL[WEBAUDIO_BLOCK_SIZE],
float aOutputR[WEBAUDIO_BLOCK_SIZE])
{
AudioBlockCopyChannelWithScale(aInput, aGainL, aOutputL);
AudioBlockCopyChannelWithScale(aInput, aGainR, aOutputR);
--- a/dom/media/webaudio/AudioNodeEngine.h
+++ b/dom/media/webaudio/AudioNodeEngine.h
@@ -205,16 +205,28 @@ void AudioBlockInPlaceScale(float aBlock
/**
* In place gain. aScale == 1.0f should be optimized.
*/
void AudioBufferInPlaceScale(float* aBlock,
float aScale,
uint32_t aSize);
/**
+ * a-rate in place gain.
+ */
+void AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
+ float aScale[WEBAUDIO_BLOCK_SIZE]);
+/**
+ * a-rate in place gain.
+ */
+void AudioBufferInPlaceScale(float* aBlock,
+ float* aScale,
+ uint32_t aSize);
+
+/**
* Upmix a mono input to a stereo output, scaling the two output channels by two
* different gain value.
* This algorithm is specified in the WebAudio spec.
*/
void
AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
float aGainL, float aGainR,
float aOutputL[WEBAUDIO_BLOCK_SIZE],
--- a/dom/media/webaudio/AudioNodeEngineNEON.cpp
+++ b/dom/media/webaudio/AudioNodeEngineNEON.cpp
@@ -157,16 +157,57 @@ AudioBufferInPlaceScale_NEON(float* aBlo
}
for (unsigned j = 0; j < dif; ++i, ++j) {
aBlock[i] *= aScale;
}
}
void
+AudioBufferInPlaceScale_NEON(float* aBlock,
+ float* aScale,
+ uint32_t aSize)
+{
+ ASSERT_ALIGNED(aBlock);
+
+ float32x4_t vin0, vin1, vin2, vin3;
+ float32x4_t vout0, vout1, vout2, vout3;
+ float32x4_t vscale0, vscale1, vscale2, vscale3;
+
+ uint32_t dif = aSize % 16;
+ uint32_t vectorSize = aSize - dif;
+ uint32_t i = 0;
+ for (; i < vectorSize; i+=16) {
+ vin0 = vld1q_f32(ADDRESS_OF(aBlock, i));
+ vin1 = vld1q_f32(ADDRESS_OF(aBlock, i+4));
+ vin2 = vld1q_f32(ADDRESS_OF(aBlock, i+8));
+ vin3 = vld1q_f32(ADDRESS_OF(aBlock, i+12));
+
+ vscale0 = vld1q_f32(ADDRESS_OF(aScale, i));
+ vscale1 = vld1q_f32(ADDRESS_OF(aScale, i+4));
+ vscale2 = vld1q_f32(ADDRESS_OF(aScale, i+8));
+ vscale3 = vld1q_f32(ADDRESS_OF(aScale, i+12));
+
+ vout0 = vmulq_f32(vin0, vscale0);
+ vout1 = vmulq_f32(vin1, vscale1);
+ vout2 = vmulq_f32(vin2, vscale2);
+ vout3 = vmulq_f32(vin3, vscale3);
+
+ vst1q_f32(ADDRESS_OF(aBlock, i), vout0);
+ vst1q_f32(ADDRESS_OF(aBlock, i+4), vout1);
+ vst1q_f32(ADDRESS_OF(aBlock, i+8), vout2);
+ vst1q_f32(ADDRESS_OF(aBlock, i+12), vout3);
+ }
+
+ for (unsigned j = 0; j < dif; ++i, ++j) {
+ aBlock[i] *= aScale[i];
+ }
+}
+
+void
AudioBlockPanStereoToStereo_NEON(const float aInputL[WEBAUDIO_BLOCK_SIZE],
const float aInputR[WEBAUDIO_BLOCK_SIZE],
float aGainL, float aGainR, bool aIsOnTheLeft,
float aOutputL[WEBAUDIO_BLOCK_SIZE],
float aOutputR[WEBAUDIO_BLOCK_SIZE])
{
ASSERT_ALIGNED(aInputL);
ASSERT_ALIGNED(aInputR);
--- a/dom/media/webaudio/AudioNodeEngineNEON.h
+++ b/dom/media/webaudio/AudioNodeEngineNEON.h
@@ -23,16 +23,20 @@ void
AudioBlockCopyChannelWithScale_NEON(const float aInput[WEBAUDIO_BLOCK_SIZE],
const float aScale[WEBAUDIO_BLOCK_SIZE],
float aOutput[WEBAUDIO_BLOCK_SIZE]);
void
AudioBufferInPlaceScale_NEON(float* aBlock,
float aScale,
uint32_t aSize);
+void
+AudioBufferInPlaceScale_NEON(float* aBlock,
+ float* aScale,
+ uint32_t aSize);
void
AudioBlockPanStereoToStereo_NEON(const float aInputL[WEBAUDIO_BLOCK_SIZE],
const float aInputR[WEBAUDIO_BLOCK_SIZE],
float aGainL, float aGainR, bool aIsOnTheLeft,
float aOutputL[WEBAUDIO_BLOCK_SIZE],
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
--- a/dom/media/webaudio/AudioNodeEngineSSE2.cpp
+++ b/dom/media/webaudio/AudioNodeEngineSSE2.cpp
@@ -144,16 +144,48 @@ AudioBufferInPlaceScale_SSE(float* aBloc
_mm_store_ps(&aBlock[i], vout0);
_mm_store_ps(&aBlock[i + 4], vout1);
_mm_store_ps(&aBlock[i + 8], vout2);
_mm_store_ps(&aBlock[i + 12], vout3);
}
}
void
+AudioBufferInPlaceScale_SSE(float* aBlock,
+ float* aScale,
+ uint32_t aSize)
+{
+ __m128 vout0, vout1, vout2, vout3,
+ vgain0, vgain1, vgain2, vgain3,
+ vin0, vin1, vin2, vin3;
+
+ ASSERT_ALIGNED16(aBlock);
+ ASSERT_MULTIPLE16(aSize);
+
+ for (unsigned i = 0; i < aSize; i+=16) {
+ vin0 = _mm_load_ps(&aBlock[i]);
+ vin1 = _mm_load_ps(&aBlock[i + 4]);
+ vin2 = _mm_load_ps(&aBlock[i + 8]);
+ vin3 = _mm_load_ps(&aBlock[i + 12]);
+ vgain0 = _mm_load_ps(&aScale[i]);
+ vgain1 = _mm_load_ps(&aScale[i + 4]);
+ vgain2 = _mm_load_ps(&aScale[i + 8]);
+ vgain3 = _mm_load_ps(&aScale[i + 12]);
+ vout0 = _mm_mul_ps(vin0, vgain0);
+ vout1 = _mm_mul_ps(vin1, vgain1);
+ vout2 = _mm_mul_ps(vin2, vgain2);
+ vout3 = _mm_mul_ps(vin3, vgain3);
+ _mm_store_ps(&aBlock[i], vout0);
+ _mm_store_ps(&aBlock[i + 4], vout1);
+ _mm_store_ps(&aBlock[i + 8], vout2);
+ _mm_store_ps(&aBlock[i + 12], vout3);
+ }
+}
+
+void
AudioBlockPanStereoToStereo_SSE(const float aInputL[WEBAUDIO_BLOCK_SIZE],
const float aInputR[WEBAUDIO_BLOCK_SIZE],
float aGainL, float aGainR, bool aIsOnTheLeft,
float aOutputL[WEBAUDIO_BLOCK_SIZE],
float aOutputR[WEBAUDIO_BLOCK_SIZE])
{
__m128 vinl0, vinr0, vinl1, vinr1,
vout0, vout1,
--- a/dom/media/webaudio/AudioNodeEngineSSE2.h
+++ b/dom/media/webaudio/AudioNodeEngineSSE2.h
@@ -21,16 +21,20 @@ void
AudioBlockCopyChannelWithScale_SSE(const float aInput[WEBAUDIO_BLOCK_SIZE],
const float aScale[WEBAUDIO_BLOCK_SIZE],
float aOutput[WEBAUDIO_BLOCK_SIZE]);
void
AudioBufferInPlaceScale_SSE(float* aBlock,
float aScale,
uint32_t aSize);
+void
+AudioBufferInPlaceScale_SSE(float* aBlock,
+ float* aScale,
+ uint32_t aSize);
void
AudioBlockPanStereoToStereo_SSE(const float aInputL[WEBAUDIO_BLOCK_SIZE],
const float aInputR[WEBAUDIO_BLOCK_SIZE],
float aGainL, float aGainR, bool aIsOnTheLeft,
float aOutputL[WEBAUDIO_BLOCK_SIZE],
float aOutputR[WEBAUDIO_BLOCK_SIZE]);