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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
/*
* 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 "modules/webaudio/AudioBuffer.h"
#include "modules/webaudio/AudioParam.h"
#include "modules/webaudio/AudioScheduledSourceNode.h"
#include "modules/webaudio/PannerNode.h"
#include "platform/audio/AudioBus.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/Threading.h"
namespace blink {
class AbstractAudioContext;
// 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 AudioBufferSourceHandler final : public AudioScheduledSourceHandler {
public:
static PassRefPtr<AudioBufferSourceHandler> create(AudioNode&, float sampleRate, AudioParamHandler& playbackRate, AudioParamHandler& detune);
~AudioBufferSourceHandler() override;
// AudioHandler
void process(size_t framesToProcess) override;
// setBuffer() is called on the main thread. This is the buffer we use for playback.
void setBuffer(AudioBuffer*, ExceptionState&);
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 start(double when, ExceptionState&);
void start(double when, double grainOffset, ExceptionState&);
void start(double when, double grainOffset, double grainDuration, ExceptionState&);
// 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;
m_didSetLooping = m_didSetLooping || 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; }
// If a panner node is set, then we can incorporate doppler shift into the playback pitch rate.
void setPannerNode(PannerHandler*);
void clearPannerNode();
// If we are no longer playing, propogate silence ahead to downstream nodes.
bool propagatesSilence() const override;
// AudioScheduledSourceNode
void finish() override;
void handleStoppableSourceNode();
private:
AudioBufferSourceHandler(AudioNode&, float sampleRate, AudioParamHandler& playbackRate, AudioParamHandler& detune);
void startSource(double when, double grainOffset, double grainDuration, bool isDurationGiven, ExceptionState&);
// 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);
// Clamps grain parameters to the duration of the given AudioBuffer.
void clampGrainParameters(const AudioBuffer*);
// m_buffer holds the sample data which this node outputs.
// This Persistent doesn't make a reference cycle including
// AudioBufferSourceNode.
Persistent<AudioBuffer> m_buffer;
// Pointers for the buffer and destination.
OwnPtr<const float*[]> m_sourceChannels;
OwnPtr<float*[]> m_destinationChannels;
RefPtr<AudioParamHandler> m_playbackRate;
RefPtr<AudioParamHandler> m_detune;
// 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;
// True if the source .loop attribute was ever set.
bool m_didSetLooping;
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
// True if grainDuration is given explicitly (via 3 arg start method).
bool m_isDurationGiven;
// Compute playback rate (k-rate) by incorporating the sample rate conversion
// factor, the doppler shift from the associated panner node, and the value
// of playbackRate and detune AudioParams.
double computePlaybackRate();
// We optionally keep track of a panner node which has a doppler shift that
// is incorporated into the pitch rate.
// This RefPtr is connection reference. We must call AudioHandler::
// makeConnection() after ref(), and call AudioHandler::breakConnection()
// before deref().
// TODO(tkent): This is always null because setPannerNode is never
// called. If we revive setPannerNode, this should be a raw pointer and
// AudioBufferSourceNode should have Member<PannerNode>.
RefPtr<PannerHandler> m_pannerNode;
// The minimum playbackRate value ever used for this source. This includes any adjustments
// caused by doppler too.
double m_minPlaybackRate;
};
class AudioBufferSourceNode final : public AudioScheduledSourceNode {
DEFINE_WRAPPERTYPEINFO();
public:
static AudioBufferSourceNode* create(AbstractAudioContext&, float sampleRate);
DECLARE_VIRTUAL_TRACE();
AudioBufferSourceHandler& audioBufferSourceHandler() const;
AudioBuffer* buffer() const;
void setBuffer(AudioBuffer*, ExceptionState&);
AudioParam* playbackRate() const;
AudioParam* detune() const;
bool loop() const;
void setLoop(bool);
double loopStart() const;
void setLoopStart(double);
double loopEnd() const;
void setLoopEnd(double);
void start(ExceptionState&);
void start(double when, ExceptionState&);
void start(double when, double grainOffset, ExceptionState&);
void start(double when, double grainOffset, double grainDuration, ExceptionState&);
private:
AudioBufferSourceNode(AbstractAudioContext&, float sampleRate);
Member<AudioParam> m_playbackRate;
Member<AudioParam> m_detune;
};
} // namespace blink
#endif // AudioBufferSourceNode_h
|