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