Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
AnalyserNode's getByteFrequencyData() / getFloatFrequencyData() shoul…
…d only do FFT analysis once per render quantum

https://bugs.webkit.org/show_bug.cgi?id=216735

Reviewed by Darin Adler.

Source/WebCore:

AnalyserNode's getByteFrequencyData() / getFloatFrequencyData() should only do FFT analysis once per render quantum:
- https://www.w3.org/TR/webaudio/#dom-analysernode-getbytefrequencydata

"""
If another call to getByteFrequencyData() or getFloatFrequencyData() occurs within the same render quantum as a
previous call, the current frequency data is not updated with the same data. Instead, the previously computed data
is returned.
"""

No new tests, rebaselined existing test.

* Modules/webaudio/RealtimeAnalyser.cpp:
(WebCore::RealtimeAnalyser::writeInput):
(WebCore::RealtimeAnalyser::doFFTAnalysisIfNecessary):
(WebCore::RealtimeAnalyser::getFloatFrequencyData):
(WebCore::RealtimeAnalyser::getByteFrequencyData):
* Modules/webaudio/RealtimeAnalyser.h:

LayoutTests:

Rebaseline webaudio tests now that more checks are passing.

* webaudio/Analyser/realtimeanalyser-freq-data-smoothing-expected.txt:
* webaudio/Analyser/realtimeanalyser-multiple-calls-expected.txt:


Canonical link: https://commits.webkit.org/229568@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267349 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Sep 21, 2020
1 parent adc85d7 commit d86206d
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 61 deletions.
12 changes: 12 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
2020-09-21 Chris Dumez <cdumez@apple.com>

AnalyserNode's getByteFrequencyData() / getFloatFrequencyData() should only do FFT analysis once per render quantum
https://bugs.webkit.org/show_bug.cgi?id=216735

Reviewed by Darin Adler.

Rebaseline webaudio tests now that more checks are passing.

* webaudio/Analyser/realtimeanalyser-freq-data-smoothing-expected.txt:
* webaudio/Analyser/realtimeanalyser-multiple-calls-expected.txt:

2020-09-21 Chris Dumez <cdumez@apple.com>

