1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/*
* 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 "AudioParam.h"
#include "AudioScheduledSourceNode.h"
#include "ExceptionCode.h"
#include "PannerNode.h"
#include <wtf/OwnArrayPtr.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 AudioScheduledSourceNode {
public:
static PassRefPtr<AudioBufferSourceNode> create(AudioContext*, float sampleRate);
virtual ~AudioBufferSourceNode();
// AudioNode
virtual void process(size_t framesToProcess);
virtual void reset();
// setBuffer() is called on the main thread. This is the buffer we use for playback.
// returns true on success.
bool 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
void startGrain(double when, double grainOffset, ExceptionCode&);
void startGrain(double when, double grainOffset, double grainDuration, ExceptionCode&);
#if ENABLE(LEGACY_WEB_AUDIO)
void noteGrainOn(double when, double grainOffset, double grainDuration, ExceptionCode&);
#endif
// Note: the attribute was originally exposed as .looping, but to be more consistent in naming with <audio>
// and with how it's described in the specification, the proper attribute name is .loop
// The old attribute is kept for backwards compatibility.
bool loop() const { return m_isLooping; }
void setLoop(bool looping) { m_isLooping = looping; }
// Loop times in seconds.
double loopStart() const { return m_loopStart; }
double loopEnd() const { return m_loopEnd; }
void setLoopStart(double loopStart) { m_loopStart = loopStart; }
void setLoopEnd(double loopEnd) { m_loopEnd = loopEnd; }
// Deprecated.
bool looping();
void setLooping(bool);
AudioParam* 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(PannerNode*);
void clearPannerNode();
// If we are no longer playing, propogate silence ahead to downstream nodes.
virtual bool propagatesSilence() const;
// AudioScheduledSourceNode
virtual void finish() OVERRIDE;
private:
AudioBufferSourceNode(AudioContext*, float sampleRate);
virtual double tailTime() const OVERRIDE { return 0; }
virtual double latencyTime() const OVERRIDE { return 0; }
// Returns true on success.
bool renderFromBuffer(AudioBus*, unsigned destinationFrameOffset, size_t numberOfFrames);
// Render silence starting from "index" frame in AudioBus.
inline bool renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess);
// m_buffer holds the sample data which this node outputs.
RefPtr<AudioBuffer> m_buffer;
// Pointers for the buffer and destination.
OwnArrayPtr<const float*> m_sourceChannels;
OwnArrayPtr<float*> m_destinationChannels;
// Used for the "gain" and "playbackRate" attributes.
RefPtr<AudioParam> m_gain;
RefPtr<AudioParam> m_playbackRate;
// 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;
double m_loopStart;
double m_loopEnd;
// m_virtualReadIndex is a sample-frame index into our buffer representing the current playback position.
// Since it's floating-point, it has sub-sample accuracy.
double m_virtualReadIndex;
// Granular playback
bool m_isGrain;
double m_grainOffset; // in seconds
double m_grainDuration; // in seconds
// 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_lastGain provides continuity when we dynamically adjust the gain.
float m_lastGain;
// We optionally keep track of a panner node which has a doppler shift that is incorporated into
// the pitch rate. We manually manage ref-counting because we want to use RefTypeConnection.
PannerNode* m_pannerNode;
// This synchronizes process() with setBuffer() which can cause dynamic channel count changes.
mutable Mutex m_processLock;
};
} // namespace WebCore
#endif // AudioBufferSourceNode_h
|