Coverage Report

Created: 2018-09-25 14:53

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