mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 17:16:12 +00:00
c689dbd103
This code is specific to Web Audio, and is not really part of the MediaStreamGraph code. I've always hated how these files being in two directories gets in the way while hacking on this code. --HG-- rename : content/media/AudioNodeEngine.cpp => content/media/webaudio/AudioNodeEngine.cpp rename : content/media/AudioNodeEngine.h => content/media/webaudio/AudioNodeEngine.h rename : content/media/AudioNodeEngineNEON.cpp => content/media/webaudio/AudioNodeEngineNEON.cpp rename : content/media/AudioNodeEngineNEON.h => content/media/webaudio/AudioNodeEngineNEON.h rename : content/media/AudioNodeExternalInputStream.cpp => content/media/webaudio/AudioNodeExternalInputStream.cpp rename : content/media/AudioNodeExternalInputStream.h => content/media/webaudio/AudioNodeExternalInputStream.h rename : content/media/AudioNodeStream.cpp => content/media/webaudio/AudioNodeStream.cpp rename : content/media/AudioNodeStream.h => content/media/webaudio/AudioNodeStream.h
241 lines
6.5 KiB
C++
241 lines
6.5 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "AudioNodeEngine.h"
|
|
#ifdef BUILD_ARM_NEON
|
|
#include "mozilla/arm.h"
|
|
#include "AudioNodeEngineNEON.h"
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
|
|
void
|
|
AllocateAudioBlock(uint32_t aChannelCount, AudioChunk* aChunk)
|
|
{
|
|
CheckedInt<size_t> size = WEBAUDIO_BLOCK_SIZE;
|
|
size *= aChannelCount;
|
|
size *= sizeof(float);
|
|
if (!size.isValid()) {
|
|
MOZ_CRASH();
|
|
}
|
|
// XXX for SIMD purposes we should do something here to make sure the
|
|
// channel buffers are 16-byte aligned.
|
|
nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(size.value());
|
|
aChunk->mDuration = WEBAUDIO_BLOCK_SIZE;
|
|
aChunk->mChannelData.SetLength(aChannelCount);
|
|
float* data = static_cast<float*>(buffer->Data());
|
|
for (uint32_t i = 0; i < aChannelCount; ++i) {
|
|
aChunk->mChannelData[i] = data + i*WEBAUDIO_BLOCK_SIZE;
|
|
}
|
|
aChunk->mBuffer = buffer.forget();
|
|
aChunk->mVolume = 1.0f;
|
|
aChunk->mBufferFormat = AUDIO_FORMAT_FLOAT32;
|
|
}
|
|
|
|
void
|
|
WriteZeroesToAudioBlock(AudioChunk* aChunk, uint32_t aStart, uint32_t aLength)
|
|
{
|
|
MOZ_ASSERT(aStart + aLength <= WEBAUDIO_BLOCK_SIZE);
|
|
MOZ_ASSERT(!aChunk->IsNull(), "You should pass a non-null chunk");
|
|
if (aLength == 0)
|
|
return;
|
|
for (uint32_t i = 0; i < aChunk->mChannelData.Length(); ++i) {
|
|
memset(static_cast<float*>(const_cast<void*>(aChunk->mChannelData[i])) + aStart,
|
|
0, aLength*sizeof(float));
|
|
}
|
|
}
|
|
|
|
void AudioBufferCopyWithScale(const float* aInput,
|
|
float aScale,
|
|
float* aOutput,
|
|
uint32_t aSize)
|
|
{
|
|
if (aScale == 1.0f) {
|
|
PodCopy(aOutput, aInput, aSize);
|
|
} else {
|
|
for (uint32_t i = 0; i < aSize; ++i) {
|
|
aOutput[i] = aInput[i]*aScale;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AudioBufferAddWithScale(const float* aInput,
|
|
float aScale,
|
|
float* aOutput,
|
|
uint32_t aSize)
|
|
{
|
|
#ifdef BUILD_ARM_NEON
|
|
if (mozilla::supports_neon()) {
|
|
AudioBufferAddWithScale_NEON(aInput, aScale, aOutput, aSize);
|
|
return;
|
|
}
|
|
#endif
|
|
if (aScale == 1.0f) {
|
|
for (uint32_t i = 0; i < aSize; ++i) {
|
|
aOutput[i] += aInput[i];
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < aSize; ++i) {
|
|
aOutput[i] += aInput[i]*aScale;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
AudioBlockAddChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
|
float aScale,
|
|
float aOutput[WEBAUDIO_BLOCK_SIZE])
|
|
{
|
|
AudioBufferAddWithScale(aInput, aScale, aOutput, WEBAUDIO_BLOCK_SIZE);
|
|
}
|
|
|
|
void
|
|
AudioBlockCopyChannelWithScale(const float* aInput,
|
|
float aScale,
|
|
float* aOutput)
|
|
{
|
|
if (aScale == 1.0f) {
|
|
memcpy(aOutput, aInput, WEBAUDIO_BLOCK_SIZE*sizeof(float));
|
|
} else {
|
|
#ifdef BUILD_ARM_NEON
|
|
if (mozilla::supports_neon()) {
|
|
AudioBlockCopyChannelWithScale_NEON(aInput, aScale, aOutput);
|
|
return;
|
|
}
|
|
#endif
|
|
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
|
aOutput[i] = aInput[i]*aScale;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
BufferComplexMultiply(const float* aInput,
|
|
const float* aScale,
|
|
float* aOutput,
|
|
uint32_t aSize)
|
|
{
|
|
for (uint32_t i = 0; i < aSize * 2; i += 2) {
|
|
float real1 = aInput[i];
|
|
float imag1 = aInput[i + 1];
|
|
float real2 = aScale[i];
|
|
float imag2 = aScale[i + 1];
|
|
float realResult = real1 * real2 - imag1 * imag2;
|
|
float imagResult = real1 * imag2 + imag1 * real2;
|
|
aOutput[i] = realResult;
|
|
aOutput[i + 1] = imagResult;
|
|
}
|
|
}
|
|
|
|
float
|
|
AudioBufferPeakValue(const float *aInput, uint32_t aSize)
|
|
{
|
|
float max = 0.0f;
|
|
for (uint32_t i = 0; i < aSize; i++) {
|
|
float mag = fabs(aInput[i]);
|
|
if (mag > max) {
|
|
max = mag;
|
|
}
|
|
}
|
|
return max;
|
|
}
|
|
|
|
void
|
|
AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
|
const float aScale[WEBAUDIO_BLOCK_SIZE],
|
|
float aOutput[WEBAUDIO_BLOCK_SIZE])
|
|
{
|
|
#ifdef BUILD_ARM_NEON
|
|
if (mozilla::supports_neon()) {
|
|
AudioBlockCopyChannelWithScale_NEON(aInput, aScale, aOutput);
|
|
return;
|
|
}
|
|
#endif
|
|
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
|
aOutput[i] = aInput[i]*aScale[i];
|
|
}
|
|
}
|
|
|
|
void
|
|
AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
|
|
float aScale)
|
|
{
|
|
AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
|
|
}
|
|
|
|
void
|
|
AudioBufferInPlaceScale(float* aBlock,
|
|
float aScale,
|
|
uint32_t aSize)
|
|
{
|
|
if (aScale == 1.0f) {
|
|
return;
|
|
}
|
|
#ifdef BUILD_ARM_NEON
|
|
if (mozilla::supports_neon()) {
|
|
AudioBufferInPlaceScale_NEON(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, float aGainR,
|
|
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
|
float aOutputR[WEBAUDIO_BLOCK_SIZE])
|
|
{
|
|
AudioBlockCopyChannelWithScale(aInput, aGainL, aOutputL);
|
|
AudioBlockCopyChannelWithScale(aInput, aGainR, aOutputR);
|
|
}
|
|
|
|
void
|
|
AudioBlockPanStereoToStereo(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])
|
|
{
|
|
#ifdef BUILD_ARM_NEON
|
|
if (mozilla::supports_neon()) {
|
|
AudioBlockPanStereoToStereo_NEON(aInputL, aInputR,
|
|
aGainL, aGainR, aIsOnTheLeft,
|
|
aOutputL, aOutputR);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
uint32_t i;
|
|
|
|
if (aIsOnTheLeft) {
|
|
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
|
*aOutputL++ = *aInputL++ + *aInputR * aGainL;
|
|
*aOutputR++ = *aInputR++ * aGainR;
|
|
}
|
|
} else {
|
|
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
|
*aOutputL++ = *aInputL * aGainL;
|
|
*aOutputR++ = *aInputR++ + *aInputL++ * aGainR;
|
|
}
|
|
}
|
|
}
|
|
|
|
float
|
|
AudioBufferSumOfSquares(const float* aInput, uint32_t aLength)
|
|
{
|
|
float sum = 0.0f;
|
|
while (aLength--) {
|
|
sum += *aInput * *aInput;
|
|
++aInput;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
}
|