зеркало из https://github.com/mozilla/gecko-dev.git
Bug 957024 - Update PannerNode distance calculations to match the web audio spec; r=karlt
Distances less than refDistance should be treated as refDistance when calculating the gain. MozReview-Commit-ID: JASGb7jLp5L --HG-- extra : rebase_source : 24e0207b7e6482000ec134bbde59ce448eee25f7
This commit is contained in:
Родитель
8f8236ba1e
Коммит
397fdefcf6
|
@ -234,14 +234,14 @@ public:
|
|||
void ComputeAzimuthAndElevation(const ThreeDPoint& position, float& aAzimuth, float& aElevation);
|
||||
float ComputeConeGain(const ThreeDPoint& position, const ThreeDPoint& orientation);
|
||||
// Compute how much the distance contributes to the gain reduction.
|
||||
float ComputeDistanceGain(const ThreeDPoint& position);
|
||||
double ComputeDistanceGain(const ThreeDPoint& position);
|
||||
|
||||
void EqualPowerPanningFunction(const AudioBlock& aInput, AudioBlock* aOutput, StreamTime tick);
|
||||
void HRTFPanningFunction(const AudioBlock& aInput, AudioBlock* aOutput, StreamTime tick);
|
||||
|
||||
float LinearGainFunction(float aDistance);
|
||||
float InverseGainFunction(float aDistance);
|
||||
float ExponentialGainFunction(float aDistance);
|
||||
float LinearGainFunction(double aDistance);
|
||||
float InverseGainFunction(double aDistance);
|
||||
float ExponentialGainFunction(double aDistance);
|
||||
|
||||
ThreeDPoint ConvertAudioParamTimelineTo3DP(AudioParamTimeline& aX, AudioParamTimeline& aY, AudioParamTimeline& aZ, StreamTime& tick);
|
||||
|
||||
|
@ -267,7 +267,7 @@ public:
|
|||
nsAutoPtr<HRTFPanner> mHRTFPanner;
|
||||
typedef void (PannerNodeEngine::*PanningModelFunction)(const AudioBlock& aInput, AudioBlock* aOutput, StreamTime tick);
|
||||
PanningModelFunction mPanningModelFunction;
|
||||
typedef float (PannerNodeEngine::*DistanceModelFunction)(float aDistance);
|
||||
typedef float (PannerNodeEngine::*DistanceModelFunction)(double aDistance);
|
||||
DistanceModelFunction mDistanceModelFunction;
|
||||
AudioParamTimeline mPositionX;
|
||||
AudioParamTimeline mPositionY;
|
||||
|
@ -370,21 +370,21 @@ void PannerNode::DestroyMediaStream()
|
|||
|
||||
// Those three functions are described in the spec.
|
||||
float
|
||||
PannerNodeEngine::LinearGainFunction(float aDistance)
|
||||
PannerNodeEngine::LinearGainFunction(double aDistance)
|
||||
{
|
||||
return 1 - mRolloffFactor * (aDistance - mRefDistance) / (mMaxDistance - mRefDistance);
|
||||
return 1 - mRolloffFactor * (std::max(std::min(aDistance, mMaxDistance), mRefDistance) - mRefDistance) / (mMaxDistance - mRefDistance);
|
||||
}
|
||||
|
||||
float
|
||||
PannerNodeEngine::InverseGainFunction(float aDistance)
|
||||
PannerNodeEngine::InverseGainFunction(double aDistance)
|
||||
{
|
||||
return mRefDistance / (mRefDistance + mRolloffFactor * (aDistance - mRefDistance));
|
||||
return mRefDistance / (mRefDistance + mRolloffFactor * (std::max(aDistance, mRefDistance) - mRefDistance));
|
||||
}
|
||||
|
||||
float
|
||||
PannerNodeEngine::ExponentialGainFunction(float aDistance)
|
||||
PannerNodeEngine::ExponentialGainFunction(double aDistance)
|
||||
{
|
||||
return pow(aDistance / mRefDistance, -mRolloffFactor);
|
||||
return pow(std::max(aDistance, mRefDistance) / mRefDistance, -mRolloffFactor);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -683,7 +683,7 @@ PannerNodeEngine::ComputeConeGain(const ThreeDPoint& position,
|
|||
return gain;
|
||||
}
|
||||
|
||||
float
|
||||
double
|
||||
PannerNodeEngine::ComputeDistanceGain(const ThreeDPoint& position)
|
||||
{
|
||||
ThreeDPoint distanceVec = position - mListenerPosition;
|
||||
|
|
|
@ -173,6 +173,7 @@ skip-if = (toolkit == 'gonk' && !debug) || (toolkit == 'android') || (os == 'mac
|
|||
[test_pannerNode.html]
|
||||
[test_pannerNode_equalPower.html]
|
||||
[test_pannerNodeAbove.html]
|
||||
[test_pannerNodeAtZeroDistance.html]
|
||||
[test_pannerNodeChannelCount.html]
|
||||
[test_pannerNodeHRTFSymmetry.html]
|
||||
[test_pannerNodeTail.html]
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test PannerNode produces output even when the even when the distance is from the listener is zero</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var BUF_SIZE = 128;
|
||||
|
||||
var types = [
|
||||
"equalpower",
|
||||
"HRTF"
|
||||
]
|
||||
|
||||
var finished = types.length;
|
||||
|
||||
function finish() {
|
||||
if (!--finished) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function test(type) {
|
||||
var ac = new OfflineAudioContext(1, BUF_SIZE, 44100);
|
||||
|
||||
// A sine to be used to fill the buffers
|
||||
function sine(t) {
|
||||
return Math.sin(440 * 2 * Math.PI * t / ac.sampleRate);
|
||||
}
|
||||
|
||||
var monoBuffer = ac.createBuffer(1, BUF_SIZE, ac.sampleRate);
|
||||
for (var i = 0; i < BUF_SIZE; ++i) {
|
||||
monoBuffer.getChannelData(0)[i] = sine(i);
|
||||
}
|
||||
|
||||
var monoSource = ac.createBufferSource();
|
||||
monoSource.buffer = monoBuffer;
|
||||
monoSource.start(0);
|
||||
|
||||
var panner = ac.createPanner();
|
||||
panner.distanceModel = "linear";
|
||||
panner.refDistance = 1;
|
||||
panner.positionX.value = 0;
|
||||
panner.positionY.value = 0;
|
||||
panner.positionZ.value = 0;
|
||||
monoSource.connect(panner);
|
||||
|
||||
var panner2 = ac.createPanner();
|
||||
panner2.distanceModel = "inverse";
|
||||
panner2.refDistance = 1;
|
||||
panner2.positionX.value = 0;
|
||||
panner2.positionY.value = 0;
|
||||
panner2.positionZ.value = 0;
|
||||
panner.connect(panner2);
|
||||
|
||||
var panner3 = ac.createPanner();
|
||||
panner3.distanceModel = "exponential";
|
||||
panner3.refDistance = 1;
|
||||
panner3.positionX.value = 0;
|
||||
panner3.positionY.value = 0;
|
||||
panner3.positionZ.value = 0;
|
||||
panner2.connect(panner3);
|
||||
|
||||
panner3.connect(ac.destination);
|
||||
|
||||
ac.startRendering().then(function(buffer) {
|
||||
compareBuffers(buffer, monoBuffer);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
types.forEach(test);
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче