Bug 1472550 - Add Audio{Buffer,Block}InPlaceScale that takes an array of gain values, with SSE and NEON variants. r=dminor
authorPaul Adenot <paul@paul.cx>
Fri, 06 Jul 2018 15:18:06 +0200
changeset 481585 bed4190ce013a59f68d04bea242d2646ce1afc47
parent 481584 a8f40ce410cb382b90b178ae58391af22bb4c37c
child 481586 ab307640537f53949779e02c21ad1069357252bf
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdminor
bugs1472550
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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]);