diff options
Diffstat (limited to 'WebCore/webaudio/AudioBufferSourceNode.h')
-rw-r--r-- | WebCore/webaudio/AudioBufferSourceNode.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/WebCore/webaudio/AudioBufferSourceNode.h b/WebCore/webaudio/AudioBufferSourceNode.h new file mode 100644 index 0000000..40b8555 --- /dev/null +++ b/WebCore/webaudio/AudioBufferSourceNode.h @@ -0,0 +1,147 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 AudioBufferSourceNode_h +#define AudioBufferSourceNode_h + +#include "AudioBuffer.h" +#include "AudioBus.h" +#include "AudioGain.h" +#include "AudioPannerNode.h" +#include "AudioResampler.h" +#include "AudioSourceNode.h" +#include "AudioSourceProvider.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/Threading.h> + +namespace WebCore { + +class AudioContext; + +// AudioBufferSourceNode is an AudioNode representing an audio source from an in-memory audio asset represented by an AudioBuffer. +// It generally will be used for short sounds which require a high degree of scheduling flexibility (can playback in rhythmically perfect ways). + +class AudioBufferSourceNode : public AudioSourceNode, public AudioSourceProvider { +public: + static PassRefPtr<AudioBufferSourceNode> create(AudioContext*, double sampleRate); + + virtual ~AudioBufferSourceNode(); + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void reset(); + + // AudioSourceProvider + // When process() is called, the resampler calls provideInput (in the audio thread) to gets its input stream. + virtual void provideInput(AudioBus*, size_t numberOfFrames); + + // setBuffer() is called on the main thread. This is the buffer we use for playback. + void setBuffer(AudioBuffer*); + AudioBuffer* buffer() { return m_buffer.get(); } + + // numberOfChannels() returns the number of output channels. This value equals the number of channels from the buffer. + // If a new buffer is set with a different number of channels, then this value will dynamically change. + unsigned numberOfChannels(); + + // Play-state + // noteOn(), noteGrainOn(), and noteOff() must all be called from the main thread. + void noteOn(double when); + void noteGrainOn(double when, double grainOffset, double grainDuration); + void noteOff(double when); + + bool looping() const { return m_isLooping; } + void setLooping(bool looping) { m_isLooping = looping; } + + AudioGain* gain() { return m_gain.get(); } + AudioParam* playbackRate() { return m_playbackRate.get(); } + + // If a panner node is set, then we can incorporate doppler shift into the playback pitch rate. + void setPannerNode(PassRefPtr<AudioPannerNode> pannerNode) { m_pannerNode = pannerNode; } + +private: + AudioBufferSourceNode(AudioContext*, double sampleRate); + + // m_buffer holds the sample data which this node outputs. + RefPtr<AudioBuffer> m_buffer; + + // Used for the "gain" and "playbackRate" attributes. + RefPtr<AudioGain> m_gain; + RefPtr<AudioParam> m_playbackRate; + + // m_isPlaying is set to true when noteOn() or noteGrainOn() is called. + bool m_isPlaying; + + // If m_isLooping is false, then this node will be done playing and become inactive after it reaches the end of the sample data in the buffer. + // If true, it will wrap around to the start of the buffer each time it reaches the end. + bool m_isLooping; + + // This node is considered finished when it reaches the end of the buffer's sample data after noteOn() has been called. + // This will only be set to true if m_isLooping == false. + bool m_hasFinished; + + // m_startTime is the time to start playing based on the context's timeline (0.0 or a time less than the context's current time means "now"). + double m_startTime; // in seconds + + // m_schedulingFrameDelay is the sample-accurate scheduling offset. + // It's used so that we start rendering audio samples at a very precise point in time. + // It will only be a non-zero value the very first render quantum that we render from the buffer. + int m_schedulingFrameDelay; + + // m_readIndex is a sample-frame index into our buffer representing the current playback position. + unsigned m_readIndex; + + // Granular playback + bool m_isGrain; + double m_grainOffset; // in seconds + double m_grainDuration; // in seconds + int m_grainFrameCount; // keeps track of which frame in the grain we're currently rendering + + // totalPitchRate() returns the instantaneous pitch rate (non-time preserving). + // It incorporates the base pitch rate, any sample-rate conversion factor from the buffer, and any doppler shift from an associated panner node. + double totalPitchRate(); + + // m_resampler performs the pitch rate changes to the buffer playback. + AudioResampler m_resampler; + + // m_lastGain provides continuity when we dynamically adjust the gain. + double m_lastGain; + + // We optionally keep track of a panner node which has a doppler shift that is incorporated into the pitch rate. + RefPtr<AudioPannerNode> m_pannerNode; + + // This synchronizes process() with setBuffer() which can cause dynamic channel count changes. + mutable Mutex m_processLock; + + // Reads the next framesToProcess sample-frames from the AudioBuffer into destinationBus. + // A grain envelope will be applied if m_isGrain is set to true. + void readFromBuffer(AudioBus* destinationBus, size_t framesToProcess); + + // readFromBufferWithGrainEnvelope() is a low-level blitter which reads from the AudioBuffer and applies a grain envelope. + void readFromBufferWithGrainEnvelope(float* sourceL, float* sourceR, float* destinationL, float* destinationR, size_t framesToProcess); +}; + +} // namespace WebCore + +#endif // AudioBufferSourceNode_h |