author | Karl Tomlinson <karlt+@karlt.net> |
Tue, 30 Sep 2014 18:10:03 +1300 | |
changeset 208296 | fce56d505b2e116bb1e5bd453905a9c8fa92478d |
parent 208295 | a3e9214bfcce9698f99c08ac6795078759819b6e |
child 208297 | fd256e9a9dbccde2edd291e1bb0b4cf86114267f |
push id | 49886 |
push user | ktomlinson@mozilla.com |
push date | Thu, 02 Oct 2014 00:23:33 +0000 |
treeherder | mozilla-inbound@fce56d505b2e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | rillian |
bugs | 1012609 |
milestone | 35.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/media/webaudio/OscillatorNode.cpp +++ b/content/media/webaudio/OscillatorNode.cpp @@ -368,46 +368,54 @@ public: void ComputeCustom(float* aOutput, TrackTicks ticks, uint32_t aStart, uint32_t aEnd) { MOZ_ASSERT(mPeriodicWave, "No custom waveform data"); uint32_t periodicWaveSize = mPeriodicWave->periodicWaveSize(); + // Mask to wrap wave data indices into the range [0,periodicWaveSize). + uint32_t indexMask = periodicWaveSize - 1; + MOZ_ASSERT(periodicWaveSize && (periodicWaveSize & indexMask) == 0, + "periodicWaveSize must be power of 2"); float* higherWaveData = nullptr; float* lowerWaveData = nullptr; float tableInterpolationFactor; // Phase increment at frequency of 1 Hz. // mPhase runs [0,periodicWaveSize) here instead of [0,2*M_PI). float basePhaseIncrement = static_cast<float>(periodicWaveSize) / mSource->SampleRate(); for (uint32_t i = aStart; i < aEnd; ++i) { UpdateParametersIfNeeded(ticks, i); mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, lowerWaveData, higherWaveData, tableInterpolationFactor); - mPhase = fmod(mPhase, periodicWaveSize); // Bilinear interpolation between adjacent samples in each table. - uint32_t j1 = floor(mPhase); + float floorPhase = floorf(mPhase); + uint32_t j1 = floorPhase; + j1 &= indexMask; uint32_t j2 = j1 + 1; - if (j2 >= periodicWaveSize) { - j2 -= periodicWaveSize; - } - float sampleInterpolationFactor = mPhase - j1; + j2 &= indexMask; + + float sampleInterpolationFactor = mPhase - floorPhase; + float lower = (1.0f - sampleInterpolationFactor) * lowerWaveData[j1] + sampleInterpolationFactor * lowerWaveData[j2]; float higher = (1.0f - sampleInterpolationFactor) * higherWaveData[j1] + sampleInterpolationFactor * higherWaveData[j2]; aOutput[i] = (1.0f - tableInterpolationFactor) * lower + tableInterpolationFactor * higher; - mPhase += basePhaseIncrement * mFinalFrequency; + // Calculate next phase position from wrapped value j1 to avoid loss of + // precision at large values. + mPhase = + j1 + sampleInterpolationFactor + basePhaseIncrement * mFinalFrequency; } } void ComputeSilence(AudioChunk *aOutput) { aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); }