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