Diff
Modified: trunk/LayoutTests/ChangeLog (117371 => 117372)
--- trunk/LayoutTests/ChangeLog 2012-05-17 00:46:10 UTC (rev 117371)
+++ trunk/LayoutTests/ChangeLog 2012-05-17 01:14:23 UTC (rev 117372)
@@ -1,3 +1,14 @@
+2012-05-16 Chris Rogers <crog...@google.com>
+
+ AudioParam must support fan-in (multiple audio connections)
+ https://bugs.webkit.org/show_bug.cgi?id=83610
+
+ Reviewed by Kenneth Russell.
+
+ * webaudio/audioparam-connect-audioratesignal.html:
+ * webaudio/audioparam-summingjunction-expected.txt: Added.
+ * webaudio/audioparam-summingjunction.html: Added.
+
2012-05-16 Julien Chaffraix <jchaffr...@webkit.org>
Unreviewed gardening after r117339 (table baseline computation change).
Modified: trunk/LayoutTests/webaudio/audioparam-connect-audioratesignal.html (117371 => 117372)
--- trunk/LayoutTests/webaudio/audioparam-connect-audioratesignal.html 2012-05-17 00:46:10 UTC (rev 117371)
+++ trunk/LayoutTests/webaudio/audioparam-connect-audioratesignal.html 2012-05-17 01:14:23 UTC (rev 117372)
@@ -87,6 +87,10 @@
// Create a gain node controlling the gain of constantSource and make the connections.
var gainNode = context.createGainNode();
+
+ // Intrinsic baseline gain of zero.
+ gainNode.gain.value = 0;
+
constantSource.connect(gainNode);
gainNode.connect(context.destination);
Added: trunk/LayoutTests/webaudio/audioparam-summingjunction-expected.txt (0 => 117372)
--- trunk/LayoutTests/webaudio/audioparam-summingjunction-expected.txt (rev 0)
+++ trunk/LayoutTests/webaudio/audioparam-summingjunction-expected.txt 2012-05-17 01:14:23 UTC (rev 117372)
@@ -0,0 +1,6 @@
+PASS Rendered signal is of correct length.
+PASS Rendered signal matches sum of two audio-rate gain changing signals plus baseline gain.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/webaudio/audioparam-summingjunction.html (0 => 117372)
--- trunk/LayoutTests/webaudio/audioparam-summingjunction.html (rev 0)
+++ trunk/LayoutTests/webaudio/audioparam-summingjunction.html 2012-05-17 01:14:23 UTC (rev 117372)
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+
+<!--
+Tests that multiple audio-rate signals (AudioNode outputs) can be connected to an AudioParam
+and that these signals are summed, along with the AudioParams intrinsic value.
+-->
+
+<html>
+<head>
+<link rel="stylesheet" href=""
+<script src=""
+<script src=""
+<script src=""
+
+</head>
+<body>
+
+<script>
+
+var sampleRate = 44100.0;
+var lengthInSeconds = 1;
+
+var context = 0;
+
+// Buffers used by the two gain controlling sources.
+var linearRampBuffer;
+var toneBuffer;
+var toneFrequency = 440;
+
+// Arbitrary non-zero value.
+var baselineGain = 5;
+
+// Allow for a small round-off error.
+var maxAllowedError = 1e-6;
+
+function checkResult(event) {
+ var renderedBuffer = event.renderedBuffer;
+ var renderedData = renderedBuffer.getChannelData(0);
+
+ // Get buffer data from the two sources used to control gain.
+ var linearRampData = linearRampBuffer.getChannelData(0);
+ var toneData = toneBuffer.getChannelData(0);
+
+ var n = renderedBuffer.length;
+
+ if (n == linearRampBuffer.length) {
+ testPassed("Rendered signal is of correct length.");
+ } else {
+ testFailed("Rendered signal is not of correct length.");
+ }
+
+ // Check that the rendered result exactly matches the sum of the intrinsic gain plus the two sources used to control gain.
+ // This is because we're changing the gain of a signal having constant value 1.
+ var success = true;
+ for (var i = 0; i < n; ++i) {
+ var expectedValue = baselineGain + linearRampData[i] + toneData[i];
+ var error = Math.abs(expectedValue - renderedData[i]);
+
+ if (error > maxAllowedError) {
+ success = false;
+ break;
+ }
+ }
+
+ if (success) {
+ testPassed("Rendered signal matches sum of two audio-rate gain changing signals plus baseline gain.");
+ } else {
+ testFailed("Rendered signal differs from the sum of two audio-rate gain changing signals plus baseline gain.");
+ }
+
+ finishJSTest();
+}
+
+function runTest() {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ window.jsTestIsAsync = true;
+
+ var sampleFrameLength = sampleRate * lengthInSeconds;
+
+ // Create offline audio context.
+ context = new webkitAudioContext(1, sampleFrameLength, sampleRate);
+
+ // Create buffer used by the source which will have its gain controlled.
+ var constantOneBuffer = createConstantBuffer(context, sampleFrameLength, 1);
+ var constantSource = context.createBufferSource();
+ constantSource.buffer = constantOneBuffer;
+
+ // Create 1st buffer used to control gain (a linear ramp).
+ linearRampBuffer = createLinearRampBuffer(context, sampleFrameLength);
+ var gainSource1 = context.createBufferSource();
+ gainSource1.buffer = linearRampBuffer;
+
+ // Create 2nd buffer used to control gain (a simple sine wave tone).
+ toneBuffer = createToneBuffer(context, toneFrequency, lengthInSeconds, 1);
+ var gainSource2 = context.createBufferSource();
+ gainSource2.buffer = toneBuffer;
+
+ // Create a gain node controlling the gain of constantSource and make the connections.
+ var gainNode = context.createGainNode();
+
+ // Intrinsic baseline gain.
+ // This gain value should be summed with gainSource1 and gainSource2.
+ gainNode.gain.value = baselineGain;
+
+ constantSource.connect(gainNode);
+ gainNode.connect(context.destination);
+
+ // Connect two audio-rate signals to control the .gain AudioParam.
+ gainSource1.connect(gainNode.gain);
+ gainSource2.connect(gainNode.gain);
+
+ // Start all sources at time 0.
+ constantSource.noteOn(0);
+ gainSource1.noteOn(0);
+ gainSource2.noteOn(0);
+
+ context._oncomplete_ = checkResult;
+ context.startRendering();
+}
+
+runTest();
+successfullyParsed = true;
+
+</script>
+<script src=""
+
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (117371 => 117372)
--- trunk/Source/WebCore/ChangeLog 2012-05-17 00:46:10 UTC (rev 117371)
+++ trunk/Source/WebCore/ChangeLog 2012-05-17 01:14:23 UTC (rev 117372)
@@ -1,3 +1,28 @@
+2012-05-16 Chris Rogers <crog...@google.com>
+
+ AudioParam must support fan-in (multiple audio connections)
+ https://bugs.webkit.org/show_bug.cgi?id=83610
+
+ Reviewed by Kenneth Russell.
+
+ Test: webaudio/audioparam-summingjunction.html
+
+ * Modules/webaudio/AudioParam.cpp:
+ * Modules/webaudio/AudioParam.h:
+ (WebCore::AudioParam::calculateSampleAccurateValues):
+ (WebCore::AudioParam::calculateAudioRateSignalValues):
+ Sums intrinsic parameter value with all audio-rate connections.
+
+ (WebCore::AudioParam::connect):
+ (WebCore::AudioParam::disconnect):
+ Support multiple connections.
+
+ (WebCore::AudioParam::hasSampleAccurateValues):
+ If we have one or more audio-rate connections.
+
+ (WebCore::AudioParam::AudioParam):
+ AudioParam now sub-classes AudioSummingJunction.
+
2012-05-16 Kentaro Hara <hara...@chromium.org>
[V8] Pass Isolate to createV8HTMLWrapper() and createV8SVGWrapper()
Modified: trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp (117371 => 117372)
--- trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp 2012-05-17 00:46:10 UTC (rev 117371)
+++ trunk/Source/WebCore/Modules/webaudio/AudioParam.cpp 2012-05-17 01:14:23 UTC (rev 117372)
@@ -101,7 +101,7 @@
if (!isSafe)
return;
- if (m_audioRateSignal)
+ if (numberOfRenderingConnections())
calculateAudioRateSignalValues(values, numberOfValues);
else
calculateTimelineValues(values, numberOfValues);
@@ -109,26 +109,40 @@
void AudioParam::calculateAudioRateSignalValues(float* values, unsigned numberOfValues)
{
- // FIXME: support fan-in (multiple audio connections to this parameter with unity-gain summing).
- // https://bugs.webkit.org/show_bug.cgi?id=83610
- ASSERT(m_audioRateSignal);
-
- AudioBus* bus = m_audioRateSignal->pull(0, numberOfValues);
- bool isBusGood = bus && bus->numberOfChannels() && bus->length() >= numberOfValues;
- ASSERT(isBusGood);
- if (!isBusGood)
+ bool isGood = numberOfRenderingConnections() && numberOfValues;
+ ASSERT(isGood);
+ if (!isGood)
return;
- if (bus->numberOfChannels() == 1) {
- // The normal case is to deal with a mono audio-rate signal.
- memcpy(values, bus->channel(0)->data(), sizeof(float) * numberOfValues);
+ // The calculated result will be the "intrinsic" value summed with all audio-rate connections.
+
+ if (m_timeline.hasValues()) {
+ // Calculate regular timeline values, if we have any.
+ calculateTimelineValues(values, numberOfValues);
} else {
- // Do a standard mixdown to one channel if necessary.
- AudioBus wrapperBus(1, numberOfValues, false);
- wrapperBus.setChannelMemory(0, values, numberOfValues);
- wrapperBus.copyFrom(*bus); // Mixdown.
+ // Otherwise set values array to our constant value.
+ float value = m_value; // Cache in local.
+
+ // FIXME: can be optimized if we create a new VectorMath function.
+ for (unsigned i = 0; i < numberOfValues; ++i)
+ values[i] = value;
}
- m_value = values[0]; // Update to first value.
+
+ // Now sum all of the audio-rate connections together (unity-gain summing junction).
+ // Note that connections would normally be mono, but we mix down to mono if necessary.
+ AudioBus summingBus(1, numberOfValues, false);
+ summingBus.setChannelMemory(0, values, numberOfValues);
+
+ for (unsigned i = 0; i < numberOfRenderingConnections(); ++i) {
+ AudioNodeOutput* output = renderingOutput(i);
+ ASSERT(output);
+
+ // Render audio from this output.
+ AudioBus* connectionBus = output->pull(0, numberOfValues);
+
+ // Sum, with unity-gain.
+ summingBus.sumFrom(*connectionBus);
+ }
}
void AudioParam::calculateTimelineValues(float* values, unsigned numberOfValues)
@@ -144,33 +158,35 @@
m_value = m_timeline.valuesForTimeRange(startTime, endTime, narrowPrecisionToFloat(m_value), values, numberOfValues, sampleRate, sampleRate);
}
-void AudioParam::connect(AudioNodeOutput* audioRateSignal)
+void AudioParam::connect(AudioNodeOutput* output)
{
ASSERT(context()->isGraphOwner());
- ASSERT(audioRateSignal);
- if (!audioRateSignal)
+
+ ASSERT(output);
+ if (!output)
return;
- if (m_audioRateSignal && m_audioRateSignal != audioRateSignal) {
- // Because we don't currently support fan-in we must explicitly disconnect from an old output.
- m_audioRateSignal->removeParam(this);
- }
+ if (m_outputs.contains(output))
+ return;
- audioRateSignal->addParam(this);
- m_audioRateSignal = audioRateSignal;
+ output->addParam(this);
+ m_outputs.add(output);
+ changedOutputs();
}
-void AudioParam::disconnect(AudioNodeOutput* audioRateSignal)
+void AudioParam::disconnect(AudioNodeOutput* output)
{
ASSERT(context()->isGraphOwner());
- ASSERT(audioRateSignal);
- if (!audioRateSignal)
+
+ ASSERT(output);
+ if (!output)
return;
- // FIXME: support fan-in (multiple audio connections to this parameter with unity-gain summing).
- // https://bugs.webkit.org/show_bug.cgi?id=83610
- if (m_audioRateSignal == audioRateSignal)
- m_audioRateSignal = 0;
+ if (m_outputs.contains(output)) {
+ m_outputs.remove(output);
+ changedOutputs();
+ output->removeParam(this);
+ }
}
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/webaudio/AudioParam.h (117371 => 117372)
--- trunk/Source/WebCore/Modules/webaudio/AudioParam.h 2012-05-17 00:46:10 UTC (rev 117371)
+++ trunk/Source/WebCore/Modules/webaudio/AudioParam.h 2012-05-17 01:14:23 UTC (rev 117372)
@@ -31,6 +31,7 @@
#include "AudioContext.h"
#include "AudioParamTimeline.h"
+#include "AudioSummingJunction.h"
#include "PlatformString.h"
#include <sys/types.h>
#include <wtf/Float32Array.h>
@@ -41,7 +42,7 @@
class AudioNodeOutput;
-class AudioParam : public RefCounted<AudioParam> {
+class AudioParam : public AudioSummingJunction, public RefCounted<AudioParam> {
public:
static const double DefaultSmoothingConstant;
static const double SnapThreshold;
@@ -51,7 +52,9 @@
return adoptRef(new AudioParam(context, name, defaultValue, minValue, maxValue, units));
}
- AudioContext* context() { return m_context.get(); }
+ // AudioSummingJunction
+ virtual bool canUpdateState() OVERRIDE { return true; }
+ virtual void didUpdate() OVERRIDE { }
float value();
void setValue(float);
@@ -84,7 +87,7 @@
void setValueCurveAtTime(Float32Array* curve, float time, float duration) { m_timeline.setValueCurveAtTime(curve, time, duration); }
void cancelScheduledValues(float startTime) { m_timeline.cancelScheduledValues(startTime); }
- bool hasSampleAccurateValues() { return m_timeline.hasValues() || m_audioRateSignal; }
+ bool hasSampleAccurateValues() { return m_timeline.hasValues() || numberOfRenderingConnections(); }
// Calculates numberOfValues parameter values starting at the context's current time.
// Must be called in the context's render thread.
@@ -96,7 +99,7 @@
protected:
AudioParam(AudioContext* context, const String& name, double defaultValue, double minValue, double maxValue, unsigned units = 0)
- : m_context(context)
+ : AudioSummingJunction(context)
, m_name(name)
, m_value(defaultValue)
, m_defaultValue(defaultValue)
@@ -105,7 +108,6 @@
, m_units(units)
, m_smoothedValue(defaultValue)
, m_smoothingConstant(DefaultSmoothingConstant)
- , m_audioRateSignal(0)
{
}
@@ -113,7 +115,6 @@
void calculateAudioRateSignalValues(float* values, unsigned numberOfValues);
void calculateTimelineValues(float* values, unsigned numberOfValues);
- RefPtr<AudioContext> m_context;
String m_name;
double m_value;
double m_defaultValue;
@@ -126,11 +127,6 @@
double m_smoothingConstant;
AudioParamTimeline m_timeline;
-
- // An audio-rate signal directly providing parameter values.
- // FIXME: support fan-in (multiple audio connections to this parameter with unity-gain summing).
- // https://bugs.webkit.org/show_bug.cgi?id=83610
- AudioNodeOutput* m_audioRateSignal;
};
} // namespace WebCore