tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AudioNodeEngine.cpp (13505B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "AudioNodeEngine.h"
      8 
      9 #include "mozilla/AbstractThread.h"
     10 #ifdef USE_NEON
     11 #  include "AudioNodeEngineGeneric.h"
     12 #  include "mozilla/arm.h"
     13 #endif
     14 #ifdef USE_SSE2
     15 #  include "AudioNodeEngineGeneric.h"
     16 #  include "mozilla/SSE.h"
     17 #endif
     18 #if defined(USE_SSE42) && defined(USE_FMA3)
     19 #  include "AudioNodeEngineGeneric.h"
     20 #  include "mozilla/SSE.h"
     21 #endif
     22 #include "AudioBlock.h"
     23 #include "Tracing.h"
     24 
     25 namespace mozilla {
     26 
     27 already_AddRefed<ThreadSharedFloatArrayBufferList>
     28 ThreadSharedFloatArrayBufferList::Create(uint32_t aChannelCount, size_t aLength,
     29                                         const mozilla::fallible_t&) {
     30  RefPtr<ThreadSharedFloatArrayBufferList> buffer =
     31      new ThreadSharedFloatArrayBufferList(aChannelCount);
     32 
     33  for (uint32_t i = 0; i < aChannelCount; ++i) {
     34    float* channelData = js_pod_malloc<float>(aLength);
     35    if (!channelData) {
     36      return nullptr;
     37    }
     38 
     39    buffer->SetData(i, channelData, js_free, channelData);
     40  }
     41 
     42  return buffer.forget();
     43 }
     44 
     45 void WriteZeroesToAudioBlock(AudioBlock* aChunk, uint32_t aStart,
     46                             uint32_t aLength) {
     47  MOZ_ASSERT(aStart + aLength <= WEBAUDIO_BLOCK_SIZE);
     48  MOZ_ASSERT(!aChunk->IsNull(), "You should pass a non-null chunk");
     49  if (aLength == 0) {
     50    return;
     51  }
     52 
     53  for (uint32_t i = 0; i < aChunk->ChannelCount(); ++i) {
     54    PodZero(aChunk->ChannelFloatsForWrite(i) + aStart, aLength);
     55  }
     56 }
     57 
     58 void AudioBufferCopyWithScale(const float* aInput, float aScale, float* aOutput,
     59                              uint32_t aSize) {
     60  if (aScale == 1.0f) {
     61    PodCopy(aOutput, aInput, aSize);
     62  } else {
     63    for (uint32_t i = 0; i < aSize; ++i) {
     64      aOutput[i] = aInput[i] * aScale;
     65    }
     66  }
     67 }
     68 
     69 void AudioBufferAddWithScale(const float* aInput, float aScale, float* aOutput,
     70                             uint32_t aSize) {
     71 #ifdef USE_NEON
     72  if (mozilla::supports_neon()) {
     73    Engine<xsimd::neon>::AudioBufferAddWithScale(aInput, aScale, aOutput,
     74                                                 aSize);
     75    return;
     76  }
     77 #endif
     78 
     79 #ifdef USE_SSE2
     80  if (mozilla::supports_sse2()) {
     81 #  if defined(USE_SSE42) && defined(USE_FMA3)
     82    if (mozilla::supports_fma3() && mozilla::supports_sse4_2()) {
     83      Engine<xsimd::fma3<xsimd::sse4_2>>::AudioBufferAddWithScale(
     84          aInput, aScale, aOutput, aSize);
     85    } else
     86 #  endif
     87    {
     88      Engine<xsimd::sse2>::AudioBufferAddWithScale(aInput, aScale, aOutput,
     89                                                   aSize);
     90    }
     91    return;
     92  }
     93 #endif
     94 
     95  if (aScale == 1.0f) {
     96    for (uint32_t i = 0; i < aSize; ++i) {
     97      aOutput[i] += aInput[i];
     98    }
     99  } else {
    100    for (uint32_t i = 0; i < aSize; ++i) {
    101      aOutput[i] += aInput[i] * aScale;
    102    }
    103  }
    104 }
    105 
    106 void AudioBlockAddChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
    107                                   float aScale,
    108                                   float aOutput[WEBAUDIO_BLOCK_SIZE]) {
    109  AudioBufferAddWithScale(aInput, aScale, aOutput, WEBAUDIO_BLOCK_SIZE);
    110 }
    111 
    112 void AudioBlockCopyChannelWithScale(const float* aInput, float aScale,
    113                                    float* aOutput) {
    114  if (aScale == 1.0f) {
    115    memcpy(aOutput, aInput, WEBAUDIO_BLOCK_SIZE * sizeof(float));
    116  } else {
    117 #ifdef USE_NEON
    118    if (mozilla::supports_neon()) {
    119      Engine<xsimd::neon>::AudioBlockCopyChannelWithScale(aInput, aScale,
    120                                                          aOutput);
    121      return;
    122    }
    123 #endif
    124 
    125 #ifdef USE_SSE2
    126    if (mozilla::supports_sse2()) {
    127      Engine<xsimd::sse2>::AudioBlockCopyChannelWithScale(aInput, aScale,
    128                                                          aOutput);
    129      return;
    130    }
    131 #endif
    132 
    133    for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
    134      aOutput[i] = aInput[i] * aScale;
    135    }
    136  }
    137 }
    138 
    139 void BufferComplexMultiply(const float* aInput, const float* aScale,
    140                           float* aOutput, uint32_t aSize) {
    141 #ifdef USE_NEON
    142  if (mozilla::supports_neon()) {
    143    Engine<xsimd::neon>::BufferComplexMultiply(aInput, aScale, aOutput, aSize);
    144    return;
    145  }
    146 #endif
    147 #ifdef USE_SSE2
    148  if (mozilla::supports_sse()) {
    149 #  if defined(USE_SSE42) && defined(USE_FMA3)
    150    if (mozilla::supports_fma3() && mozilla::supports_sse4_2()) {
    151      Engine<xsimd::fma3<xsimd::sse4_2>>::BufferComplexMultiply(aInput, aScale,
    152                                                                aOutput, aSize);
    153    } else
    154 #  endif
    155    {
    156      Engine<xsimd::sse2>::BufferComplexMultiply(aInput, aScale, aOutput,
    157                                                 aSize);
    158    }
    159    return;
    160  }
    161 #endif
    162 
    163  for (uint32_t i = 0; i < aSize * 2; i += 2) {
    164    float real1 = aInput[i];
    165    float imag1 = aInput[i + 1];
    166    float real2 = aScale[i];
    167    float imag2 = aScale[i + 1];
    168    float realResult = real1 * real2 - imag1 * imag2;
    169    float imagResult = real1 * imag2 + imag1 * real2;
    170    aOutput[i] = realResult;
    171    aOutput[i + 1] = imagResult;
    172  }
    173 }
    174 
    175 float AudioBufferPeakValue(const float* aInput, uint32_t aSize) {
    176  float max = 0.0f;
    177  for (uint32_t i = 0; i < aSize; i++) {
    178    float mag = fabs(aInput[i]);
    179    if (mag > max) {
    180      max = mag;
    181    }
    182  }
    183  return max;
    184 }
    185 
    186 void AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
    187                                    const float aScale[WEBAUDIO_BLOCK_SIZE],
    188                                    float aOutput[WEBAUDIO_BLOCK_SIZE]) {
    189 #ifdef USE_NEON
    190  if (mozilla::supports_neon()) {
    191    Engine<xsimd::neon>::AudioBlockCopyChannelWithScale(aInput, aScale,
    192                                                        aOutput);
    193    return;
    194  }
    195 #endif
    196 
    197 #ifdef USE_SSE2
    198  if (mozilla::supports_sse2()) {
    199    Engine<xsimd::sse2>::AudioBlockCopyChannelWithScale(aInput, aScale,
    200                                                        aOutput);
    201    return;
    202  }
    203 #endif
    204 
    205  for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
    206    aOutput[i] = aInput[i] * aScale[i];
    207  }
    208 }
    209 
    210 void AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE], float aScale) {
    211  AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
    212 }
    213 
    214 void AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
    215                            float aScale[WEBAUDIO_BLOCK_SIZE]) {
    216  AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
    217 }
    218 
    219 void AudioBufferInPlaceScale(float* aBlock, float aScale, uint32_t aSize) {
    220  if (aScale == 1.0f) {
    221    return;
    222  }
    223 #ifdef USE_NEON
    224  if (mozilla::supports_neon()) {
    225    Engine<xsimd::neon>::AudioBufferInPlaceScale(aBlock, aScale, aSize);
    226    return;
    227  }
    228 #endif
    229 
    230 #ifdef USE_SSE2
    231  if (mozilla::supports_sse2()) {
    232    Engine<xsimd::sse2>::AudioBufferInPlaceScale(aBlock, aScale, aSize);
    233    return;
    234  }
    235 #endif
    236 
    237  for (uint32_t i = 0; i < aSize; ++i) {
    238    *aBlock++ *= aScale;
    239  }
    240 }
    241 
    242 void AudioBufferInPlaceScale(float* aBlock, float* aScale, uint32_t aSize) {
    243 #ifdef USE_NEON
    244  if (mozilla::supports_neon()) {
    245    Engine<xsimd::neon>::AudioBufferInPlaceScale(aBlock, aScale, aSize);
    246    return;
    247  }
    248 #endif
    249 
    250 #ifdef USE_SSE2
    251  if (mozilla::supports_sse2()) {
    252    Engine<xsimd::sse2>::AudioBufferInPlaceScale(aBlock, aScale, aSize);
    253    return;
    254  }
    255 #endif
    256 
    257  for (uint32_t i = 0; i < aSize; ++i) {
    258    *aBlock++ *= *aScale++;
    259  }
    260 }
    261 
    262 void AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
    263                               float aGainL[WEBAUDIO_BLOCK_SIZE],
    264                               float aGainR[WEBAUDIO_BLOCK_SIZE],
    265                               float aOutputL[WEBAUDIO_BLOCK_SIZE],
    266                               float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
    267  AudioBlockCopyChannelWithScale(aInput, aGainL, aOutputL);
    268  AudioBlockCopyChannelWithScale(aInput, aGainR, aOutputR);
    269 }
    270 
    271 void AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
    272                               float aGainL, float aGainR,
    273                               float aOutputL[WEBAUDIO_BLOCK_SIZE],
    274                               float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
    275  AudioBlockCopyChannelWithScale(aInput, aGainL, aOutputL);
    276  AudioBlockCopyChannelWithScale(aInput, aGainR, aOutputR);
    277 }
    278 
    279 void AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
    280                                 const float aInputR[WEBAUDIO_BLOCK_SIZE],
    281                                 float aGainL, float aGainR, bool aIsOnTheLeft,
    282                                 float aOutputL[WEBAUDIO_BLOCK_SIZE],
    283                                 float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
    284 #ifdef USE_NEON
    285  if (mozilla::supports_neon()) {
    286    Engine<xsimd::neon>::AudioBlockPanStereoToStereo(
    287        aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    288    return;
    289  }
    290 #endif
    291 
    292 #ifdef USE_SSE2
    293  if (mozilla::supports_sse2()) {
    294 #  if defined(USE_SSE42) && defined(USE_FMA3)
    295    if (mozilla::supports_fma3() && mozilla::supports_sse4_2()) {
    296      Engine<xsimd::fma3<xsimd::sse4_2>>::AudioBlockPanStereoToStereo(
    297          aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    298    } else
    299 #  endif
    300    {
    301      Engine<xsimd::sse2>::AudioBlockPanStereoToStereo(
    302          aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    303    }
    304    return;
    305  }
    306 #endif
    307 
    308  uint32_t i;
    309 
    310  if (aIsOnTheLeft) {
    311    for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
    312      aOutputL[i] = aInputL[i] + aInputR[i] * aGainL;
    313      aOutputR[i] = aInputR[i] * aGainR;
    314    }
    315  } else {
    316    for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
    317      aOutputL[i] = aInputL[i] * aGainL;
    318      aOutputR[i] = aInputR[i] + aInputL[i] * aGainR;
    319    }
    320  }
    321 }
    322 
    323 void AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
    324                                 const float aInputR[WEBAUDIO_BLOCK_SIZE],
    325                                 const float aGainL[WEBAUDIO_BLOCK_SIZE],
    326                                 const float aGainR[WEBAUDIO_BLOCK_SIZE],
    327                                 const bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
    328                                 float aOutputL[WEBAUDIO_BLOCK_SIZE],
    329                                 float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
    330 #ifdef USE_NEON
    331  if (mozilla::supports_neon()) {
    332    Engine<xsimd::neon>::AudioBlockPanStereoToStereo(
    333        aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    334    return;
    335  }
    336 #endif
    337 
    338 #ifdef USE_SSE2
    339  if (mozilla::supports_sse2()) {
    340 #  if defined(USE_SSE42) && defined(USE_FMA3)
    341    if (mozilla::supports_fma3() && mozilla::supports_sse4_2()) {
    342      Engine<xsimd::fma3<xsimd::sse2>>::AudioBlockPanStereoToStereo(
    343          aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    344    } else
    345 #  endif
    346    {
    347      Engine<xsimd::sse2>::AudioBlockPanStereoToStereo(
    348          aInputL, aInputR, aGainL, aGainR, aIsOnTheLeft, aOutputL, aOutputR);
    349    }
    350    return;
    351  }
    352 #endif
    353 
    354  uint32_t i;
    355  for (i = 0; i < WEBAUDIO_BLOCK_SIZE; i++) {
    356    if (aIsOnTheLeft[i]) {
    357      aOutputL[i] = aInputL[i] + aInputR[i] * aGainL[i];
    358      aOutputR[i] = aInputR[i] * aGainR[i];
    359    } else {
    360      aOutputL[i] = aInputL[i] * aGainL[i];
    361      aOutputR[i] = aInputR[i] + aInputL[i] * aGainR[i];
    362    }
    363  }
    364 }
    365 
    366 float AudioBufferSumOfSquares(const float* aInput, uint32_t aLength) {
    367 #ifdef USE_NEON
    368  if (mozilla::supports_neon()) {
    369    return Engine<xsimd::neon>::AudioBufferSumOfSquares(aInput, aLength);
    370  }
    371 #endif
    372 
    373 #ifdef USE_SSE2
    374  if (mozilla::supports_sse()) {
    375 #  if defined(USE_SSE42) && defined(USE_FMA3)
    376    if (mozilla::supports_fma3() && mozilla::supports_sse4_2()) {
    377      return Engine<xsimd::fma3<xsimd::sse4_2>>::AudioBufferSumOfSquares(
    378          aInput, aLength);
    379    } else
    380 #  endif
    381    {
    382      return Engine<xsimd::sse2>::AudioBufferSumOfSquares(aInput, aLength);
    383    }
    384  }
    385 #endif
    386 
    387  float sum = 0.f;
    388  while (aLength--) {
    389    sum += *aInput * *aInput;
    390    ++aInput;
    391  }
    392  return sum;
    393 }
    394 
    395 void NaNToZeroInPlace(float* aSamples, size_t aCount) {
    396 #ifdef USE_SSE2
    397  if (mozilla::supports_sse2()) {
    398    Engine<xsimd::sse2>::NaNToZeroInPlace(aSamples, aCount);
    399    return;
    400  }
    401 #endif
    402  for (size_t i = 0; i < aCount; i++) {
    403    if (aSamples[i] != aSamples[i]) {
    404      aSamples[i] = 0.0;
    405    }
    406  }
    407 }
    408 
    409 AudioNodeEngine::AudioNodeEngine(dom::AudioNode* aNode)
    410    : mNode(aNode),
    411      mNodeType(aNode ? aNode->NodeType() : nullptr),
    412      mInputCount(aNode ? aNode->NumberOfInputs() : 1),
    413      mOutputCount(aNode ? aNode->NumberOfOutputs() : 0) {
    414  MOZ_ASSERT(NS_IsMainThread());
    415  MOZ_COUNT_CTOR(AudioNodeEngine);
    416 }
    417 
    418 void AudioNodeEngine::ProcessBlock(AudioNodeTrack* aTrack, GraphTime aFrom,
    419                                   const AudioBlock& aInput,
    420                                   AudioBlock* aOutput, bool* aFinished) {
    421  MOZ_ASSERT(mInputCount <= 1 && mOutputCount <= 1);
    422  TRACE("AudioNodeEngine::ProcessBlock");
    423  *aOutput = aInput;
    424 }
    425 
    426 void AudioNodeEngine::ProcessBlocksOnPorts(AudioNodeTrack* aTrack,
    427                                           GraphTime aFrom,
    428                                           Span<const AudioBlock> aInput,
    429                                           Span<AudioBlock> aOutput,
    430                                           bool* aFinished) {
    431  MOZ_ASSERT(mInputCount > 1 || mOutputCount > 1);
    432  TRACE("AudioNodeEngine::ProcessBlocksOnPorts");
    433  // Only produce one output port, and drop all other input ports.
    434  aOutput[0] = aInput[0];
    435 }
    436 
    437 }  // namespace mozilla