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 "modules/webaudio/AudioBufferSourceNode.h"
30
31#include "bindings/core/v8/ExceptionState.h"
32#include "core/dom/ExceptionCode.h"
33#include "platform/audio/AudioUtilities.h"
34#include "modules/webaudio/AudioContext.h"
35#include "modules/webaudio/AudioNodeOutput.h"
36#include "platform/FloatConversion.h"
37#include "wtf/MainThread.h"
38#include "wtf/MathExtras.h"
39#include <algorithm>
40
41namespace blink {
42
43const double DefaultGrainDuration = 0.020; // 20ms
44
45// Arbitrary upper limit on playback rate.
46// Higher than expected rates can be useful when playing back oversampled buffers
47// to minimize linear interpolation aliasing.
48const double MaxRate = 1024;
49
50AudioBufferSourceNode* AudioBufferSourceNode::create(AudioContext* context, float sampleRate)
51{
52    return adoptRefCountedGarbageCollectedWillBeNoop(new AudioBufferSourceNode(context, sampleRate));
53}
54
55AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sampleRate)
56    : AudioScheduledSourceNode(context, sampleRate)
57    , m_buffer(nullptr)
58    , m_isLooping(false)
59    , m_loopStart(0)
60    , m_loopEnd(0)
61    , m_virtualReadIndex(0)
62    , m_isGrain(false)
63    , m_grainOffset(0.0)
64    , m_grainDuration(DefaultGrainDuration)
65{
66    setNodeType(NodeTypeAudioBufferSource);
67
68    m_playbackRate = AudioParam::create(context, 1.0);
69
70    // Default to mono. A call to setBuffer() will set the number of output
71    // channels to that of the buffer.
72    addOutput(AudioNodeOutput::create(this, 1));
73
74    initialize();
75}
76
77AudioBufferSourceNode::~AudioBufferSourceNode()
78{
79    ASSERT(!isInitialized());
80}
81
82void AudioBufferSourceNode::dispose()
83{
84    clearPannerNode();
85    uninitialize();
86    AudioScheduledSourceNode::dispose();
87}
88
89void AudioBufferSourceNode::process(size_t framesToProcess)
90{
91    AudioBus* outputBus = output(0)->bus();
92
93    if (!isInitialized()) {
94        outputBus->zero();
95        return;
96    }
97
98    // The audio thread can't block on this lock, so we call tryLock() instead.
99    MutexTryLocker tryLocker(m_processLock);
100    if (tryLocker.locked()) {
101        if (!buffer()) {
102            outputBus->zero();
103            return;
104        }
105
106        // After calling setBuffer() with a buffer having a different number of channels, there can in rare cases be a slight delay
107        // before the output bus is updated to the new number of channels because of use of tryLocks() in the context's updating system.
108        // In this case, if the the buffer has just been changed and we're not quite ready yet, then just output silence.
109        if (numberOfChannels() != buffer()->numberOfChannels()) {
110            outputBus->zero();
111            return;
112        }
113
114        size_t quantumFrameOffset;
115        size_t bufferFramesToProcess;
116
117        updateSchedulingInfo(framesToProcess,
118                             outputBus,
119                             quantumFrameOffset,
120                             bufferFramesToProcess);
121
122        if (!bufferFramesToProcess) {
123            outputBus->zero();
124            return;
125        }
126
127        for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i)
128            m_destinationChannels[i] = outputBus->channel(i)->mutableData();
129
130        // Render by reading directly from the buffer.
131        if (!renderFromBuffer(outputBus, quantumFrameOffset, bufferFramesToProcess)) {
132            outputBus->zero();
133            return;
134        }
135
136        outputBus->clearSilentFlag();
137    } else {
138        // Too bad - the tryLock() failed.  We must be in the middle of changing buffers and were already outputting silence anyway.
139        outputBus->zero();
140    }
141}
142
143// Returns true if we're finished.
144bool AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess)
145{
146    if (!loop()) {
147        // If we're not looping, then stop playing when we get to the end.
148
149        if (framesToProcess > 0) {
150            // We're not looping and we've reached the end of the sample data, but we still need to provide more output,
151            // so generate silence for the remaining.
152            for (unsigned i = 0; i < numberOfChannels(); ++i)
153                memset(m_destinationChannels[i] + index, 0, sizeof(float) * framesToProcess);
154        }
155
156        finish();
157        return true;
158    }
159    return false;
160}
161
162bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destinationFrameOffset, size_t numberOfFrames)
163{
164    ASSERT(context()->isAudioThread());
165
166    // Basic sanity checking
167    ASSERT(bus);
168    ASSERT(buffer());
169    if (!bus || !buffer())
170        return false;
171
172    unsigned numberOfChannels = this->numberOfChannels();
173    unsigned busNumberOfChannels = bus->numberOfChannels();
174
175    bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfChannels;
176    ASSERT(channelCountGood);
177    if (!channelCountGood)
178        return false;
179
180    // Sanity check destinationFrameOffset, numberOfFrames.
181    size_t destinationLength = bus->length();
182
183    bool isLengthGood = destinationLength <= 4096 && numberOfFrames <= 4096;
184    ASSERT(isLengthGood);
185    if (!isLengthGood)
186        return false;
187
188    bool isOffsetGood = destinationFrameOffset <= destinationLength && destinationFrameOffset + numberOfFrames <= destinationLength;
189    ASSERT(isOffsetGood);
190    if (!isOffsetGood)
191        return false;
192
193    // Potentially zero out initial frames leading up to the offset.
194    if (destinationFrameOffset) {
195        for (unsigned i = 0; i < numberOfChannels; ++i)
196            memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrameOffset);
197    }
198
199    // Offset the pointers to the correct offset frame.
200    unsigned writeIndex = destinationFrameOffset;
201
202    size_t bufferLength = buffer()->length();
203    double bufferSampleRate = buffer()->sampleRate();
204
205    // Avoid converting from time to sample-frames twice by computing
206    // the grain end time first before computing the sample frame.
207    unsigned endFrame = m_isGrain ? AudioUtilities::timeToSampleFrame(m_grainOffset + m_grainDuration, bufferSampleRate) : bufferLength;
208
209    // This is a HACK to allow for HRTF tail-time - avoids glitch at end.
210    // FIXME: implement tailTime for each AudioNode for a more general solution to this problem.
211    // https://bugs.webkit.org/show_bug.cgi?id=77224
212    if (m_isGrain)
213        endFrame += 512;
214
215    // Do some sanity checking.
216    if (endFrame > bufferLength)
217        endFrame = bufferLength;
218    if (m_virtualReadIndex >= endFrame)
219        m_virtualReadIndex = 0; // reset to start
220
221    // If the .loop attribute is true, then values of m_loopStart == 0 && m_loopEnd == 0 implies
222    // that we should use the entire buffer as the loop, otherwise use the loop values in m_loopStart and m_loopEnd.
223    double virtualEndFrame = endFrame;
224    double virtualDeltaFrames = endFrame;
225
226    if (loop() && (m_loopStart || m_loopEnd) && m_loopStart >= 0 && m_loopEnd > 0 && m_loopStart < m_loopEnd) {
227        // Convert from seconds to sample-frames.
228        double loopStartFrame = m_loopStart * buffer()->sampleRate();
229        double loopEndFrame = m_loopEnd * buffer()->sampleRate();
230
231        virtualEndFrame = std::min(loopEndFrame, virtualEndFrame);
232        virtualDeltaFrames = virtualEndFrame - loopStartFrame;
233    }
234
235
236    double pitchRate = totalPitchRate();
237
238    // Sanity check that our playback rate isn't larger than the loop size.
239    if (pitchRate >= virtualDeltaFrames)
240        return false;
241
242    // Get local copy.
243    double virtualReadIndex = m_virtualReadIndex;
244
245    // Render loop - reading from the source buffer to the destination using linear interpolation.
246    int framesToProcess = numberOfFrames;
247
248    const float** sourceChannels = m_sourceChannels.get();
249    float** destinationChannels = m_destinationChannels.get();
250
251    // Optimize for the very common case of playing back with pitchRate == 1.
252    // We can avoid the linear interpolation.
253    if (pitchRate == 1 && virtualReadIndex == floor(virtualReadIndex)
254        && virtualDeltaFrames == floor(virtualDeltaFrames)
255        && virtualEndFrame == floor(virtualEndFrame)) {
256        unsigned readIndex = static_cast<unsigned>(virtualReadIndex);
257        unsigned deltaFrames = static_cast<unsigned>(virtualDeltaFrames);
258        endFrame = static_cast<unsigned>(virtualEndFrame);
259        while (framesToProcess > 0) {
260            int framesToEnd = endFrame - readIndex;
261            int framesThisTime = std::min(framesToProcess, framesToEnd);
262            framesThisTime = std::max(0, framesThisTime);
263
264            for (unsigned i = 0; i < numberOfChannels; ++i)
265                memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] + readIndex, sizeof(float) * framesThisTime);
266
267            writeIndex += framesThisTime;
268            readIndex += framesThisTime;
269            framesToProcess -= framesThisTime;
270
271            // Wrap-around.
272            if (readIndex >= endFrame) {
273                readIndex -= deltaFrames;
274                if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess))
275                    break;
276            }
277        }
278        virtualReadIndex = readIndex;
279    } else {
280        while (framesToProcess--) {
281            unsigned readIndex = static_cast<unsigned>(virtualReadIndex);
282            double interpolationFactor = virtualReadIndex - readIndex;
283
284            // For linear interpolation we need the next sample-frame too.
285            unsigned readIndex2 = readIndex + 1;
286            if (readIndex2 >= bufferLength) {
287                if (loop()) {
288                    // Make sure to wrap around at the end of the buffer.
289                    readIndex2 = static_cast<unsigned>(virtualReadIndex + 1 - virtualDeltaFrames);
290                } else
291                    readIndex2 = readIndex;
292            }
293
294            // Final sanity check on buffer access.
295            // FIXME: as an optimization, try to get rid of this inner-loop check and put assertions and guards before the loop.
296            if (readIndex >= bufferLength || readIndex2 >= bufferLength)
297                break;
298
299            // Linear interpolation.
300            for (unsigned i = 0; i < numberOfChannels; ++i) {
301                float* destination = destinationChannels[i];
302                const float* source = sourceChannels[i];
303
304                double sample1 = source[readIndex];
305                double sample2 = source[readIndex2];
306                double sample = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2;
307
308                destination[writeIndex] = narrowPrecisionToFloat(sample);
309            }
310            writeIndex++;
311
312            virtualReadIndex += pitchRate;
313
314            // Wrap-around, retaining sub-sample position since virtualReadIndex is floating-point.
315            if (virtualReadIndex >= virtualEndFrame) {
316                virtualReadIndex -= virtualDeltaFrames;
317                if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess))
318                    break;
319            }
320        }
321    }
322
323    bus->clearSilentFlag();
324
325    m_virtualReadIndex = virtualReadIndex;
326
327    return true;
328}
329
330
331void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& exceptionState)
332{
333    ASSERT(isMainThread());
334
335    // The context must be locked since changing the buffer can re-configure the number of channels that are output.
336    AudioContext::AutoLocker contextLocker(context());
337
338    // This synchronizes with process().
339    MutexLocker processLocker(m_processLock);
340
341    if (buffer) {
342        // Do any necesssary re-configuration to the buffer's number of channels.
343        unsigned numberOfChannels = buffer->numberOfChannels();
344
345        if (numberOfChannels > AudioContext::maxNumberOfChannels()) {
346            exceptionState.throwTypeError("number of input channels (" + String::number(numberOfChannels)
347                + ") exceeds maximum ("
348                + String::number(AudioContext::maxNumberOfChannels()) + ").");
349            return;
350        }
351
352        output(0)->setNumberOfChannels(numberOfChannels);
353
354        m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]);
355        m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]);
356
357        for (unsigned i = 0; i < numberOfChannels; ++i)
358            m_sourceChannels[i] = buffer->getChannelData(i)->data();
359    }
360
361    m_virtualReadIndex = 0;
362    m_buffer = buffer;
363}
364
365unsigned AudioBufferSourceNode::numberOfChannels()
366{
367    return output(0)->numberOfChannels();
368}
369
370void AudioBufferSourceNode::start(double when, ExceptionState& exceptionState)
371{
372    AudioScheduledSourceNode::start(when, exceptionState);
373}
374
375void AudioBufferSourceNode::start(double when, double grainOffset, ExceptionState& exceptionState)
376{
377    start(when, grainOffset, buffer() ? buffer()->duration() : 0, exceptionState);
378}
379
380void AudioBufferSourceNode::start(double when, double grainOffset, double grainDuration, ExceptionState& exceptionState)
381{
382    ASSERT(isMainThread());
383
384    if (m_playbackState != UNSCHEDULED_STATE) {
385        exceptionState.throwDOMException(
386            InvalidStateError,
387            "cannot call start more than once.");
388        return;
389    }
390
391    if (!std::isfinite(when) || (when < 0)) {
392        exceptionState.throwDOMException(
393            InvalidStateError,
394            "Start time must be a finite non-negative number: " + String::number(when));
395        return;
396    }
397
398    if (!std::isfinite(grainOffset) || (grainOffset < 0)) {
399        exceptionState.throwDOMException(
400            InvalidStateError,
401            "Offset must be a finite non-negative number: " + String::number(grainOffset));
402        return;
403    }
404
405    if (!std::isfinite(grainDuration) || (grainDuration < 0)) {
406        exceptionState.throwDOMException(
407            InvalidStateError,
408            "Duration must be a finite non-negative number: " + String::number(grainDuration));
409        return;
410    }
411
412    if (!buffer())
413        return;
414
415    // Do sanity checking of grain parameters versus buffer size.
416    double bufferDuration = buffer()->duration();
417
418    grainOffset = std::max(0.0, grainOffset);
419    grainOffset = std::min(bufferDuration, grainOffset);
420    m_grainOffset = grainOffset;
421
422    double maxDuration = bufferDuration - grainOffset;
423
424    grainDuration = std::max(0.0, grainDuration);
425    grainDuration = std::min(maxDuration, grainDuration);
426    m_grainDuration = grainDuration;
427
428    m_isGrain = true;
429    m_startTime = when;
430
431    // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation
432    // at a sub-sample position since it will degrade the quality.
433    // When aligned to the sample-frame the playback will be identical to the PCM data stored in the buffer.
434    // Since playbackRate == 1 is very common, it's worth considering quality.
435    m_virtualReadIndex = AudioUtilities::timeToSampleFrame(m_grainOffset, buffer()->sampleRate());
436
437    m_playbackState = SCHEDULED_STATE;
438}
439
440double AudioBufferSourceNode::totalPitchRate()
441{
442    double dopplerRate = 1.0;
443    if (m_pannerNode)
444        dopplerRate = m_pannerNode->dopplerRate();
445
446    // Incorporate buffer's sample-rate versus AudioContext's sample-rate.
447    // Normally it's not an issue because buffers are loaded at the AudioContext's sample-rate, but we can handle it in any case.
448    double sampleRateFactor = 1.0;
449    if (buffer())
450        sampleRateFactor = buffer()->sampleRate() / sampleRate();
451
452    double basePitchRate = playbackRate()->value();
453
454    double totalRate = dopplerRate * sampleRateFactor * basePitchRate;
455
456    // Sanity check the total rate.  It's very important that the resampler not get any bad rate values.
457    totalRate = std::max(0.0, totalRate);
458    if (!totalRate)
459        totalRate = 1; // zero rate is considered illegal
460    totalRate = std::min(MaxRate, totalRate);
461
462    bool isTotalRateValid = !std::isnan(totalRate) && !std::isinf(totalRate);
463    ASSERT(isTotalRateValid);
464    if (!isTotalRateValid)
465        totalRate = 1.0;
466
467    return totalRate;
468}
469
470bool AudioBufferSourceNode::propagatesSilence() const
471{
472    return !isPlayingOrScheduled() || hasFinished() || !m_buffer;
473}
474
475void AudioBufferSourceNode::setPannerNode(PannerNode* pannerNode)
476{
477    if (m_pannerNode != pannerNode && !hasFinished()) {
478        PannerNode* oldPannerNode(m_pannerNode.release());
479        m_pannerNode = pannerNode;
480        if (pannerNode)
481            pannerNode->makeConnection();
482        if (oldPannerNode)
483            oldPannerNode->breakConnection();
484    }
485}
486
487void AudioBufferSourceNode::clearPannerNode()
488{
489    if (m_pannerNode) {
490        m_pannerNode->breakConnection();
491        m_pannerNode.clear();
492    }
493}
494
495void AudioBufferSourceNode::finish()
496{
497    clearPannerNode();
498    ASSERT(!m_pannerNode);
499    AudioScheduledSourceNode::finish();
500}
501
502void AudioBufferSourceNode::trace(Visitor* visitor)
503{
504    visitor->trace(m_buffer);
505    visitor->trace(m_playbackRate);
506    visitor->trace(m_pannerNode);
507    AudioScheduledSourceNode::trace(visitor);
508}
509
510} // namespace blink
511
512#endif // ENABLE(WEB_AUDIO)
513