AnalyserNode should downmix input audio to mono
Expand Down
Expand Up @@ -17,39 +17,39 @@ FAIL X First 512-point FFT at frame 512 does not equal [-100,-100,-96.0621261596
assert_true: expected true got false
FAIL X 512-point byte FFT does not equal [0,0,14,28,43,209,255,255,252,186,37,53,197,242,250,225...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
Index Actual Expected AbsError RelError Test threshold
[0] 1.3000000000000000e+1 0.0000000000000000e+0 1.3000000000000000e+1 Infinity 0.0000000000000000e+0
[1] 2.8000000000000000e+1 0.0000000000000000e+0 2.8000000000000000e+1 Infinity 0.0000000000000000e+0
[2] 4.9000000000000000e+1 1.4000000000000000e+1 3.5000000000000000e+1 2.5000000000000000e+0 0.0000000000000000e+0
[3] 6.3000000000000000e+1 2.8000000000000000e+1 3.5000000000000000e+1 1.2500000000000000e+0 0.0000000000000000e+0
[4] 7.7000000000000000e+1 4.3000000000000000e+1 3.4000000000000000e+1 7.9069767441860461e-1 0.0000000000000000e+0
...and 195 more errors.
Max AbsError of 3.5000000000000000e+1 at index of 2.
Max RelError of Infinity at index of 0.
[1] 1.6000000000000000e+1 0.0000000000000000e+0 1.6000000000000000e+1 Infinity 0.0000000000000000e+0
[2] 3.6000000000000000e+1 1.4000000000000000e+1 2.2000000000000000e+1 1.5714285714285714e+0 0.0000000000000000e+0
[3] 5.0000000000000000e+1 2.8000000000000000e+1 2.2000000000000000e+1 7.8571428571428570e-1 0.0000000000000000e+0
[4] 6.5000000000000000e+1 4.3000000000000000e+1 2.2000000000000000e+1 5.1162790697674421e-1 0.0000000000000000e+0
[5] 2.3100000000000000e+2 2.0900000000000000e+2 2.2000000000000000e+1 1.0526315789473684e-1 0.0000000000000000e+0
...and 189 more errors.
Max AbsError of 2.2000000000000000e+1 at index of 2.
Max RelError of Infinity at index of 1.
assert_true: expected true got false
FAIL X Smoothed 512-point FFT at frame 1536 does not equal [-94.55278778076172,-93.13629150390625,-90.07610321044922,-87.21340942382812,-85.55162048339844,-38.930355072021484,-24.825944900512695,-21.471542358398438,-27.15943145751953,-45.10898971557617,-87.53993225097656,-78.7408447265625,-42.376895904541016,-29.92169761657715,-27.697038650512695,-34.60657501220703...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0.000025332}.
Index Actual Expected AbsError RelError Test threshold
[0] -8.7954093933105469e+1 -9.4552787780761719e+1 6.5986938476562500e+0 6.9788464227586319e-2 2.3952112200622561e-3
[1] -8.6332389831542969e+1 -9.3136291503906250e+1 6.8039016723632813e+0 7.3053173607174574e-2 2.3593285363769532e-3
[2] -8.3028343200683594e+1 -9.0076103210449219e+1 7.0477600097656250e+0 7.8242283564372198e-2 2.2818078465270996e-3
[3] -8.0046691894531250e+1 -8.7213409423828125e+1 7.1667175292968750e+0 8.2174491017419291e-2 2.2092900875244140e-3
[4] -7.8052825927734375e+1 -8.5551620483398438e+1 7.4987945556640625e+0 8.7652279562831045e-2 2.1671936500854494e-3
...and 201 more errors.
Max AbsError of 7.6593704223632813e+0 at index of 79.
[79] -9.0711067199707031e+1 -9.8370437622070313e+1 7.6593704223632813e+0 7.7862522598403400e-2 2.4919199258422852e-3
Max RelError of 3.4275040169589932e-1 at index of 7.
[7] -1.4112162590026855e+1 -2.1471542358398438e+1 7.3593797683715820e+0 3.4275040169589932e-1 5.4391711102294929e-4
[0] -8.8532302856445313e+1 -9.4552787780761719e+1 6.0204849243164063e+0 6.3673267236456568e-2 2.3952112200622561e-3
[1] -8.7115928649902344e+1 -9.3136291503906250e+1 6.0203628540039063e+0 6.4640354010137985e-2 2.3593285363769532e-3
[2] -8.4055267333984375e+1 -9.0076103210449219e+1 6.0208358764648438e+0 6.6841655687503151e-2 2.2818078465270996e-3
[3] -8.1192565917968750e+1 -8.7213409423828125e+1 6.0208435058593750e+0 6.9035754313881717e-2 2.2092900875244140e-3
[4] -7.9531051635742188e+1 -8.5551620483398438e+1 6.0205688476562500e+0 7.0373522016740298e-2 2.1671936500854494e-3
...and 199 more errors.
Max AbsError of 6.0210571289062500e+0 at index of 183.
[183] -9.0905830383300781e+1 -9.6926887512207031e+1 6.0210571289062500e+0 6.2119575728127596e-2 2.4553519144592285e-3
Max RelError of 2.8039901674224449e-1 at index of 7.
[7] -1.5450942993164063e+1 -2.1471542358398438e+1 6.0205993652343750e+0 2.8039901674224449e-1 5.4391711102294929e-4
assert_true: expected true got false
FAIL X 512-point byte FFT does not equal [19,25,36,46,52,222,255,255,255,199,45,77,209,255,255,238...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
Index Actual Expected AbsError RelError Test threshold
[0] 5.2000000000000000e+1 1.9000000000000000e+1 3.3000000000000000e+1 1.7368421052631580e+0 0.0000000000000000e+0
[1] 5.6000000000000000e+1 2.5000000000000000e+1 3.1000000000000000e+1 1.2400000000000000e+0 0.0000000000000000e+0
[2] 6.6000000000000000e+1 3.6000000000000000e+1 3.0000000000000000e+1 8.3333333333333337e-1 0.0000000000000000e+0
[3] 7.6000000000000000e+1 4.6000000000000000e+1 3.0000000000000000e+1 6.5217391304347827e-1 0.0000000000000000e+0
[4] 8.0000000000000000e+1 5.2000000000000000e+1 2.8000000000000000e+1 5.3846153846153844e-1 0.0000000000000000e+0
...and 196 more errors.
Max AbsError of 3.3000000000000000e+1 at index of 0.
[0] 4.1000000000000000e+1 1.9000000000000000e+1 2.2000000000000000e+1 1.1578947368421053e+0 0.0000000000000000e+0
[1] 4.6000000000000000e+1 2.5000000000000000e+1 2.1000000000000000e+1 8.3999999999999997e-1 0.0000000000000000e+0
[2] 5.8000000000000000e+1 3.6000000000000000e+1 2.2000000000000000e+1 6.1111111111111116e-1 0.0000000000000000e+0
[3] 6.8000000000000000e+1 4.6000000000000000e+1 2.2000000000000000e+1 4.7826086956521741e-1 0.0000000000000000e+0
[4] 7.4000000000000000e+1 5.2000000000000000e+1 2.2000000000000000e+1 4.2307692307692307e-1 0.0000000000000000e+0
...and 193 more errors.
Max AbsError of 2.2000000000000000e+1 at index of 0.
Max RelError of Infinity at index of 51.
[51] 2.2000000000000000e+1 0.0000000000000000e+0 2.2000000000000000e+1 Infinity 0.0000000000000000e+0
[51] 1.5000000000000000e+1 0.0000000000000000e+0 1.5000000000000000e+1 Infinity 0.0000000000000000e+0
assert_true: expected true got false
FAIL < [smoothing test] 4 out of 4 assertions were failed. assert_true: expected true got false
FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed. assert_true: expected true got false
Expand Down
Expand Up @@ -3,34 +3,10 @@ PASS # AUDIT TASK RUNNER STARTED.
PASS Executing "test"
PASS Audit report
PASS > [test]
FAIL X Second call to getFloatFrequencyData expected to be equal to the array [-52.5184440612793,-35.278839111328125,-27.40174102783203,-29.20952796936035,-35.99977493286133,-33.581512451171875,-40.76682662963867,-36.675636291503906,-41.62258529663086,-40.120052337646484,-41.18754959106445,-44.266780853271484,-41.43907165527344,-47.687599182128906,-42.71406173706055,-47.281829833984375...] but differs in 128 places:
Index Actual Expected
[0] -4.7412990570068359e+1 -5.2518444061279297e+1
[1] -3.0173389434814453e+1 -3.5278839111328125e+1
[2] -2.2296291351318359e+1 -2.7401741027832031e+1
[3] -2.4104078292846680e+1 -2.9209527969360352e+1
...and 124 more errors. assert_true: expected true got false
FAIL X Second call to getByteFrequencyData expected to be equal to the array [199,255,255,255,255,255,252,255,246,248,244,236,242,226,237,225...] but differs in 114 places:
Index Actual Expected
[0] 2.0500000000000000e+2 1.9900000000000000e+2
[6] 2.5500000000000000e+2 2.5200000000000000e+2
[8] 2.5400000000000000e+2 2.4600000000000000e+2
[9] 2.5500000000000000e+2 2.4800000000000000e+2
...and 110 more errors. assert_true: expected true got false
FAIL X Output of getByteFrequencyData after getFloatFrequencyData expected to be equal to the array [195,255,255,255,255,255,255,255,255,255,255,255,255,248,252,245...] but differs in 110 places:
Index Actual Expected
[0] 2.0000000000000000e+2 1.9500000000000000e+2
[11] 2.5000000000000000e+2 2.5500000000000000e+2
[12] 2.5300000000000000e+2 2.5500000000000000e+2
[13] 2.4300000000000000e+2 2.4800000000000000e+2
...and 106 more errors. assert_true: expected true got false
FAIL X Output of getFloatFrequenycData (converted to byte) after getByteFrequencyData expected to be equal to the array [209,255,255,255,255,255,255,255,255,255,255,255,255,251,255,248...] but differs in 108 places:
Index Actual Expected
[0] 2.0300000000000000e+2 2.0900000000000000e+2
[13] 2.5000000000000000e+2 2.5100000000000000e+2
[14] 2.5400000000000000e+2 2.5500000000000000e+2
[15] 2.4700000000000000e+2 2.4800000000000000e+2
...and 104 more errors. assert_true: expected true got false
FAIL < [test] 4 out of 4 assertions were failed. assert_true: expected true got false
FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed. assert_true: expected true got false
PASS Second call to getFloatFrequencyData is identical to the array [expected array].
PASS Second call to getByteFrequencyData is identical to the array [189,254,255,255,255,255,245,250,238,239,236,228,233,219,228,218...].
PASS Output of getByteFrequencyData after getFloatFrequencyData is identical to the array [185,255,255,255,255,255,255,255,251,250,247,241,243,234,238,231...].
PASS Output of getFloatFrequenycData (converted to byte) after getByteFrequencyData is identical to the array [198,255,255,255,255,255,255,255,255,255,253,247,249,239,244,237...].
PASS < [test] All assertions passed. (total 4 assertions)
PASS # AUDIT TASK RUNNER FINISHED: 1 tasks ran successfully.

25 changes: 25 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,28 @@
2020-09-21 Chris Dumez <cdumez@apple.com>

AnalyserNode's getByteFrequencyData() / getFloatFrequencyData() should only do FFT analysis once per render quantum
https://bugs.webkit.org/show_bug.cgi?id=216735

Reviewed by Darin Adler.

AnalyserNode's getByteFrequencyData() / getFloatFrequencyData() should only do FFT analysis once per render quantum:
- https://www.w3.org/TR/webaudio/#dom-analysernode-getbytefrequencydata

"""
If another call to getByteFrequencyData() or getFloatFrequencyData() occurs within the same render quantum as a
previous call, the current frequency data is not updated with the same data. Instead, the previously computed data
is returned.
"""

No new tests, rebaselined existing test.

* Modules/webaudio/RealtimeAnalyser.cpp:
(WebCore::RealtimeAnalyser::writeInput):
(WebCore::RealtimeAnalyser::doFFTAnalysisIfNecessary):
(WebCore::RealtimeAnalyser::getFloatFrequencyData):
(WebCore::RealtimeAnalyser::getByteFrequencyData):
* Modules/webaudio/RealtimeAnalyser.h:

2020-09-21 Antoine Quint <graouts@webkit.org>

Remove dedicated HashSet<Element*> for DocumentTimeline::runningAnimationsForElementAreAllAccelerated()
Expand Down
14 changes: 11 additions & 3 deletions Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp
Expand Up @@ -120,6 +120,9 @@ void RealtimeAnalyser::writeInput(AudioBus* bus, size_t framesToProcess)
m_writeIndex += framesToProcess;
if (m_writeIndex >= InputBufferSize)
m_writeIndex = 0;

// A new render quantum has been processed so we should do the FFT analysis again.
m_shouldDoFFTAnalysis = true;
}

namespace {
Expand All @@ -143,10 +146,15 @@ void applyWindow(float* p, size_t n)

} // namespace

void RealtimeAnalyser::doFFTAnalysis()
void RealtimeAnalyser::doFFTAnalysisIfNecessary()
{
ASSERT(isMainThread());

if (!m_shouldDoFFTAnalysis)
return;

m_shouldDoFFTAnalysis = false;

// Unroll the input buffer into a temporary buffer, where we'll apply an analysis window followed by an FFT.
size_t fftSize = this->fftSize();

Expand Down Expand Up @@ -197,7 +205,7 @@ void RealtimeAnalyser::getFloatFrequencyData(Float32Array& destinationArray)
{
ASSERT(isMainThread());

doFFTAnalysis();
doFFTAnalysisIfNecessary();

// Convert from linear magnitude to floating-point decibels.
unsigned sourceLength = magnitudeBuffer().size();
Expand All @@ -215,7 +223,7 @@ void RealtimeAnalyser::getByteFrequencyData(Uint8Array& destinationArray)
{
ASSERT(isMainThread());

doFFTAnalysis();
doFFTAnalysisIfNecessary();

// Convert from linear magnitude to unsigned-byte decibels.
unsigned sourceLength = magnitudeBuffer().size();
Expand Down
7 changes: 5 additions & 2 deletions Source/WebCore/Modules/webaudio/RealtimeAnalyser.h
Expand Up @@ -86,9 +86,9 @@ class RealtimeAnalyser {

size_t m_fftSize;
std::unique_ptr<FFTFrame> m_analysisFrame;
void doFFTAnalysis();
void doFFTAnalysisIfNecessary();

// doFFTAnalysis() stores the floating-point magnitude analysis data here.
// doFFTAnalysisIfNecessary() stores the floating-point magnitude analysis data here.
AudioFloatArray m_magnitudeBuffer;
AudioFloatArray& magnitudeBuffer() { return m_magnitudeBuffer; }

Expand All @@ -98,6 +98,9 @@ class RealtimeAnalyser {
// The range used when converting when using getByteFrequencyData().
double m_minDecibels;
double m_maxDecibels;

// We should only do the FFT analysis once per render quantum.
bool m_shouldDoFFTAnalysis { true };
};

} // namespace WebCore

0 comments on commit d86206d

Please sign in to comment.