Reviewed by Kenneth Russell.
Allow existing AudioParams to use scheduled parameter changes
https://bugs.webkit.org/show_bug.cgi?id=62046
No new tests since audio API is not yet implemented.
* platform/audio/AudioBus.cpp:
(WebCore::AudioBus::processWithGainFrom):
(WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom):
* platform/audio/AudioBus.h:
* webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::AudioBufferSourceNode):
* webaudio/AudioGainNode.cpp:
(WebCore::AudioGainNode::AudioGainNode):
(WebCore::AudioGainNode::process):
* webaudio/AudioGainNode.h:
* webaudio/HighPass2FilterNode.cpp:
(WebCore::HighPass2FilterNode::HighPass2FilterNode):
* webaudio/LowPass2FilterNode.cpp:
(WebCore::LowPass2FilterNode::LowPass2FilterNode):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@88074
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-06-03 Chris Rogers <crogers@google.com>
+
+ Reviewed by Kenneth Russell.
+
+ Allow existing AudioParams to use scheduled parameter changes
+ https://bugs.webkit.org/show_bug.cgi?id=62046
+
+ No new tests since audio API is not yet implemented.
+
+ * platform/audio/AudioBus.cpp:
+ (WebCore::AudioBus::processWithGainFrom):
+ (WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom):
+ * platform/audio/AudioBus.h:
+ * webaudio/AudioBufferSourceNode.cpp:
+ (WebCore::AudioBufferSourceNode::AudioBufferSourceNode):
+ * webaudio/AudioGainNode.cpp:
+ (WebCore::AudioGainNode::AudioGainNode):
+ (WebCore::AudioGainNode::process):
+ * webaudio/AudioGainNode.h:
+ * webaudio/HighPass2FilterNode.cpp:
+ (WebCore::HighPass2FilterNode::HighPass2FilterNode):
+ * webaudio/LowPass2FilterNode.cpp:
+ (WebCore::LowPass2FilterNode::LowPass2FilterNode):
+
2011-06-03 Chris Rogers <crogers@google.com>
Reviewed by Kenneth Russell.
{
// Make sure we're summing from same type of bus.
// We *are* able to sum from mono -> stereo
- if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus))
+ if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
+ ASSERT_NOT_REACHED();
return;
+ }
// Dispatch for different channel layouts
switch (numberOfChannels()) {
}
}
+void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
+{
+ // Make sure we're processing from the same type of bus.
+ // We *are* able to process from mono -> stereo
+ if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ if (!gainValues || numberOfGainValues > sourceBus.length()) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ // FIXME: this can potentially use SIMD optimizations with vector libraries.
+ // We handle both the 1 -> N and N -> N case here.
+ const float* source = sourceBus.channel(0)->data();
+ for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
+ if (sourceBus.numberOfChannels() == numberOfChannels())
+ source = sourceBus.channel(channelIndex)->data();
+ float* destination = channel(channelIndex)->data();
+ for (unsigned i = 0; i < numberOfGainValues; ++i)
+ destination[i] = source[i] * gainValues[i];
+ }
+}
+
void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
{
processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
void copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
void sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
+ // Copies the sourceBus by scaling with sample-accurate gain values.
+ void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);
+
// Returns maximum absolute value across all channels (useful for normalization).
float maxAbsValue() const;
m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
m_playbackRate = AudioParam::create("playbackRate", 1.0, 0.0, AudioResampler::MaxRate);
+
+ m_gain->setContext(context);
+ m_playbackRate->setContext(context);
// Default to mono. A call to setBuffer() will set the number of output channels to that of the buffer.
addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
AudioGainNode::AudioGainNode(AudioContext* context, double sampleRate)
: AudioNode(context, sampleRate)
, m_lastGain(1.0)
+ , m_sampleAccurateGainValues(AudioNode::ProcessingSizeInFrames) // FIXME: can probably share temp buffer in context
{
m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
+ m_gain->setContext(context);
addInput(adoptPtr(new AudioNodeInput(this)));
addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
initialize();
}
-void AudioGainNode::process(size_t /*framesToProcess*/)
+void AudioGainNode::process(size_t framesToProcess)
{
- // FIXME: there is a nice optimization to avoid processing here, and let the gain change
+ // FIXME: for some cases there is a nice optimization to avoid processing here, and let the gain change
// happen in the summing junction input of the AudioNode we're connected to.
// Then we can avoid all of the following:
else {
AudioBus* inputBus = input(0)->bus();
- // Apply the gain with de-zippering into the output bus.
- outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value());
+ if (gain()->hasTimelineValues()) {
+ // Apply sample-accurate gain scaling for precise envelopes, grain windows, etc.
+ ASSERT(framesToProcess <= m_sampleAccurateGainValues.size());
+ if (framesToProcess <= m_sampleAccurateGainValues.size()) {
+ float* gainValues = m_sampleAccurateGainValues.data();
+ gain()->calculateSampleAccurateValues(gainValues, framesToProcess);
+ outputBus->copyWithSampleAccurateGainValuesFrom(*inputBus, gainValues, framesToProcess);
+ }
+ } else {
+ // Apply the gain with de-zippering into the output bus.
+ outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value());
+ }
}
m_processLock.unlock();
double m_lastGain; // for de-zippering
RefPtr<AudioGain> m_gain;
+ AudioFloatArray m_sampleAccurateGainValues;
+
// This synchronizes live channel count changes which require an uninitialization / re-initialization.
// FIXME: this can go away when we implement optimization for mixing with gain directly in summing junction of AudioNodeInput.
mutable Mutex m_processLock;
: AudioBasicProcessorNode(context, sampleRate)
{
m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::HighPass2, sampleRate, 1, false));
+ biquadProcessor()->parameter1()->setContext(context);
+ biquadProcessor()->parameter2()->setContext(context);
+ biquadProcessor()->parameter3()->setContext(context);
setType(NodeTypeHighPass2Filter);
}
: AudioBasicProcessorNode(context, sampleRate)
{
m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::LowPass2, sampleRate, 1, false));
+ biquadProcessor()->parameter1()->setContext(context);
+ biquadProcessor()->parameter2()->setContext(context);
+ biquadProcessor()->parameter3()->setContext(context);
setType(NodeTypeLowPass2Filter);
}