Bug 1472550 - Add Audio{Buffer,Block}InPlaceScale that takes an array of gain values, with SSE and NEON variants. r=dminor draft
authorPaul Adenot <paul@paul.cx>
Fri, 06 Jul 2018 15:18:06 +0200
changeset 817781 4697a44f5369279a060d63ac495fdb034e35202b
parent 817312 fe17acc6e291e54463db3ea82697c714ae5a4b27
child 817782 29aabddc7caf16427330687acbab91f9c3047d32
push id116162
push userpaul@paul.cx
push dateFri, 13 Jul 2018 12:47:51 +0000
reviewersdminor
bugs1472550
milestone63.0a1
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
dom/media/webaudio/AudioNodeEngine.cpp
dom/media/webaudio/AudioNodeEngine.h
dom/media/webaudio/AudioNodeEngineNEON.cpp
dom/media/webaudio/AudioNodeEngineNEON.h
dom/media/webaudio/AudioNodeEngineSSE2.cpp
dom/media/webaudio/AudioNodeEngineSSE2.h
--- 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]);