2010-12-07 Kenneth Russell <kbr@google.com>
[WebKit.git] / WebCore / webaudio / AudioBufferSourceNode.cpp
1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(WEB_AUDIO)
28
29 #include "AudioBufferSourceNode.h"
30
31 #include "AudioContext.h"
32 #include "AudioNodeOutput.h"
33 #include <algorithm>
34 #include <wtf/MathExtras.h>
35
36 using namespace std;
37
38 namespace WebCore {
39
40 const double DefaultGrainDuration = 0.020; // 20ms
41
42 PassRefPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* context, double sampleRate)
43 {
44     return adoptRef(new AudioBufferSourceNode(context, sampleRate));
45 }
46
47 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, double sampleRate)
48     : AudioSourceNode(context, sampleRate)
49     , m_buffer(0)
50     , m_isPlaying(false)
51     , m_isLooping(false)
52     , m_hasFinished(false)
53     , m_startTime(0.0)
54     , m_schedulingFrameDelay(0)
55     , m_readIndex(0)
56     , m_isGrain(false)
57     , m_grainOffset(0.0)
58     , m_grainDuration(DefaultGrainDuration)
59     , m_grainFrameCount(0)
60     , m_lastGain(1.0)
61     , m_pannerNode(0)
62 {
63     setType(NodeTypeAudioBufferSource);
64
65     m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
66     m_playbackRate = AudioParam::create("playbackRate", 1.0, 0.0, AudioResampler::MaxRate);
67
68     // Default to mono.  A call to setBuffer() will set the number of output channels to that of the buffer.
69     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
70
71     initialize();
72 }
73
74 AudioBufferSourceNode::~AudioBufferSourceNode()
75 {
76     uninitialize();
77 }
78
79 void AudioBufferSourceNode::process(size_t framesToProcess)
80 {
81     AudioBus* outputBus = output(0)->bus();
82
83     if (!isInitialized()) {
84         outputBus->zero();
85         return;
86     }
87
88     // The audio thread can't block on this lock, so we call tryLock() instead.
89     // Careful - this is a tryLock() and not an autolocker, so we must unlock() before every return.
90     if (m_processLock.tryLock()) {
91         // Check if it's time to start playing.
92         double sampleRate = this->sampleRate();
93         double pitchRate = totalPitchRate();
94         double quantumStartTime = context()->currentTime();
95         double quantumEndTime = quantumStartTime + framesToProcess / sampleRate;
96
97         if (!m_isPlaying || m_hasFinished || !buffer() || m_startTime >= quantumEndTime) {
98             // FIXME: can optimize here by propagating silent hint instead of forcing the whole chain to process silence.
99             outputBus->zero();
100             m_processLock.unlock();
101             return;
102         }
103
104         // Handle sample-accurate scheduling so that buffer playback will happen at a very precise time.
105         m_schedulingFrameDelay = 0;
106         if (m_startTime >= quantumStartTime) {
107             // m_schedulingFrameDelay is set here only the very first render quantum (because of above check: m_startTime >= quantumEndTime)
108             // So: quantumStartTime <= m_startTime < quantumEndTime
109             ASSERT(m_startTime < quantumEndTime);
110             
111             double startTimeInQuantum = m_startTime - quantumStartTime;
112             double startFrameInQuantum = startTimeInQuantum * sampleRate;
113             
114             // m_schedulingFrameDelay is used in provideInput(), so factor in the current playback pitch rate.
115             m_schedulingFrameDelay = static_cast<int>(pitchRate * startFrameInQuantum);
116         }
117
118         // FIXME: optimization opportunity:
119         // With a bit of work, it should be possible to avoid going through the resampler completely when the pitchRate == 1,
120         // especially if the pitchRate has never deviated from 1 in the past.
121
122         // Read the samples through the pitch resampler.  Our provideInput() method will be called by the resampler.
123         m_resampler.setRate(pitchRate);
124         m_resampler.process(this, outputBus, framesToProcess);
125
126         // Apply the gain (in-place) to the output bus.
127         double totalGain = gain()->value() * m_buffer->gain();
128         outputBus->copyWithGainFrom(*outputBus, &m_lastGain, totalGain);
129
130         m_processLock.unlock();
131     } else {
132         // Too bad - the tryLock() failed.  We must be in the middle of changing buffers and were already outputting silence anyway.
133         outputBus->zero();
134     }
135 }
136
137 // The resampler calls us back here to get the input samples from our buffer.
138 void AudioBufferSourceNode::provideInput(AudioBus* bus, size_t numberOfFrames)
139 {
140     ASSERT(context()->isAudioThread());
141     
142     // Basic sanity checking
143     ASSERT(bus);
144     ASSERT(buffer());
145     if (!bus || !buffer())
146         return;
147
148     unsigned numberOfChannels = this->numberOfChannels();
149     unsigned busNumberOfChannels = bus->numberOfChannels();
150
151     // FIXME: we can add support for sources with more than two channels, but this is not a common case.
152     bool channelCountGood = numberOfChannels == busNumberOfChannels && (numberOfChannels == 1 || numberOfChannels == 2);
153     ASSERT(channelCountGood);
154     if (!channelCountGood)
155         return;
156
157     // Get the destination pointers.
158     float* destinationL = bus->channel(0)->data();
159     ASSERT(destinationL);
160     if (!destinationL)
161         return;
162     float* destinationR = (numberOfChannels < 2) ? 0 : bus->channel(1)->data();
163
164     size_t bufferLength = buffer()->length();
165     double bufferSampleRate = buffer()->sampleRate();
166
167     // Calculate the start and end frames in our buffer that we want to play.
168     // If m_isGrain is true, then we will be playing a portion of the total buffer.
169     unsigned startFrame = m_isGrain ? static_cast<unsigned>(m_grainOffset * bufferSampleRate) : 0;
170     unsigned endFrame = m_isGrain ? static_cast<unsigned>(startFrame + m_grainDuration * bufferSampleRate) : bufferLength;
171
172     // This is a HACK to allow for HRTF tail-time - avoids glitch at end.
173     // FIXME: implement tailTime for each AudioNode for a more general solution to this problem.
174     if (m_isGrain)
175         endFrame += 512;
176
177     // Do some sanity checking.
178     if (startFrame >= bufferLength)
179         startFrame = !bufferLength ? 0 : bufferLength - 1;
180     if (endFrame > bufferLength)
181         endFrame = bufferLength;
182     if (m_readIndex >= endFrame)
183         m_readIndex = startFrame; // reset to start
184     
185     int framesToProcess = numberOfFrames;
186
187     // Handle sample-accurate scheduling so that we play the buffer at a very precise time.
188     // m_schedulingFrameDelay will only be non-zero the very first time that provideInput() is called, which corresponds
189     // with the very start of the buffer playback.
190     if (m_schedulingFrameDelay > 0) {
191         ASSERT(m_schedulingFrameDelay <= framesToProcess);
192         if (m_schedulingFrameDelay <= framesToProcess) {
193             // Generate silence for the initial portion of the destination.
194             memset(destinationL, 0, sizeof(float) * m_schedulingFrameDelay);
195             destinationL += m_schedulingFrameDelay;
196             if (destinationR) {
197                 memset(destinationR, 0, sizeof(float) * m_schedulingFrameDelay);
198                 destinationR += m_schedulingFrameDelay;
199             }
200
201             // Since we just generated silence for the initial portion, we have fewer frames to provide.
202             framesToProcess -= m_schedulingFrameDelay;
203         }
204     }
205     
206     // We have to generate a certain number of output sample-frames, but we need to handle the case where we wrap around
207     // from the end of the buffer to the start if playing back with looping and also the case where we simply reach the
208     // end of the sample data, but haven't yet rendered numberOfFrames worth of output.
209     while (framesToProcess > 0) {
210         ASSERT(m_readIndex <= endFrame);
211         if (m_readIndex > endFrame)
212             return;
213             
214         // Figure out how many frames we can process this time.
215         int framesAvailable = endFrame - m_readIndex;
216         int framesThisTime = min(framesToProcess, framesAvailable);
217         
218         // Create the destination bus for the part of the destination we're processing this time.
219         AudioBus currentDestinationBus(busNumberOfChannels, framesThisTime, false);
220         currentDestinationBus.setChannelMemory(0, destinationL, framesThisTime);
221         if (busNumberOfChannels > 1)
222             currentDestinationBus.setChannelMemory(1, destinationR, framesThisTime);
223
224         // Generate output from the buffer.
225         readFromBuffer(&currentDestinationBus, framesThisTime);
226
227         // Update the destination pointers.
228         destinationL += framesThisTime;
229         if (busNumberOfChannels > 1)
230             destinationR += framesThisTime;
231
232         framesToProcess -= framesThisTime;
233
234         // Handle the case where we reach the end of the part of the sample data we're supposed to play for the buffer.
235         if (m_readIndex >= endFrame) {
236             m_readIndex = startFrame;
237             m_grainFrameCount = 0;
238             
239             if (!looping()) {
240                 // If we're not looping, then stop playing when we get to the end.
241                 m_isPlaying = false;
242
243                 if (framesToProcess > 0) {
244                     // We're not looping and we've reached the end of the sample data, but we still need to provide more output,
245                     // so generate silence for the remaining.
246                     memset(destinationL, 0, sizeof(float) * framesToProcess);
247
248                     if (destinationR)
249                         memset(destinationR, 0, sizeof(float) * framesToProcess);
250                 }
251
252                 if (!m_hasFinished) {
253                     // Let the context dereference this AudioNode.
254                     context()->notifyNodeFinishedProcessing(this);
255                     m_hasFinished = true;
256                 }
257                 return;
258             }
259         }
260     }
261 }
262
263 void AudioBufferSourceNode::readFromBuffer(AudioBus* destinationBus, size_t framesToProcess)
264 {
265     bool isBusGood = destinationBus && destinationBus->length() == framesToProcess && destinationBus->numberOfChannels() == numberOfChannels();
266     ASSERT(isBusGood);
267     if (!isBusGood)
268         return;
269     
270     unsigned numberOfChannels = this->numberOfChannels();
271     // FIXME: we can add support for sources with more than two channels, but this is not a common case.
272     bool channelCountGood = numberOfChannels == 1 || numberOfChannels == 2;
273     ASSERT(channelCountGood);
274     if (!channelCountGood)
275         return;
276             
277     // Get pointers to the start of the sample buffer.
278     float* sourceL = m_buffer->getChannelData(0)->data();
279     float* sourceR = m_buffer->numberOfChannels() == 2 ? m_buffer->getChannelData(1)->data() : 0;
280
281     // Sanity check buffer access.
282     bool isSourceGood = sourceL && (numberOfChannels == 1 || sourceR) && m_readIndex + framesToProcess <= m_buffer->length();
283     ASSERT(isSourceGood);
284     if (!isSourceGood)
285         return;
286
287     // Offset the pointers to the current read position in the sample buffer.
288     sourceL += m_readIndex;
289     sourceR += m_readIndex;
290
291     // Get pointers to the destination.
292     float* destinationL = destinationBus->channel(0)->data();
293     float* destinationR = numberOfChannels == 2 ? destinationBus->channel(1)->data() : 0;
294     bool isDestinationGood = destinationL && (numberOfChannels == 1 || destinationR);
295     ASSERT(isDestinationGood);
296     if (!isDestinationGood)
297         return;
298
299     if (m_isGrain)
300         readFromBufferWithGrainEnvelope(sourceL, sourceR, destinationL, destinationR, framesToProcess);
301     else {
302         // Simply copy the data from the source buffer to the destination.
303         memcpy(destinationL, sourceL, sizeof(float) * framesToProcess);
304         if (numberOfChannels == 2)
305             memcpy(destinationR, sourceR, sizeof(float) * framesToProcess);
306     }
307
308     // Advance the buffer's read index.
309     m_readIndex += framesToProcess;
310 }
311
312 void AudioBufferSourceNode::readFromBufferWithGrainEnvelope(float* sourceL, float* sourceR, float* destinationL, float* destinationR, size_t framesToProcess)
313 {
314     ASSERT(sourceL && destinationL);
315     if (!sourceL || !destinationL)
316         return;
317         
318     int grainFrameLength = static_cast<int>(m_grainDuration * m_buffer->sampleRate());
319     bool isStereo = sourceR && destinationR;
320     
321     int n = framesToProcess;
322     while (n--) {
323         // Apply the grain envelope.
324         float x = static_cast<float>(m_grainFrameCount) / static_cast<float>(grainFrameLength);
325         m_grainFrameCount++;
326
327         x = min(1.0f, x);
328         float grainEnvelope = sinf(piFloat * x);
329         
330         *destinationL++ = grainEnvelope * *sourceL++;
331
332         if (isStereo)
333             *destinationR++ = grainEnvelope * *sourceR++;
334     }
335 }
336
337 void AudioBufferSourceNode::reset()
338 {
339     m_resampler.reset();
340     m_readIndex = 0;
341     m_grainFrameCount = 0;
342     m_lastGain = gain()->value();
343 }
344
345 void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer)
346 {
347     ASSERT(isMainThread());
348     
349     // The context must be locked since changing the buffer can re-configure the number of channels that are output.
350     AudioContext::AutoLocker contextLocker(context());
351     
352     // This synchronizes with process().
353     MutexLocker processLocker(m_processLock);
354     
355     if (buffer) {
356         // Do any necesssary re-configuration to the buffer's number of channels.
357         unsigned numberOfChannels = buffer->numberOfChannels();
358         m_resampler.configureChannels(numberOfChannels);
359         output(0)->setNumberOfChannels(numberOfChannels);
360     }
361
362     m_readIndex = 0;
363     m_buffer = buffer;
364 }
365
366 unsigned AudioBufferSourceNode::numberOfChannels()
367 {
368     return output(0)->numberOfChannels();
369 }
370
371 void AudioBufferSourceNode::noteOn(double when)
372 {
373     ASSERT(isMainThread());
374     if (m_isPlaying)
375         return;
376
377     m_isGrain = false;
378     m_startTime = when;
379     m_readIndex = 0;
380     m_isPlaying = true;
381 }
382
383 void AudioBufferSourceNode::noteGrainOn(double when, double grainOffset, double grainDuration)
384 {
385     ASSERT(isMainThread());
386     if (m_isPlaying)
387         return;
388
389     if (!buffer())
390         return;
391         
392     // Do sanity checking of grain parameters versus buffer size.
393     double bufferDuration = buffer()->duration();
394
395     if (grainDuration > bufferDuration)
396         return; // FIXME: maybe should throw exception - consider in specification.
397     
398     double maxGrainOffset = bufferDuration - grainDuration;
399     maxGrainOffset = max(0.0, maxGrainOffset);
400
401     grainOffset = max(0.0, grainOffset);
402     grainOffset = min(maxGrainOffset, grainOffset);    
403     m_grainOffset = grainOffset;
404
405     m_grainDuration = grainDuration;
406     m_grainFrameCount = 0;
407     
408     m_isGrain = true;
409     m_startTime = when;
410     m_readIndex = static_cast<int>(m_grainOffset * buffer()->sampleRate());
411     m_isPlaying = true;
412 }
413
414 void AudioBufferSourceNode::noteOff(double)
415 {
416     ASSERT(isMainThread());
417     if (!m_isPlaying)
418         return;
419         
420     // FIXME: the "when" argument to this method is ignored.
421     m_isPlaying = false;
422     m_readIndex = 0;
423 }
424
425 double AudioBufferSourceNode::totalPitchRate()
426 {
427     double dopplerRate = 1.0;
428     if (m_pannerNode.get())
429         dopplerRate = m_pannerNode->dopplerRate();
430     
431     // Incorporate buffer's sample-rate versus AudioContext's sample-rate.
432     // Normally it's not an issue because buffers are loaded at the AudioContext's sample-rate, but we can handle it in any case.
433     double sampleRateFactor = 1.0;
434     if (buffer())
435         sampleRateFactor = buffer()->sampleRate() / sampleRate();
436     
437     double basePitchRate = playbackRate()->value();
438
439     double totalRate = dopplerRate * sampleRateFactor * basePitchRate;
440
441     // Sanity check the total rate.  It's very important that the resampler not get any bad rate values.
442     totalRate = max(0.0, totalRate);
443     totalRate = min(AudioResampler::MaxRate, totalRate);
444     
445     bool isTotalRateValid = !isnan(totalRate) && !isinf(totalRate);
446     ASSERT(isTotalRateValid);
447     if (!isTotalRateValid)
448         totalRate = 1.0;
449     
450     return totalRate;
451 }
452
453 } // namespace WebCore
454
455 #endif // ENABLE(WEB_AUDIO)