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