Creating "basic waveform" Oscillator nodes is not efficient
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Aug 2012 00:18:23 +0000 (00:18 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Aug 2012 00:18:23 +0000 (00:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=93194

Patch by Raymond Toy <rtoy@google.com> on 2012-08-08
Reviewed by Chris Rogers.

Source/WebCore:

Cache the wavetables for the basic types so they don't have to be
recomputed every time.

Also fix a bug where oscillator type was always set to CUSTOM
instead of the specified oscillator type.  Test added for this.

Test: webaudio/oscillator-basic.html

* Modules/webaudio/Oscillator.cpp:
(WebCore):
(WebCore::Oscillator::setType): Use cached wavetables; fix bug in
setting the oscillator type.
* Modules/webaudio/Oscillator.h:
(Oscillator): Define static variables to hold cached wavetables.

LayoutTests:

Add test to verify that the returned oscillator type is the same
as what was set.

* webaudio/oscillator-basic-expected.txt: Added.
* webaudio/oscillator-basic.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@125122 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/webaudio/oscillator-basic-expected.txt [new file with mode: 0644]
LayoutTests/webaudio/oscillator-basic.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/webaudio/Oscillator.cpp
Source/WebCore/Modules/webaudio/Oscillator.h

index f694117..180157b 100644 (file)
@@ -1,3 +1,16 @@
+2012-08-08  Raymond Toy  <rtoy@google.com>
+
+        Creating "basic waveform" Oscillator nodes is not efficient
+        https://bugs.webkit.org/show_bug.cgi?id=93194
+
+        Reviewed by Chris Rogers.
+
+        Add test to verify that the returned oscillator type is the same
+        as what was set.
+        
+        * webaudio/oscillator-basic-expected.txt: Added.
+        * webaudio/oscillator-basic.html: Added.
+
 2012-08-08  Tom Sepez  <tsepez@chromium.org>
 
         Avoid ASSERT(m_workerContext->isSharedWorkerContext()) in WorkerScriptController::initScript()
diff --git a/LayoutTests/webaudio/oscillator-basic-expected.txt b/LayoutTests/webaudio/oscillator-basic-expected.txt
new file mode 100644 (file)
index 0000000..46c6edb
--- /dev/null
@@ -0,0 +1,13 @@
+Basic test of setting Oscillator node types.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS Oscillator correctly set to SINE type.
+PASS Oscillator correctly set to SQUARE type.
+PASS Oscillator correctly set to SAWTOOTH type.
+PASS Oscillator correctly set to TRIANGLE type.
+PASS Oscillator correctly set to CUSTOM type.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/webaudio/oscillator-basic.html b/LayoutTests/webaudio/oscillator-basic.html
new file mode 100644 (file)
index 0000000..bf26b02
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<!--
+Create an oscillator of each type and verify that the type is set correctly.
+-->
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css"/>
+<script type="text/javascript" src="resources/audio-testing.js"></script>
+<script type="text/javascript" src="../fast/js/resources/js-test-pre.js"></script>
+</head>
+
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Basic test of setting Oscillator node types.");
+
+var sampleRate = 44100;
+var renderLengthSeconds = 0.25;
+
+var oscTypes = [{type: 0, name: "SINE"},
+                {type: 1, name: "SQUARE"},
+                {type: 2, name: "SAWTOOTH"},
+                {type: 3, name: "TRIANGLE"},
+                {type: 4, name: "CUSTOM"}];
+
+function runTest() 
+{
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+    
+    window.jsTestIsAsync = true;
+        
+    // Create offline audio context.
+    var context = new webkitAudioContext(2, sampleRate * renderLengthSeconds, sampleRate);
+    var osc = context.createOscillator();
+
+    // Set each possible oscillator type (except CUSTOM) and verify that the type is correct.
+    for (var k = 0; k < oscTypes.length - 1; ++k) {
+        osc.type = oscTypes[k].type
+        if (osc.type == oscTypes[k].type)
+            testPassed("Oscillator correctly set to " + oscTypes[k].name + " type.");
+        else
+            testFailed("Oscillator set to " + oscTypes[k].name + " type, but returns " + oscTypes[osc.type].name + " type.");
+    }
+
+    // Now set a custom oscillator
+    var coeffA = new Float32Array([0, 1, 0.5]);
+    var coeffB = new Float32Array([0, 0, 0]);        
+    var wavetable = context.createWaveTable(coeffA, coeffB);
+    osc.setWaveTable(wavetable);
+    if (osc.type == osc.CUSTOM)
+        testPassed("Oscillator correctly set to CUSTOM type.");
+    else
+        testFailed("Oscillator set to CUSTOM type, but returns " + oscTypes[osc.type].name + " type.");
+
+    finishJSTest();
+}
+
+runTest();
+successfullyParsed = true;
+
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+
+</body>
+</html>
index 842a0ed..bb9fd5a 100644 (file)
@@ -1,3 +1,25 @@
+2012-08-08  Raymond Toy  <rtoy@google.com>
+
+        Creating "basic waveform" Oscillator nodes is not efficient
+        https://bugs.webkit.org/show_bug.cgi?id=93194
+
+        Reviewed by Chris Rogers.
+
+        Cache the wavetables for the basic types so they don't have to be
+        recomputed every time.
+
+        Also fix a bug where oscillator type was always set to CUSTOM
+        instead of the specified oscillator type.  Test added for this.
+
+        Test: webaudio/oscillator-basic.html
+
+        * Modules/webaudio/Oscillator.cpp:
+        (WebCore):
+        (WebCore::Oscillator::setType): Use cached wavetables; fix bug in
+        setting the oscillator type.
+        * Modules/webaudio/Oscillator.h: 
+        (Oscillator): Define static variables to hold cached wavetables.
+
 2012-08-08  Tom Sepez  <tsepez@chromium.org>
 
         Avoid ASSERT(m_workerContext->isSharedWorkerContext()) in WorkerScriptController::initScript()
index 18588a6..ecbd4db 100644 (file)
@@ -42,6 +42,11 @@ namespace WebCore {
 
 using namespace VectorMath;
 
+WaveTable* Oscillator::s_waveTableSine = 0;
+WaveTable* Oscillator::s_waveTableSquare = 0;
+WaveTable* Oscillator::s_waveTableSawtooth = 0;
+WaveTable* Oscillator::s_waveTableTriangle = 0;
+
 PassRefPtr<Oscillator> Oscillator::create(AudioContext* context, float sampleRate)
 {
     return adoptRef(new Oscillator(context, sampleRate));
@@ -78,30 +83,40 @@ Oscillator::~Oscillator()
 
 void Oscillator::setType(unsigned short type)
 {
-    RefPtr<WaveTable> waveTable;
+    WaveTable* waveTable = 0;
     float sampleRate = this->sampleRate();
 
     switch (type) {
     case SINE:
-        waveTable = WaveTable::createSine(sampleRate);
+        if (!s_waveTableSine)
+            s_waveTableSine = WaveTable::createSine(sampleRate).leakRef();
+        waveTable = s_waveTableSine;
         break;
     case SQUARE:
-        waveTable = WaveTable::createSquare(sampleRate);
+        if (!s_waveTableSquare)
+            s_waveTableSquare = WaveTable::createSquare(sampleRate).leakRef();
+        waveTable = s_waveTableSquare;
         break;
     case SAWTOOTH:
-        waveTable = WaveTable::createSawtooth(sampleRate);
+        if (!s_waveTableSawtooth)
+            s_waveTableSawtooth = WaveTable::createSawtooth(sampleRate).leakRef();
+        waveTable = s_waveTableSawtooth;
         break;
     case TRIANGLE:
-        waveTable = WaveTable::createTriangle(sampleRate);
+        if (!s_waveTableTriangle)
+            s_waveTableTriangle = WaveTable::createTriangle(sampleRate).leakRef();
+        waveTable = s_waveTableTriangle;
         break;
     case CUSTOM:
-        // FIXME: throw exception since setWaveTable() method must be called explicitly.
+    default:
+        // FIXME: throw exception for invalid types or if the type is CUSTOM since setWaveTable()
+        // method must be called explicitly in that case.
         return;
         break;
     }
 
+    setWaveTable(waveTable);
     m_type = type;
-    setWaveTable(waveTable.get());
 }
 
 bool Oscillator::calculateSampleAccuratePhaseIncrements(size_t framesToProcess)
index 2158a82..127b31b 100644 (file)
@@ -99,6 +99,12 @@ private:
     AudioFloatArray m_detuneValues;
     
     RefPtr<WaveTable> m_waveTable;
+
+    // Cache the wave tables for different waveform types, except CUSTOM.
+    static WaveTable* s_waveTableSine;
+    static WaveTable* s_waveTableSquare;
+    static WaveTable* s_waveTableSawtooth;
+    static WaveTable* s_waveTableTriangle;
 };
 
 } // namespace WebCore