зеркало из https://github.com/mozilla/gecko-dev.git
Bug 853360 - Implement the coneGain part of the AudioPannerNode. r=roc
This commit is contained in:
Родитель
c8964509cc
Коммит
633978e79e
|
@ -117,7 +117,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation);
|
void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation);
|
||||||
void DistanceGain(AudioChunk* aChunk, float aGain);
|
void DistanceAndConeGain(AudioChunk* aChunk, float aGain);
|
||||||
|
float ComputeConeGain();
|
||||||
|
|
||||||
void GainMonoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
void GainMonoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||||
float aGainL, float aGainR);
|
float aGainL, float aGainR);
|
||||||
|
@ -226,7 +227,7 @@ void
|
||||||
PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
|
PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
|
||||||
AudioChunk* aOutput)
|
AudioChunk* aOutput)
|
||||||
{
|
{
|
||||||
float azimuth, elevation, gainL, gainR, normalizedAzimuth, distance, distanceGain;
|
float azimuth, elevation, gainL, gainR, normalizedAzimuth, distance, distanceGain, coneGain;
|
||||||
int inputChannels = aInput.mChannelData.Length();
|
int inputChannels = aInput.mChannelData.Length();
|
||||||
ThreeDPoint distanceVec;
|
ThreeDPoint distanceVec;
|
||||||
|
|
||||||
|
@ -242,6 +243,7 @@ PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
|
||||||
AllocateAudioBlock(2, aOutput);
|
AllocateAudioBlock(2, aOutput);
|
||||||
|
|
||||||
ComputeAzimuthAndElevation(azimuth, elevation);
|
ComputeAzimuthAndElevation(azimuth, elevation);
|
||||||
|
coneGain = ComputeConeGain();
|
||||||
|
|
||||||
// The following algorithm is described in the spec.
|
// The following algorithm is described in the spec.
|
||||||
// Clamp azimuth in the [-90, 90] range.
|
// Clamp azimuth in the [-90, 90] range.
|
||||||
|
@ -281,7 +283,7 @@ PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
|
||||||
GainStereoToStereo(aInput, aOutput, gainL, gainR, azimuth);
|
GainStereoToStereo(aInput, aOutput, gainL, gainR, azimuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
DistanceGain(aOutput, distanceGain);
|
DistanceAndConeGain(aOutput, distanceGain * coneGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -308,7 +310,7 @@ PannerNodeEngine::GainStereoToStereo(const AudioChunk& aInput, AudioChunk* aOutp
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PannerNodeEngine::DistanceGain(AudioChunk* aChunk, float aGain)
|
PannerNodeEngine::DistanceAndConeGain(AudioChunk* aChunk, float aGain)
|
||||||
{
|
{
|
||||||
float* samples = static_cast<float*>(const_cast<void*>(*aChunk->mChannelData.Elements()));
|
float* samples = static_cast<float*>(const_cast<void*>(*aChunk->mChannelData.Elements()));
|
||||||
uint32_t channelCount = aChunk->mChannelData.Length();
|
uint32_t channelCount = aChunk->mChannelData.Length();
|
||||||
|
@ -371,6 +373,48 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This algorithm is described in the WebAudio spec.
|
||||||
|
float
|
||||||
|
PannerNodeEngine::ComputeConeGain()
|
||||||
|
{
|
||||||
|
// Omnidirectional source
|
||||||
|
if (mOrientation.IsZero() || ((mConeInnerAngle == 360) && (mConeOuterAngle == 360))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalized source-listener vector
|
||||||
|
ThreeDPoint sourceToListener = mListenerPosition - mPosition;
|
||||||
|
sourceToListener.Normalize();
|
||||||
|
|
||||||
|
ThreeDPoint normalizedSourceOrientation = mOrientation;
|
||||||
|
normalizedSourceOrientation.Normalize();
|
||||||
|
|
||||||
|
// Angle between the source orientation vector and the source-listener vector
|
||||||
|
double dotProduct = sourceToListener.DotProduct(normalizedSourceOrientation);
|
||||||
|
double angle = 180 * acos(dotProduct) / M_PI;
|
||||||
|
double absAngle = fabs(angle);
|
||||||
|
|
||||||
|
// Divide by 2 here since API is entire angle (not half-angle)
|
||||||
|
double absInnerAngle = fabs(mConeInnerAngle) / 2;
|
||||||
|
double absOuterAngle = fabs(mConeOuterAngle) / 2;
|
||||||
|
double gain = 1;
|
||||||
|
|
||||||
|
if (absAngle <= absInnerAngle) {
|
||||||
|
// No attenuation
|
||||||
|
gain = 1;
|
||||||
|
} else if (absAngle >= absOuterAngle) {
|
||||||
|
// Max attenuation
|
||||||
|
gain = mConeOuterGain;
|
||||||
|
} else {
|
||||||
|
// Between inner and outer cones
|
||||||
|
// inner -> outer, x goes from 0 -> 1
|
||||||
|
double x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle);
|
||||||
|
gain = (1 - x) + mConeOuterGain * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче