2011-06-03 Chris Rogers <crogers@google.com>
[WebKit-https.git] / Source / 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 const double UnknownTime = -1;
42
43 PassRefPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* context, double sampleRate)
44 {
45     return adoptRef(new AudioBufferSourceNode(context, sampleRate));
46 }
47
48 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, double sampleRate)
49     : AudioSourceNode(context, sampleRate)
50     , m_buffer(0)
51     , m_isPlaying(false)
52     , m_isLooping(false)
53     , m_hasFinished(false)
54     , m_startTime(0.0)
55     , m_endTime(UnknownTime)
56     , m_schedulingFrameDelay(0)
57     , m_readIndex(0)
58     , m_isGrain(false)
59     , m_grainOffset(0.0)
60     , m_grainDuration(DefaultGrainDuration)
61     , m_grainFrameCount(0)
62     , m_lastGain(1.0)
63     , m_pannerNode(0)
64 {
65     setType(NodeTypeAudioBufferSource);
66
67     m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
68     m_playbackRate = AudioParam::create("playbackRate", 1.0, 0.0, AudioResampler::MaxRate);
69     
70     m_gain->setContext(context);
71     m_playbackRate->setContext(context);
72
73     // Default to mono.  A call to setBuffer() will set the number of output channels to that of the buffer.
74     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
75
76     initialize();
77 }
78
79 AudioBufferSourceNode::~AudioBufferSourceNode()
80 {
81     uninitialize();
82 }
83
84 void AudioBufferSourceNode::process(size_t framesToProcess)
85 {
86     AudioBus* outputBus = output(0)->bus();
87
88     if (!isInitialized()) {
89         outputBus->zero();
90         return;
91     }
92
93     // The audio thread can't block on this lock, so we call tryLock() instead.
94     // Careful - this is a tryLock() and not an autolocker, so we must unlock() before every return.
95     if (m_processLock.tryLock()) {
96         // Check if it's time to start playing.
97         double sampleRate = this->sampleRate();
98         double pitchRate = totalPitchRate();
99         double quantumStartTime = context()->currentTime();
100         double quantumEndTime = quantumStartTime + framesToProcess / sampleRate;
101
102         // If we know the end time and it's already passed, then don't bother doing any more rendering this cycle.
103         if (m_endTime != UnknownTime && m_endTime <= quantumStartTime) {
104             m_isPlaying = false;
105             m_readIndex = 0;
106             finish();
107         }
108         
109         if (!m_isPlaying || m_hasFinished || !buffer() || m_startTime >= quantumEndTime) {
110             // FIXME: can optimize here by propagating silent hint instead of forcing the whole chain to process silence.
111             outputBus->zero();
112             m_processLock.unlock();
113             return;
114         }
115
116         // Handle sample-accurate scheduling so that buffer playback will happen at a very precise time.
117         m_schedulingFrameDelay = 0;
118         if (m_startTime >= quantumStartTime) {
119             // m_schedulingFrameDelay is set here only the very first render quantum (because of above check: m_startTime >= quantumEndTime)
120             // So: quantumStartTime <= m_startTime < quantumEndTime
121             ASSERT(m_startTime < quantumEndTime);
122             
123             double startTimeInQuantum = m_startTime - quantumStartTime;
124             double startFrameInQuantum = startTimeInQuantum * sampleRate;
125             
126             // m_schedulingFrameDelay is used in provideInput(), so factor in the current playback pitch rate.
127             m_schedulingFrameDelay = static_cast<int>(pitchRate * startFrameInQuantum);
128         }
129
130         // FIXME: optimization opportunity:
131         // With a bit of work, it should be possible to avoid going through the resampler completely when the pitchRate == 1,
132         // especially if the pitchRate has never deviated from 1 in the past.
133
134         // Read the samples through the pitch resampler.  Our provideInput() method will be called by the resampler.
135         m_resampler.setRate(pitchRate);
136         m_resampler.process(this, outputBus, framesToProcess);
137
138         // Apply the gain (in-place) to the output bus.
139         double totalGain = gain()->value() * m_buffer->gain();
140         outputBus->copyWithGainFrom(*outputBus, &m_lastGain, totalGain);
141
142         // If the end time is somewhere in the middle of this time quantum, then simply zero out the
143         // frames starting at the end time.
144         if (m_endTime != UnknownTime && m_endTime >= quantumStartTime && m_endTime < quantumEndTime) {
145             unsigned zeroStartFrame = (m_endTime - quantumStartTime) * sampleRate;
146             unsigned framesToZero = framesToProcess - zeroStartFrame;
147
148             bool isSafe = zeroStartFrame < framesToProcess && framesToZero <= framesToProcess && zeroStartFrame + framesToZero <= framesToProcess;
149             ASSERT(isSafe);
150             
151             if (isSafe) {
152                 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i)
153                     memset(outputBus->channel(i)->data() + zeroStartFrame, 0, sizeof(float) * framesToZero);
154             }
155
156             m_isPlaying = false;
157             m_readIndex = 0;
158             finish();
159         }
160
161         m_processLock.unlock();
162     } else {
163         // Too bad - the tryLock() failed.  We must be in the middle of changing buffers and were already outputting silence anyway.
164         outputBus->zero();
165     }
166 }
167
168 // The resampler calls us back here to get the input samples from our buffer.
169 void AudioBufferSourceNode::provideInput(AudioBus* bus, size_t numberOfFrames)
170 {
171     ASSERT(context()->isAudioThread());
172     
173     // Basic sanity checking
174     ASSERT(bus);
175     ASSERT(buffer());
176     if (!bus || !buffer())
177         return;
178
179     unsigned numberOfChannels = this->numberOfChannels();
180     unsigned busNumberOfChannels = bus->numberOfChannels();
181
182     // FIXME: we can add support for sources with more than two channels, but this is not a common case.
183     bool channelCountGood = numberOfChannels == busNumberOfChannels && (numberOfChannels == 1 || numberOfChannels == 2);
184     ASSERT(channelCountGood);
185     if (!channelCountGood)
186         return;
187
188     // Get the destination pointers.
189     float* destinationL = bus->channel(0)->data();
190     ASSERT(destinationL);
191     if (!destinationL)
192         return;
193     float* destinationR = (numberOfChannels < 2) ? 0 : bus->channel(1)->data();
194
195     size_t bufferLength = buffer()->length();
196     double bufferSampleRate = buffer()->sampleRate();
197
198     // Calculate the start and end frames in our buffer that we want to play.
199     // If m_isGrain is true, then we will be playing a portion of the total buffer.
200     unsigned startFrame = m_isGrain ? static_cast<unsigned>(m_grainOffset * bufferSampleRate) : 0;
201     unsigned endFrame = m_isGrain ? static_cast<unsigned>(startFrame + m_grainDuration * bufferSampleRate) : bufferLength;
202
203     // This is a HACK to allow for HRTF tail-time - avoids glitch at end.
204     // FIXME: implement tailTime for each AudioNode for a more general solution to this problem.
205     if (m_isGrain)
206         endFrame += 512;
207
208     // Do some sanity checking.
209     if (startFrame >= bufferLength)
210         startFrame = !bufferLength ? 0 : bufferLength - 1;
211     if (endFrame > bufferLength)
212         endFrame = bufferLength;
213     if (m_readIndex >= endFrame)
214         m_readIndex = startFrame; // reset to start
215     
216     int framesToProcess = numberOfFrames;
217
218     // Handle sample-accurate scheduling so that we play the buffer at a very precise time.
219     // m_schedulingFrameDelay will only be non-zero the very first time that provideInput() is called, which corresponds
220     // with the very start of the buffer playback.
221     if (m_schedulingFrameDelay > 0) {
222         ASSERT(m_schedulingFrameDelay <= framesToProcess);
223         if (m_schedulingFrameDelay <= framesToProcess) {
224             // Generate silence for the initial portion of the destination.
225             memset(destinationL, 0, sizeof(float) * m_schedulingFrameDelay);
226             destinationL += m_schedulingFrameDelay;
227             if (destinationR) {
228                 memset(destinationR, 0, sizeof(float) * m_schedulingFrameDelay);
229                 destinationR += m_schedulingFrameDelay;
230             }
231
232             // Since we just generated silence for the initial portion, we have fewer frames to provide.
233             framesToProcess -= m_schedulingFrameDelay;
234         }
235     }
236     
237     // We have to generate a certain number of output sample-frames, but we need to handle the case where we wrap around
238     // from the end of the buffer to the start if playing back with looping and also the case where we simply reach the
239     // end of the sample data, but haven't yet rendered numberOfFrames worth of output.
240     while (framesToProcess > 0) {
241         ASSERT(m_readIndex <= endFrame);
242         if (m_readIndex > endFrame)
243             return;
244             
245         // Figure out how many frames we can process this time.
246         int framesAvailable = endFrame - m_readIndex;
247         int framesThisTime = min(framesToProcess, framesAvailable);
248         
249         // Create the destination bus for the part of the destination we're processing this time.
250         AudioBus currentDestinationBus(busNumberOfChannels, framesThisTime, false);
251         currentDestinationBus.setChannelMemory(0, destinationL, framesThisTime);
252         if (busNumberOfChannels > 1)
253             currentDestinationBus.setChannelMemory(1, destinationR, framesThisTime);
254
255         // Generate output from the buffer.
256         readFromBuffer(&currentDestinationBus, framesThisTime);
257
258         // Update the destination pointers.
259         destinationL += framesThisTime;
260         if (busNumberOfChannels > 1)
261             destinationR += framesThisTime;
262
263         framesToProcess -= framesThisTime;
264
265         // Handle the case where we reach the end of the part of the sample data we're supposed to play for the buffer.
266         if (m_readIndex >= endFrame) {
267             m_readIndex = startFrame;
268             m_grainFrameCount = 0;
269             
270             if (!looping()) {
271                 // If we're not looping, then stop playing when we get to the end.
272                 m_isPlaying = false;
273
274                 if (framesToProcess > 0) {
275                     // We're not looping and we've reached the end of the sample data, but we still need to provide more output,
276                     // so generate silence for the remaining.
277                     memset(destinationL, 0, sizeof(float) * framesToProcess);
278
279                     if (destinationR)
280                         memset(destinationR, 0, sizeof(float) * framesToProcess);
281                 }
282
283                 finish();
284                 return;
285             }
286         }
287     }
288 }
289
290 void AudioBufferSourceNode::readFromBuffer(AudioBus* destinationBus, size_t framesToProcess)
291 {
292     bool isBusGood = destinationBus && destinationBus->length() == framesToProcess && destinationBus->numberOfChannels() == numberOfChannels();
293     ASSERT(isBusGood);
294     if (!isBusGood)
295         return;
296     
297     unsigned numberOfChannels = this->numberOfChannels();
298     // FIXME: we can add support for sources with more than two channels, but this is not a common case.
299     bool channelCountGood = numberOfChannels == 1 || numberOfChannels == 2;
300     ASSERT(channelCountGood);
301     if (!channelCountGood)
302         return;
303             
304     // Get pointers to the start of the sample buffer.
305     float* sourceL = m_buffer->getChannelData(0)->data();
306     float* sourceR = m_buffer->numberOfChannels() == 2 ? m_buffer->getChannelData(1)->data() : 0;
307
308     // Sanity check buffer access.
309     bool isSourceGood = sourceL && (numberOfChannels == 1 || sourceR) && m_readIndex + framesToProcess <= m_buffer->length();
310     ASSERT(isSourceGood);
311     if (!isSourceGood)
312         return;
313
314     // Offset the pointers to the current read position in the sample buffer.
315     sourceL += m_readIndex;
316     sourceR += m_readIndex;
317
318     // Get pointers to the destination.
319     float* destinationL = destinationBus->channel(0)->data();
320     float* destinationR = numberOfChannels == 2 ? destinationBus->channel(1)->data() : 0;
321     bool isDestinationGood = destinationL && (numberOfChannels == 1 || destinationR);
322     ASSERT(isDestinationGood);
323     if (!isDestinationGood)
324         return;
325
326     if (m_isGrain)
327         readFromBufferWithGrainEnvelope(sourceL, sourceR, destinationL, destinationR, framesToProcess);
328     else {
329         // Simply copy the data from the source buffer to the destination.
330         memcpy(destinationL, sourceL, sizeof(float) * framesToProcess);
331         if (numberOfChannels == 2)
332             memcpy(destinationR, sourceR, sizeof(float) * framesToProcess);
333     }
334
335     // Advance the buffer's read index.
336     m_readIndex += framesToProcess;
337 }
338
339 void AudioBufferSourceNode::readFromBufferWithGrainEnvelope(float* sourceL, float* sourceR, float* destinationL, float* destinationR, size_t framesToProcess)
340 {
341     ASSERT(sourceL && destinationL);
342     if (!sourceL || !destinationL)
343         return;
344         
345     int grainFrameLength = static_cast<int>(m_grainDuration * m_buffer->sampleRate());
346     bool isStereo = sourceR && destinationR;
347     
348     int n = framesToProcess;
349     while (n--) {
350         // Apply the grain envelope.
351         float x = static_cast<float>(m_grainFrameCount) / static_cast<float>(grainFrameLength);
352         m_grainFrameCount++;
353
354         x = min(1.0f, x);
355         float grainEnvelope = sinf(piFloat * x);
356         
357         *destinationL++ = grainEnvelope * *sourceL++;
358
359         if (isStereo)
360             *destinationR++ = grainEnvelope * *sourceR++;
361     }
362 }
363
364 void AudioBufferSourceNode::reset()
365 {
366     m_resampler.reset();
367     m_readIndex = 0;
368     m_grainFrameCount = 0;
369     m_lastGain = gain()->value();
370 }
371
372 void AudioBufferSourceNode::finish()
373 {
374     if (!m_hasFinished) {
375         // Let the context dereference this AudioNode.
376         context()->notifyNodeFinishedProcessing(this);
377         m_hasFinished = true;
378     }
379 }
380
381 void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer)
382 {
383     ASSERT(isMainThread());
384     
385     // The context must be locked since changing the buffer can re-configure the number of channels that are output.
386     AudioContext::AutoLocker contextLocker(context());
387     
388     // This synchronizes with process().
389     MutexLocker processLocker(m_processLock);
390     
391     if (buffer) {
392         // Do any necesssary re-configuration to the buffer's number of channels.
393         unsigned numberOfChannels = buffer->numberOfChannels();
394         m_resampler.configureChannels(numberOfChannels);
395         output(0)->setNumberOfChannels(numberOfChannels);
396     }
397
398     m_readIndex = 0;
399     m_buffer = buffer;
400 }
401
402 unsigned AudioBufferSourceNode::numberOfChannels()
403 {
404     return output(0)->numberOfChannels();
405 }
406
407 void AudioBufferSourceNode::noteOn(double when)
408 {
409     ASSERT(isMainThread());
410     if (m_isPlaying)
411         return;
412
413     m_isGrain = false;
414     m_startTime = when;
415     m_readIndex = 0;
416     m_isPlaying = true;
417 }
418
419 void AudioBufferSourceNode::noteGrainOn(double when, double grainOffset, double grainDuration)
420 {
421     ASSERT(isMainThread());
422     if (m_isPlaying)
423         return;
424
425     if (!buffer())
426         return;
427         
428     // Do sanity checking of grain parameters versus buffer size.
429     double bufferDuration = buffer()->duration();
430
431     if (grainDuration > bufferDuration)
432         return; // FIXME: maybe should throw exception - consider in specification.
433     
434     double maxGrainOffset = bufferDuration - grainDuration;
435     maxGrainOffset = max(0.0, maxGrainOffset);
436
437     grainOffset = max(0.0, grainOffset);
438     grainOffset = min(maxGrainOffset, grainOffset);
439     m_grainOffset = grainOffset;
440
441     m_grainDuration = grainDuration;
442     m_grainFrameCount = 0;
443     
444     m_isGrain = true;
445     m_startTime = when;
446     m_readIndex = static_cast<int>(m_grainOffset * buffer()->sampleRate());
447     m_isPlaying = true;
448 }
449
450 void AudioBufferSourceNode::noteOff(double when)
451 {
452     ASSERT(isMainThread());
453     if (!m_isPlaying)
454         return;
455     
456     when = max(0.0, when);
457     m_endTime = when;
458 }
459
460 double AudioBufferSourceNode::totalPitchRate()
461 {
462     double dopplerRate = 1.0;
463     if (m_pannerNode.get())
464         dopplerRate = m_pannerNode->dopplerRate();
465     
466     // Incorporate buffer's sample-rate versus AudioContext's sample-rate.
467     // Normally it's not an issue because buffers are loaded at the AudioContext's sample-rate, but we can handle it in any case.
468     double sampleRateFactor = 1.0;
469     if (buffer())
470         sampleRateFactor = buffer()->sampleRate() / sampleRate();
471     
472     double basePitchRate = playbackRate()->value();
473
474     double totalRate = dopplerRate * sampleRateFactor * basePitchRate;
475
476     // Sanity check the total rate.  It's very important that the resampler not get any bad rate values.
477     totalRate = max(0.0, totalRate);
478     totalRate = min(AudioResampler::MaxRate, totalRate);
479     
480     bool isTotalRateValid = !isnan(totalRate) && !isinf(totalRate);
481     ASSERT(isTotalRateValid);
482     if (!isTotalRateValid)
483         totalRate = 1.0;
484     
485     return totalRate;
486 }
487
488 } // namespace WebCore
489
490 #endif // ENABLE(WEB_AUDIO)