[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