[Webkit-unassigned] [Bug 34452] Initial patch for audio engine: AudioBus and helper classes
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Aug 31 18:22:39 PDT 2010
https://bugs.webkit.org/show_bug.cgi?id=34452
Kenneth Russell <kbr at google.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Attachment #65995|review? |review+
Flag| |
--- Comment #18 from Kenneth Russell <kbr at google.com> 2010-08-31 18:22:38 PST ---
(From update of attachment 65995)
This looks good to me; r=me. A couple of minor issues which you can fix upon commit if you're using webkit-patch land, or upload a new patch if you're going to use the commit queue.
> Index: WebCore/platform/audio/AudioBus.cpp
> ===================================================================
> --- WebCore/platform/audio/AudioBus.cpp (revision 0)
> +++ WebCore/platform/audio/AudioBus.cpp (revision 0)
> @@ -0,0 +1,364 @@
> +/*
> + * Copyright (C) 2010 Google Inc. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
> + * its contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include "config.h"
> +
> +#if ENABLE(WEB_AUDIO)
> +
> +#include "AudioBus.h"
> +
> +#include "Accelerate.h"
> +#include <assert.h>
> +#include <math.h>
> +#include <wtf/OwnPtr.h>
> +#include <wtf/PassOwnPtr.h>
> +
> +namespace WebCore {
> +
> +AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
> + : m_length(length)
> + , m_busGain(1.0)
> + , m_isFirstTime(true)
> + , m_sampleRate(0.0)
> +{
> + m_channels.reserveInitialCapacity(numberOfChannels);
> +
> + for (unsigned i = 0; i < numberOfChannels; ++i) {
> + PassOwnPtr<AudioChannel> channel = allocate ? adoptPtr(new AudioChannel(length)) : adoptPtr(new AudioChannel(0, length));
> + m_channels.append(channel);
> + }
> +
> + m_layout = LayoutCanonical; // for now this is the only layout we define
> +}
> +
> +void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length)
> +{
> + if (channelIndex < m_channels.size()) {
> + channel(channelIndex)->set(storage, length);
> + m_length = length;
This still looks fishy to me; only one of the channels is having its storage set, but the overall length of the AudioBus is being updated.
> + }
> +}
> +
> +void AudioBus::zero()
> +{
> + for (unsigned i = 0; i < m_channels.size(); ++i)
> + m_channels[i]->zero();
> +}
> +
> +AudioChannel* AudioBus::channelByType(unsigned channelType)
> +{
> + // For now we only support canonical channel layouts...
> + if (m_layout != LayoutCanonical)
> + return 0;
> +
> + switch (numberOfChannels()) {
> + case 1: // mono
> + if (channelType == ChannelMono || channelType == ChannelLeft)
> + return channel(0);
> + return 0;
> +
> + case 2: // stereo
> + switch (channelType) {
> + case ChannelLeft: return channel(0);
> + case ChannelRight: return channel(1);
> + default: return 0;
> + }
> +
> + case 4: // quad
> + switch (channelType) {
> + case ChannelLeft: return channel(0);
> + case ChannelRight: return channel(1);
> + case ChannelSurroundLeft: return channel(2);
> + case ChannelSurroundRight: return channel(3);
> + default: return 0;
> + }
> +
> + case 5: // 5.0
> + switch (channelType) {
> + case ChannelLeft: return channel(0);
> + case ChannelRight: return channel(1);
> + case ChannelCenter: return channel(2);
> + case ChannelSurroundLeft: return channel(3);
> + case ChannelSurroundRight: return channel(4);
> + default: return 0;
> + }
> +
> + case 6: // 5.1
> + switch (channelType) {
> + case ChannelLeft: return channel(0);
> + case ChannelRight: return channel(1);
> + case ChannelCenter: return channel(2);
> + case ChannelLFE: return channel(3);
> + case ChannelSurroundLeft: return channel(4);
> + case ChannelSurroundRight: return channel(5);
> + default: return 0;
> + }
> + }
> +
> + ASSERT_NOT_REACHED();
> + return 0;
> +}
> +
> +// Returns true if the channel count and frame-size match.
> +bool AudioBus::topologyMatches(const AudioBus& bus) const
> +{
> + if (numberOfChannels() != bus.numberOfChannels())
> + return false; // channel mismatch
> +
> + // Make sure source bus has enough frames.
> + if (length() > bus.length())
> + return false; // frame-size mismatch
> +
> + return true;
> +}
> +
> +PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
> +{
> + size_t numberOfSourceFrames = sourceBuffer->length();
> + unsigned numberOfChannels = sourceBuffer->numberOfChannels();
> +
> + // Sanity checking
> + bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
> + ASSERT(isRangeSafe);
> + if (!isRangeSafe)
> + return 0;
> +
> + size_t rangeLength = endFrame - startFrame;
> +
> + PassOwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(numberOfChannels, rangeLength));
If this were a PassRefPtr, holding on to it as one instead of as a RefPtr would be incorrect. To match the preferred style, use OwnPtr<AudioBus> here; see below for the return value.
> + audioBus->setSampleRate(sourceBuffer->sampleRate());
> +
> + for (unsigned i = 0; i < numberOfChannels; ++i)
> + audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
> +
> + return audioBus;
Here, use "return audioBus.release()".
> +}
> +
> +float AudioBus::maxAbsValue() const
> +{
> + float max = 0.0f;
> + for (unsigned i = 0; i < numberOfChannels(); ++i) {
> + AudioChannel* channel = const_cast<AudioBus*>(this)->channel(i);
Shouldn't you be able to write "const AudioChannel* channel = ..." now, and get rid of the const_cast?
> + float channelMax = channel->maxAbsValue();
> + if (channelMax > max)
> + max = channelMax;
Could just write "max = std::max(max, channel->maxAbsValue()".
> + }
> +
> + return max;
> +}
> +
> +void AudioBus::normalize()
> +{
> + float max = maxAbsValue();
> + if (max)
> + scale(1.0f / max);
> +}
> +
> +void AudioBus::scale(double scale)
> +{
> + for (unsigned i = 0; i < numberOfChannels(); ++i)
> + channel(i)->scale(scale);
> +}
> +
> +// Just copies the samples from the source bus to this one.
> +// This is just a simple copy if the number of channels match, otherwise a mixup or mixdown is done.
> +// For now, we just support a mixup from mono -> stereo.
> +void AudioBus::copyFrom(const AudioBus& sourceBus)
> +{
> + if (&sourceBus == this)
> + return;
> +
> + if (numberOfChannels() == sourceBus.numberOfChannels()) {
> + for (unsigned i = 0; i < numberOfChannels(); ++i)
> + channel(i)->copyFrom(sourceBus.channel(i));
> + } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
> + // Handle mono -> stereo case (for now simply copy mono channel into both left and right)
> + // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
> + const AudioChannel* sourceChannel = sourceBus.channel(0);
> + channel(0)->copyFrom(sourceChannel);
> + channel(1)->copyFrom(sourceChannel);
> + } else {
> + // Case not handled
> + ASSERT_NOT_REACHED();
> + }
> +}
> +
> +void AudioBus::sumFrom(const AudioBus &sourceBus)
> +{
> + if (numberOfChannels() == sourceBus.numberOfChannels()) {
> + for (unsigned i = 0; i < numberOfChannels(); ++i)
> + channel(i)->sumFrom(sourceBus.channel(i));
> + } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) {
> + // Handle mono -> stereo case (for now simply sum mono channel into both left and right)
> + // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
> + const AudioChannel* sourceChannel = sourceBus.channel(0);
> + channel(0)->sumFrom(sourceChannel);
> + channel(1)->sumFrom(sourceChannel);
> + } else {
> + // Case not handled
> + ASSERT_NOT_REACHED();
> + }
> +}
> +
> +void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
> +{
> + // We don't want to suddenly change the gain from mixing one time slice to the next,
> + // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
> +
> + // FIXME: optimize this method (SSE, etc.)
> + // FIXME: Need fast path here when gain has converged on targetGain. In this case, de-zippering is no longer needed.
> + // FIXME: Need fast path when this==sourceBus && lastMixGain==targetGain==1.0 && sumToBus==false (this is a NOP)
> +
> + // Take master bus gain into account as well as the targetGain.
> + double totalDesiredGain = m_busGain * targetGain;
> +
> + // First time, snap directly to totalDesiredGain.
> + double gain = m_isFirstTime ? totalDesiredGain : *lastMixGain;
> + m_isFirstTime = false;
> +
> + int numberOfSourceChannels = sourceBus.numberOfChannels();
> + int numberOfDestinationChannels = numberOfChannels();
> +
> + AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
> + const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
> + const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
> +
> + float* destinationL = channelByType(ChannelLeft)->data();
> + float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0;
> +
> + const double DezipperRate = 0.005;
> + int framesToProcess = length();
> +
> + if (sumToBus) {
> + // Sum to our bus
> + if (sourceR && destinationR) {
> + // Stereo
> + while (framesToProcess--) {
> + float sampleL = *sourceL++;
> + float sampleR = *sourceR++;
> + *destinationL++ += static_cast<float>(gain * sampleL);
> + *destinationR++ += static_cast<float>(gain * sampleR);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + } else if (destinationR) {
> + // Mono -> stereo (mix equally into L and R)
> + // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
> + while (framesToProcess--) {
> + float sample = *sourceL++;
> + *destinationL++ += static_cast<float>(gain * sample);
> + *destinationR++ += static_cast<float>(gain * sample);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + } else {
> + // Mono
> + while (framesToProcess--) {
> + float sampleL = *sourceL++;
> + *destinationL++ += static_cast<float>(gain * sampleL);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + }
> + } else {
> + // Process directly (without summing) to our bus
> + if (sourceR && destinationR) {
> + // Stereo
> + while (framesToProcess--) {
> + float sampleL = *sourceL++;
> + float sampleR = *sourceR++;
> + *destinationL++ = static_cast<float>(gain * sampleL);
> + *destinationR++ = static_cast<float>(gain * sampleR);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + } else if (destinationR) {
> + // Mono -> stereo (mix equally into L and R)
> + // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
> + while (framesToProcess--) {
> + float sample = *sourceL++;
> + *destinationL++ = static_cast<float>(gain * sample);
> + *destinationR++ = static_cast<float>(gain * sample);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + } else {
> + // Mono
> + while (framesToProcess--) {
> + float sampleL = *sourceL++;
> + *destinationL++ = static_cast<float>(gain * sampleL);
> +
> + // Slowly change gain to desired gain.
> + gain += (totalDesiredGain - gain) * DezipperRate;
> + }
> + }
> + }
> +
> + // Save the target gain as the starting point for next time around.
> + *lastMixGain = gain;
> +}
> +
> +void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)
> +{
> + // Make sure we're summing from same type of bus.
> + // We *are* able to sum from mono -> stereo
> + if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus))
> + return;
> +
> + // Dispatch for different channel layouts
> + switch (numberOfChannels()) {
> + case 1: // mono
> + case 2: // stereo
> + processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
> + break;
> + case 4: // FIXME: implement quad
> + case 5: // FIXME: implement 5.0
> + default:
> + ASSERT_NOT_REACHED();
> + break;
> + }
> +}
> +
> +void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
> +{
> + processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
> +}
> +
> +void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
> +{
> + processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
> +}
> +
> +} // WebCore
> +
> +#endif // ENABLE(WEB_AUDIO)
> Index: WebCore/platform/audio/AudioBus.h
> ===================================================================
> --- WebCore/platform/audio/AudioBus.h (revision 0)
> +++ WebCore/platform/audio/AudioBus.h (revision 0)
> @@ -0,0 +1,139 @@
> +/*
> + * Copyright (C) 2010 Google Inc. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
> + * its contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef AudioBus_h
> +#define AudioBus_h
> +
> +#include "AudioChannel.h"
> +#include <wtf/Noncopyable.h>
> +#include <wtf/PassOwnPtr.h>
> +#include <wtf/Vector.h>
> +
> +namespace WebCore {
> +
> +// An AudioBus represents a collection of one or more AudioChannels.
> +// The data layout is "planar" as opposed to "interleaved".
> +// An AudioBus with one channel is mono, an AudioBus with two channels is stereo, etc.
> +class AudioBus : public Noncopyable {
> +public:
> + enum {
> + ChannelLeft = 0,
> + ChannelRight = 1,
> + ChannelCenter = 2, // center and mono are the same
> + ChannelMono = 2,
> + ChannelLFE = 3,
> + ChannelSurroundLeft = 4,
> + ChannelSurroundRight = 5,
> + };
> +
> + enum {
> + LayoutCanonical = 0
> + // Can define non-standard layouts here
> + };
> +
> + // allocate indicates whether or not to initially have the AudioChannels created with managed storage.
> + // Normal usage is to pass true here, in which case the AudioChannels will memory-manage their own storage.
> + // If allocate is false then setChannelMemory() has to be called later on for each channel before the AudioBus is useable...
> + AudioBus(unsigned numberOfChannels, size_t length, bool allocate = true);
> +
> + // Tells the given channel to use an externally allocated buffer.
> + void setChannelMemory(unsigned channelIndex, float* storage, size_t length);
> +
> + // Channels
> + unsigned numberOfChannels() const { return m_channels.size(); }
> +
> + AudioChannel* channel(unsigned channel) { return m_channels[channel].get(); }
> + const AudioChannel* channel(unsigned channel) const { return const_cast<AudioBus*>(this)->m_channels[channel].get(); }
> + AudioChannel* channelByType(unsigned type);
> +
> + // Number of sample-frames
> + size_t length() const { return m_length; }
> +
> + // Sample-rate : 0.0 if unknown or "don't care"
> + double sampleRate() const { return m_sampleRate; }
> + void setSampleRate(double sampleRate) { m_sampleRate = sampleRate; }
> +
> + // Zeroes all channels.
> + void zero();
> +
> + // Returns true if the channel count and frame-size match.
> + bool topologyMatches(const AudioBus &sourceBus) const;
> +
> + // Creates a new buffer from a range in the source buffer.
> + // 0 may be returned if the range does not fit in the sourceBuffer
> + static PassOwnPtr<AudioBus> createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame);
> +
> + // Scales all samples by the same amount.
> + void scale(double scale);
> +
> + // Master gain for this bus - used with sumWithGainFrom() below
> + void setGain(double gain) { m_busGain = gain; }
> + double gain() { return m_busGain; }
> +
> + void reset() { m_isFirstTime = true; } // for de-zippering
> +
> + // Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.
> + void copyFrom(const AudioBus &sourceBus);
> +
> + // Sums the sourceBus into our bus with unity gain.
> + // Our own internal gain m_busGain is ignored.
> + void sumFrom(const AudioBus &sourceBus);
> +
> + // Copy or sum each channel from sourceBus into our corresponding channel.
> + // We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
> + // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be summed to this bus.
> + // This represents the dezippering memory.
> + void copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
> + void sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
> +
> + // Returns maximum absolute value across all channels (useful for normalization).
> + float maxAbsValue() const;
> +
> + // Makes maximum absolute value == 1.0 (if possible).
> + void normalize();
> +
> +protected:
> + AudioBus() { };
> +
> + void processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
> + void processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
> +
> + size_t m_length;
> +
> + Vector<OwnPtr<AudioChannel> > m_channels;
> +
> + int m_layout;
> +
> + double m_busGain;
> + bool m_isFirstTime;
> + double m_sampleRate; // 0.0 if unknown or N/A
> +};
> +
> +} // WebCore
> +
> +#endif // AudioBus_h
> Index: WebCore/platform/audio/AudioSourceProvider.h
> ===================================================================
> --- WebCore/platform/audio/AudioSourceProvider.h (revision 0)
> +++ WebCore/platform/audio/AudioSourceProvider.h (revision 0)
> @@ -0,0 +1,46 @@
> +/*
> + * Copyright (C) 2010 Google Inc. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
> + * its contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef AudioSourceProvider_h
> +#define AudioSourceProvider_h
> +
> +namespace WebCore {
> +
> +class AudioBus;
> +
> +// Abstract base-class for a pull-model client.
> +// provideInput() gets called repeatedly to render time-slices of a continuous audio stream.
> +class AudioSourceProvider {
> +public:
> + virtual void provideInput(AudioBus* bus, size_t framesToProcess) = 0;
> + virtual ~AudioSourceProvider() { }
> +};
> +
> +} // WebCore
> +
> +#endif // AudioSourceProvider_h
--
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.
More information about the webkit-unassigned
mailing list