Bug 1105513 - Add a NEON version for AudioBlockPanStereoToStereo when aIsOnTheLeft is an array r=padenot draft
authorDan Minor <dminor@mozilla.com>
Thu, 17 Dec 2015 13:15:54 -0500
changeset 318711 9905b14962aec450f3b439026124d05e4b4accf3
parent 318506 d7a0ad85d9fb77916f9d77d62697b852f3dc63e6
child 512485 a53dd0f06e3a37ed1ebb2c9e39d1bea693573285
push id8912
push userdminor@mozilla.com
push dateMon, 04 Jan 2016 18:29:57 +0000
reviewerspadenot
bugs1105513
milestone46.0a1
Bug 1105513 - Add a NEON version for AudioBlockPanStereoToStereo when aIsOnTheLeft is an array r=padenot
dom/media/webaudio/AudioNodeEngine.cpp
dom/media/webaudio/AudioNodeEngineNEON.cpp
dom/media/webaudio/AudioNodeEngineNEON.h
--- a/dom/media/webaudio/AudioNodeEngine.cpp
+++ b/dom/media/webaudio/AudioNodeEngine.cpp
@@ -240,17 +240,22 @@ AudioBlockPanStereoToStereo(const float 
                             const float aInputR[WEBAUDIO_BLOCK_SIZE],
                             float aGainL[WEBAUDIO_BLOCK_SIZE],
                             float aGainR[WEBAUDIO_BLOCK_SIZE],
                             bool  aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
                             float aOutputL[WEBAUDIO_BLOCK_SIZE],
                             float aOutputR[WEBAUDIO_BLOCK_SIZE])
 {
 #ifdef BUILD_ARM_NEON
-  // No NEON version yet: bug 1105513
+   if (mozilla::supports_neon()) {
+     AudioBlockPanStereoToStereo_NEON(aInputL, aInputR,
+                                      aGainL, aGainR, aIsOnTheLeft,
+                                      aOutputL, aOutputR);
+    return;
+  }
 #endif
 
   uint32_t i;
   for (i = 0; i < WEBAUDIO_BLOCK_SIZE; i++) {
     if (aIsOnTheLeft[i]) {
       aOutputL[i] = aInputL[i] + aInputR[i] * aGainL[i];
       aOutputR[i] = aInputR[i] * aGainR[i];
     } else {
--- a/dom/media/webaudio/AudioNodeEngineNEON.cpp
+++ b/dom/media/webaudio/AudioNodeEngineNEON.cpp
@@ -217,9 +217,102 @@ AudioBlockPanStereoToStereo_NEON(const f
       voutR0 = vmlaq_f32(vinR0, vinL0, vscaleR);
       voutR1 = vmlaq_f32(vinR1, vinL1, vscaleR);
 
       vst1q_f32(ADDRESS_OF(aOutputR, i), voutR0);
       vst1q_f32(ADDRESS_OF(aOutputR, i+4), voutR1);
     }
   }
 }
+
+void
+AudioBlockPanStereoToStereo_NEON(const float aInputL[WEBAUDIO_BLOCK_SIZE],
+                                 const float aInputR[WEBAUDIO_BLOCK_SIZE],
+                                 float aGainL[WEBAUDIO_BLOCK_SIZE],
+                                 float aGainR[WEBAUDIO_BLOCK_SIZE],
+                                 const bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
+                                 float aOutputL[WEBAUDIO_BLOCK_SIZE],
+                                 float aOutputR[WEBAUDIO_BLOCK_SIZE])
+{
+  ASSERT_ALIGNED(aInputL);
+  ASSERT_ALIGNED(aInputR);
+  ASSERT_ALIGNED(aGainL);
+  ASSERT_ALIGNED(aGainR);
+  ASSERT_ALIGNED(aIsOnTheLeft);
+  ASSERT_ALIGNED(aOutputL);
+  ASSERT_ALIGNED(aOutputR);
+
+  float32x4_t vinL0, vinL1;
+  float32x4_t vinR0, vinR1;
+  float32x4_t voutL0, voutL1;
+  float32x4_t voutR0, voutR1;
+  float32x4_t vscaleL0, vscaleL1;
+  float32x4_t vscaleR0, vscaleR1;
+  float32x4_t onleft0, onleft1, notonleft0, notonleft1;
+
+  float32x4_t zero = {0, 0, 0, 0};
+  uint8x8_t isOnTheLeft;
+
+  for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; i+=8) {
+    vinL0 = vld1q_f32(ADDRESS_OF(aInputL, i));
+    vinL1 = vld1q_f32(ADDRESS_OF(aInputL, i+4));
+
+    vinR0 = vld1q_f32(ADDRESS_OF(aInputR, i));
+    vinR1 = vld1q_f32(ADDRESS_OF(aInputR, i+4));
+
+    vscaleL0 = vld1q_f32(ADDRESS_OF(aGainL, i));
+    vscaleL1 = vld1q_f32(ADDRESS_OF(aGainL, i+4));
+
+    vscaleR0 = vld1q_f32(ADDRESS_OF(aGainR, i));
+    vscaleR1 = vld1q_f32(ADDRESS_OF(aGainR, i+4));
+
+    // Load output with boolean "on the left" values. This assumes that
+    // bools are stored as a single byte.
+    isOnTheLeft = vld1_u8((uint8_t *)&aIsOnTheLeft[i]);
+    voutL0 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 0), voutL0, 0);
+    voutL0 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 1), voutL0, 1);
+    voutL0 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 2), voutL0, 2);
+    voutL0 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 3), voutL0, 3);
+    voutL1 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 4), voutL1, 0);
+    voutL1 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 5), voutL1, 1);
+    voutL1 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 6), voutL1, 2);
+    voutL1 = vsetq_lane_f32(vget_lane_u8(isOnTheLeft, 7), voutL1, 3);
+
+    // Convert the boolean values into masks by setting all bits to 1
+    // if true.
+    voutL0 = (float32x4_t)vcgtq_f32(voutL0, zero);
+    voutL1 = (float32x4_t)vcgtq_f32(voutL1, zero);
+
+    // The right output masks are the same as the left masks
+    voutR0 = voutL0;
+    voutR1 = voutL1;
+
+    // Calculate left channel assuming isOnTheLeft
+    onleft0 = vmlaq_f32(vinL0, vinR0, vscaleL0);
+    onleft1 = vmlaq_f32(vinL1, vinR1, vscaleL0);
+
+    // Calculate left channel assuming not isOnTheLeft
+    notonleft0 = vmulq_f32(vinL0, vscaleL0);
+    notonleft1 = vmulq_f32(vinL1, vscaleL1);
+
+    // Write results using previously stored masks
+    voutL0 = vbslq_f32((uint32x4_t)voutL0, onleft0, notonleft0);
+    voutL1 = vbslq_f32((uint32x4_t)voutL1, onleft1, notonleft1);
+
+    // Calculate right channel assuming isOnTheLeft
+    onleft0 = vmulq_f32(vinR0, vscaleR0);
+    onleft1 = vmulq_f32(vinR1, vscaleR1);
+
+    // Calculate right channel assuming not isOnTheLeft
+    notonleft0 = vmlaq_f32(vinR0, vinL0, vscaleR0);
+    notonleft1 = vmlaq_f32(vinR1, vinL1, vscaleR1);
+
+    // Write results using previously stored masks
+    voutR0 = vbslq_f32((uint32x4_t)voutR0, onleft0, notonleft0);
+    voutR1 = vbslq_f32((uint32x4_t)voutR1, onleft1, notonleft1);
+
+    vst1q_f32(ADDRESS_OF(aOutputL, i), voutL0);
+    vst1q_f32(ADDRESS_OF(aOutputL, i+4), voutL1);
+    vst1q_f32(ADDRESS_OF(aOutputR, i), voutR0);
+    vst1q_f32(ADDRESS_OF(aOutputR, i+4), voutR1);
+  }
 }
+}
--- a/dom/media/webaudio/AudioNodeEngineNEON.h
+++ b/dom/media/webaudio/AudioNodeEngineNEON.h
@@ -30,11 +30,20 @@ AudioBufferInPlaceScale_NEON(float* aBlo
                              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]);
+
+void
+AudioBlockPanStereoToStereo_NEON(const float aInputL[WEBAUDIO_BLOCK_SIZE],
+                                 const float aInputR[WEBAUDIO_BLOCK_SIZE],
+                                 float aGainL[WEBAUDIO_BLOCK_SIZE],
+                                 float aGainR[WEBAUDIO_BLOCK_SIZE],
+                                 const bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
+                                 float aOutputL[WEBAUDIO_BLOCK_SIZE],
+                                 float aOutputR[WEBAUDIO_BLOCK_SIZE]);
 }
 
 #endif /* MOZILLA_AUDIONODEENGINENEON_H_ */