<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[172816] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/172816">172816</a></dd>
<dt>Author</dt> <dd>dino@apple.com</dd>
<dt>Date</dt> <dd>2014-08-20 15:39:44 -0700 (Wed, 20 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAudio FFT analysis uses incorrect scaling
https://bugs.webkit.org/show_bug.cgi?id=136120

Reviewed by Tim Horton.

Source/WebCore:

This is a port of Blink <a href="http://trac.webkit.org/projects/webkit/changeset/166687">r166687</a> (author rtoy)
https://codereview.chromium.org/156993002

Currently, for a fixed sine-wave input, the peak FFT amplitude changes
depending on the selected FFT size. This is incorrect; the FFT amplitude
should not appreciably change when the FFT size changes.

Layout test added to verify the FFT result stays approximately constant,
independent of the FFT size used.

When this test is run using an older version of WebKit, the peak varies
from about -44 dB (FFT size 32) to -7 dB (FFT size 2048).  With this CL,
the peak is about -7 dB.  (It's not 0 dB because of the Blackman window that is applied.)

Note: this change may break existing applications that depended on this strange scaling effect.

Test: webaudio/realtimeanalyser-fft-scaling.html

* Modules/webaudio/RealtimeAnalyser.cpp:
(WebCore::RealtimeAnalyser::doFFTAnalysis):

LayoutTests:

Test from Blink <a href="http://trac.webkit.org/projects/webkit/changeset/166687">r166687</a>.

* webaudio/realtimeanalyser-fft-scaling.html: Added.
* webaudio/realtimeanalyser-fft-scaling-expected.txt: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioRealtimeAnalysercpp">trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestswebaudiorealtimeanalyserfftscalingexpectedtxt">trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudiorealtimeanalyserfftscalinghtml">trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (172815 => 172816)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-08-20 22:08:45 UTC (rev 172815)
+++ trunk/LayoutTests/ChangeLog        2014-08-20 22:39:44 UTC (rev 172816)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-08-20  Dean Jackson  &lt;dino@apple.com&gt;
+
+        WebAudio FFT analysis uses incorrect scaling
+        https://bugs.webkit.org/show_bug.cgi?id=136120
+
+        Reviewed by Tim Horton.
+
+        Test from Blink r166687.
+
+        * webaudio/realtimeanalyser-fft-scaling.html: Added.
+        * webaudio/realtimeanalyser-fft-scaling-expected.txt: Added.
+
</ins><span class="cx"> 2014-08-20  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         fast/multicol/mixed-opacity-fixed-test.html fails in compositing mode
</span></span></pre></div>
<a id="trunkLayoutTestswebaudiorealtimeanalyserfftscalingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling-expected.txt (0 => 172816)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling-expected.txt                                (rev 0)
+++ trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling-expected.txt        2014-08-20 22:39:44 UTC (rev 172816)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+Test scaling of FFT data for AnalyserNode
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+PASS Actual FFT peak in the expected position (1)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 32
+PASS Actual FFT peak in the expected position (2)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 64
+PASS Actual FFT peak in the expected position (4)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 128
+PASS Actual FFT peak in the expected position (8)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 256
+PASS Actual FFT peak in the expected position (16)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 512
+PASS Actual FFT peak in the expected position (32)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 1024
+PASS Actual FFT peak in the expected position (64)
+PASS Peak value is near 0 dBFS as expected
+PASS Analyser correctly scaled FFT data of size 2048
+PASS All Analyser tests passed.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins><span class="cx">Property changes on: trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling-expected.txt
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestswebaudiorealtimeanalyserfftscalinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html (0 => 172816)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html                                (rev 0)
+++ trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html        2014-08-20 22:39:44 UTC (rev 172816)
</span><span class="lines">@@ -0,0 +1,124 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;&gt;
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;script src=&quot;../resources/js-test.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;resources/audio-testing.js&quot;&gt;&lt;/script&gt;
+  &lt;/head&gt;
+
+  &lt;body&gt;
+    &lt;div id=&quot;description&quot;&gt;&lt;/div&gt;
+    &lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+
+    &lt;script&gt;
+description(&quot;Test scaling of FFT data for AnalyserNode&quot;);
+
+// The number of analysers. We have analysers from size for each of the possible sizes of 32,
+// 64, 128, 256, 512, 1024 and 2048.
+var numberOfAnalysers = 7;
+var sampleRate = 44100;
+var context;
+var osc;
+var oscFrequency = sampleRate/32;
+var analysers = new Array(7);
+var peakValue = new Array(7);
+
+// For a 0dBFS sine wave, we would expect the FFT magnitude to be 0dB as well, but the
+// analyzer node applies a Blackman window (to smooth the estimate).  This reduces the energy
+// of the signal so the FFT peak is less than 0dB.  The threshold value given here was
+// determined experimentally.
+//
+// See https://code.google.com/p/chromium/issues/detail?id=341596.
+var peakThreshold = [-8.41, -7.54, -7.54, -7.54, -7.54, -7.54, -7.54];
+
+function checkResult() {
+    var allTestsPassed = true;
+
+    for (var n = 0; n &lt; analysers.length; ++n) {
+        // Grab the FFT data from each analyser.
+        var fftSize = analysers[n].fftSize;
+        var fftData = new Float32Array(fftSize);
+        analysers[n].getFloatFrequencyData(fftData);
+
+        // Compute the frequency bin that should contain the peak.
+        var expectedBin = fftSize * (oscFrequency / sampleRate);
+
+        // Find the actual bin by finding the bin containing the peak.
+        var actualBin = 0;
+        peakValue[n] = -1000;
+        for (k = 0; k &lt; analysers[n].frequencyBinCount; ++k) {
+            if (fftData[k] &gt; peakValue[n]) {
+                actualBin = k;
+                peakValue[n] = fftData[k];
+            }
+        }
+
+        var success = true;
+
+        if (actualBin == expectedBin) {
+            testPassed(&quot;Actual FFT peak in the expected position (&quot; + expectedBin + &quot;)&quot;);
+        } else {
+            success = false;
+            testFailed(&quot;Actual FFT peak (&quot; + actualBin + &quot;) differs from expected (&quot; + expectedBin + &quot;)&quot;);
+        }
+
+        if (peakValue[n] &gt;= peakThreshold[n]) {
+            testPassed(&quot;Peak value is near 0 dBFS as expected&quot;);
+        } else {
+            success = false;
+            testFailed(&quot;Peak value of &quot; + peakValue[n]
+            + &quot; is incorrect.  (Expected approximately &quot;
+            + peakThreshold[n] + &quot;)&quot;);
+        }
+
+        if (success) {
+            testPassed(&quot;Analyser correctly scaled FFT data of size &quot; + fftSize);
+        } else {
+            testFailed(&quot;Analyser incorrectly scaled FFT data of size &quot; + fftSize);
+        }
+        allTestsPassed = allTestsPassed &amp;&amp; success;
+    }
+
+    if (allTestsPassed) {
+        testPassed(&quot;All Analyser tests passed.&quot;);
+    } else {
+        testFailed(&quot;At least one Analyser test failed.&quot;);
+    }
+
+    finishJSTest();
+}
+
+function runTests() {
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    window.jsTestIsAsync = true;
+
+    context = new webkitOfflineAudioContext(1, 2048, sampleRate);
+
+    // Use a sine wave oscillator as the reference source signal.
+    osc = context.createOscillator();
+    osc.type = &quot;sine&quot;;
+    osc.frequency.value = oscFrequency;
+    osc.connect(context.destination);
+
+    // Create an analyser node for each of the possible valid sizes.
+    for (var order = 5; order &lt; 12; ++order) {
+        analysers[order - 5] = context.createAnalyser();
+        // No smoothing so between frames to simplify testing.
+        analysers[order - 5].smoothingTimeConstant = 0;
+        analysers[order - 5].fftSize = 1 &lt;&lt; order;
+        osc.connect(analysers[order - 5]);
+    }
+
+    osc.start(0);
+    context.oncomplete = checkResult;
+    context.startRendering();
+}
+
+runTests();
+successfullyParsed = true;
+    &lt;/script&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (172815 => 172816)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-20 22:08:45 UTC (rev 172815)
+++ trunk/Source/WebCore/ChangeLog        2014-08-20 22:39:44 UTC (rev 172816)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2014-08-20  Dean Jackson  &lt;dino@apple.com&gt;
+
+        WebAudio FFT analysis uses incorrect scaling
+        https://bugs.webkit.org/show_bug.cgi?id=136120
+
+        Reviewed by Tim Horton.
+
+        This is a port of Blink r166687 (author rtoy)
+        https://codereview.chromium.org/156993002
+
+        Currently, for a fixed sine-wave input, the peak FFT amplitude changes
+        depending on the selected FFT size. This is incorrect; the FFT amplitude
+        should not appreciably change when the FFT size changes.
+
+        Layout test added to verify the FFT result stays approximately constant,
+        independent of the FFT size used.
+
+        When this test is run using an older version of WebKit, the peak varies
+        from about -44 dB (FFT size 32) to -7 dB (FFT size 2048).  With this CL,
+        the peak is about -7 dB.  (It's not 0 dB because of the Blackman window that is applied.)
+
+        Note: this change may break existing applications that depended on this strange scaling effect.
+
+        Test: webaudio/realtimeanalyser-fft-scaling.html
+
+        * Modules/webaudio/RealtimeAnalyser.cpp:
+        (WebCore::RealtimeAnalyser::doFFTAnalysis):
+
</ins><span class="cx"> 2014-08-20  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Introducing WEBCORE_EXPORT macro.
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioRealtimeAnalysercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp (172815 => 172816)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp        2014-08-20 22:08:45 UTC (rev 172815)
+++ trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp        2014-08-20 22:39:44 UTC (rev 172816)
</span><span class="lines">@@ -185,7 +185,7 @@
</span><span class="cx">     imagP[0] = 0;
</span><span class="cx">     
</span><span class="cx">     // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor).
</span><del>-    const double magnitudeScale = 1.0 / DefaultFFTSize;
</del><ins>+    const double magnitudeScale = 1.0 / fftSize;
</ins><span class="cx"> 
</span><span class="cx">     // A value of 0 does no averaging with the previous result.  Larger values produce slower, but smoother changes.
</span><span class="cx">     double k = m_smoothingTimeConstant;
</span></span></pre>
</div>
</div>

</body>
</html>