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 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30
31#if ENABLE(WEB_AUDIO)
32
33#include "AudioBus.h"
34
35#include "DenormalDisabler.h"
36
37#include "SincResampler.h"
38#include "VectorMath.h"
39#include <algorithm>
40#include <assert.h>
41#include <math.h>
42
43namespace WebCore {
44
45using namespace VectorMath;
46
47const unsigned MaxBusChannels = 32;
48
49PassRefPtr<AudioBus> AudioBus::create(unsigned numberOfChannels, size_t length, bool allocate)
50{
51    ASSERT(numberOfChannels <= MaxBusChannels);
52    if (numberOfChannels > MaxBusChannels)
53        return 0;
54
55    return adoptRef(new AudioBus(numberOfChannels, length, allocate));
56}
57
58AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
59    : m_length(length)
60    , m_busGain(1)
61    , m_isFirstTime(true)
62    , m_sampleRate(0)
63{
64    m_channels.reserveInitialCapacity(numberOfChannels);
65
66    for (unsigned i = 0; i < numberOfChannels; ++i) {
67        auto channel = allocate ? std::make_unique<AudioChannel>(length) : std::make_unique<AudioChannel>(nullptr, length);
68        m_channels.append(WTF::move(channel));
69    }
70
71    m_layout = LayoutCanonical; // for now this is the only layout we define
72}
73
74void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length)
75{
76    if (channelIndex < m_channels.size()) {
77        channel(channelIndex)->set(storage, length);
78        m_length = length; // FIXME: verify that this length matches all the other channel lengths
79    }
80}
81
82void AudioBus::resizeSmaller(size_t newLength)
83{
84    ASSERT(newLength <= m_length);
85    if (newLength <= m_length)
86        m_length = newLength;
87
88    for (unsigned i = 0; i < m_channels.size(); ++i)
89        m_channels[i]->resizeSmaller(newLength);
90}
91
92void AudioBus::zero()
93{
94    for (unsigned i = 0; i < m_channels.size(); ++i)
95        m_channels[i]->zero();
96}
97
98AudioChannel* AudioBus::channelByType(unsigned channelType)
99{
100    // For now we only support canonical channel layouts...
101    if (m_layout != LayoutCanonical)
102        return 0;
103
104    switch (numberOfChannels()) {
105    case 1: // mono
106        if (channelType == ChannelMono || channelType == ChannelLeft)
107            return channel(0);
108        return 0;
109
110    case 2: // stereo
111        switch (channelType) {
112        case ChannelLeft: return channel(0);
113        case ChannelRight: return channel(1);
114        default: return 0;
115        }
116
117    case 4: // quad
118        switch (channelType) {
119        case ChannelLeft: return channel(0);
120        case ChannelRight: return channel(1);
121        case ChannelSurroundLeft: return channel(2);
122        case ChannelSurroundRight: return channel(3);
123        default: return 0;
124        }
125
126    case 5: // 5.0
127        switch (channelType) {
128        case ChannelLeft: return channel(0);
129        case ChannelRight: return channel(1);
130        case ChannelCenter: return channel(2);
131        case ChannelSurroundLeft: return channel(3);
132        case ChannelSurroundRight: return channel(4);
133        default: return 0;
134        }
135
136    case 6: // 5.1
137        switch (channelType) {
138        case ChannelLeft: return channel(0);
139        case ChannelRight: return channel(1);
140        case ChannelCenter: return channel(2);
141        case ChannelLFE: return channel(3);
142        case ChannelSurroundLeft: return channel(4);
143        case ChannelSurroundRight: return channel(5);
144        default: return 0;
145        }
146    }
147
148    ASSERT_NOT_REACHED();
149    return 0;
150}
151
152const AudioChannel* AudioBus::channelByType(unsigned type) const
153{
154    return const_cast<AudioBus*>(this)->channelByType(type);
155}
156
157// Returns true if the channel count and frame-size match.
158bool AudioBus::topologyMatches(const AudioBus& bus) const
159{
160    if (numberOfChannels() != bus.numberOfChannels())
161        return false; // channel mismatch
162
163    // Make sure source bus has enough frames.
164    if (length() > bus.length())
165        return false; // frame-size mismatch
166
167    return true;
168}
169
170PassRefPtr<AudioBus> AudioBus::createBufferFromRange(const AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
171{
172    size_t numberOfSourceFrames = sourceBuffer->length();
173    unsigned numberOfChannels = sourceBuffer->numberOfChannels();
174
175    // Sanity checking
176    bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
177    ASSERT(isRangeSafe);
178    if (!isRangeSafe)
179        return 0;
180
181    size_t rangeLength = endFrame - startFrame;
182
183    RefPtr<AudioBus> audioBus = create(numberOfChannels, rangeLength);
184    audioBus->setSampleRate(sourceBuffer->sampleRate());
185
186    for (unsigned i = 0; i < numberOfChannels; ++i)
187        audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
188
189    return audioBus;
190}
191
192float AudioBus::maxAbsValue() const
193{
194    float max = 0.0f;
195    for (unsigned i = 0; i < numberOfChannels(); ++i) {
196        const AudioChannel* channel = this->channel(i);
197        max = std::max(max, channel->maxAbsValue());
198    }
199
200    return max;
201}
202
203void AudioBus::normalize()
204{
205    float max = maxAbsValue();
206    if (max)
207        scale(1.0f / max);
208}
209
210void AudioBus::scale(float scale)
211{
212    for (unsigned i = 0; i < numberOfChannels(); ++i)
213        channel(i)->scale(scale);
214}
215
216void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation)
217{
218    if (&sourceBus == this)
219        return;
220
221    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
222    unsigned numberOfDestinationChannels = numberOfChannels();
223
224    if (numberOfDestinationChannels == numberOfSourceChannels) {
225        for (unsigned i = 0; i < numberOfSourceChannels; ++i)
226            channel(i)->copyFrom(sourceBus.channel(i));
227    } else {
228        switch (channelInterpretation) {
229        case Speakers:
230            speakersCopyFrom(sourceBus);
231            break;
232        case Discrete:
233            discreteCopyFrom(sourceBus);
234            break;
235        default:
236            ASSERT_NOT_REACHED();
237        }
238    }
239}
240
241void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation)
242{
243    if (&sourceBus == this)
244        return;
245
246    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
247    unsigned numberOfDestinationChannels = numberOfChannels();
248
249    if (numberOfDestinationChannels == numberOfSourceChannels) {
250        for (unsigned i = 0; i < numberOfSourceChannels; ++i)
251            channel(i)->sumFrom(sourceBus.channel(i));
252    } else {
253        switch (channelInterpretation) {
254        case Speakers:
255            speakersSumFrom(sourceBus);
256            break;
257        case Discrete:
258            discreteSumFrom(sourceBus);
259            break;
260        default:
261            ASSERT_NOT_REACHED();
262        }
263    }
264}
265
266void AudioBus::speakersCopyFrom(const AudioBus& sourceBus)
267{
268    // FIXME: Implement down mixing 5.1 to stereo.
269    // https://bugs.webkit.org/show_bug.cgi?id=79192
270
271    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
272    unsigned numberOfDestinationChannels = numberOfChannels();
273
274    if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) {
275        // Handle mono -> stereo case (for now simply copy mono channel into both left and right)
276        // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
277        const AudioChannel* sourceChannel = sourceBus.channel(0);
278        channel(0)->copyFrom(sourceChannel);
279        channel(1)->copyFrom(sourceChannel);
280    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
281        // Handle stereo -> mono case. output = 0.5 * (input.L + input.R).
282        AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
283
284        const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
285        const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
286
287        float* destination = channelByType(ChannelLeft)->mutableData();
288        vadd(sourceL, 1, sourceR, 1, destination, 1, length());
289        float scale = 0.5;
290        vsmul(destination, 1, &scale, destination, 1, length());
291    } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
292        // Handle mono -> 5.1 case, copy mono channel to center.
293        channel(2)->copyFrom(sourceBus.channel(0));
294        channel(0)->zero();
295        channel(1)->zero();
296        channel(3)->zero();
297        channel(4)->zero();
298        channel(5)->zero();
299    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
300        // Handle 5.1 -> mono case.
301        zero();
302        speakersSumFrom5_1_ToMono(sourceBus);
303    } else {
304        // Fallback for unknown combinations.
305        discreteCopyFrom(sourceBus);
306    }
307}
308
309void AudioBus::speakersSumFrom(const AudioBus& sourceBus)
310{
311    // FIXME: Implement down mixing 5.1 to stereo.
312    // https://bugs.webkit.org/show_bug.cgi?id=79192
313
314    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
315    unsigned numberOfDestinationChannels = numberOfChannels();
316
317    if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) {
318        // Handle mono -> stereo case (summing mono channel into both left and right).
319        const AudioChannel* sourceChannel = sourceBus.channel(0);
320        channel(0)->sumFrom(sourceChannel);
321        channel(1)->sumFrom(sourceChannel);
322    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
323        // Handle stereo -> mono case. output += 0.5 * (input.L + input.R).
324        AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
325
326        const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
327        const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
328
329        float* destination = channelByType(ChannelLeft)->mutableData();
330        float scale = 0.5;
331        vsma(sourceL, 1, &scale, destination, 1, length());
332        vsma(sourceR, 1, &scale, destination, 1, length());
333    } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
334        // Handle mono -> 5.1 case, sum mono channel into center.
335        channel(2)->sumFrom(sourceBus.channel(0));
336    } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
337        // Handle 5.1 -> mono case.
338        speakersSumFrom5_1_ToMono(sourceBus);
339    } else {
340        // Fallback for unknown combinations.
341        discreteSumFrom(sourceBus);
342    }
343}
344
345void AudioBus::speakersSumFrom5_1_ToMono(const AudioBus& sourceBus)
346{
347    AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
348
349    const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
350    const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
351    const float* sourceC = sourceBusSafe.channelByType(ChannelCenter)->data();
352    const float* sourceSL = sourceBusSafe.channelByType(ChannelSurroundLeft)->data();
353    const float* sourceSR = sourceBusSafe.channelByType(ChannelSurroundRight)->data();
354
355    float* destination = channelByType(ChannelLeft)->mutableData();
356
357    AudioFloatArray temp(length());
358    float* tempData = temp.data();
359
360    // Sum in L and R.
361    vadd(sourceL, 1, sourceR, 1, tempData, 1, length());
362    float scale = 0.7071;
363    vsmul(tempData, 1, &scale, tempData, 1, length());
364    vadd(tempData, 1, destination, 1, destination, 1, length());
365
366    // Sum in SL and SR.
367    vadd(sourceSL, 1, sourceSR, 1, tempData, 1, length());
368    scale = 0.5;
369    vsmul(tempData, 1, &scale, tempData, 1, length());
370    vadd(tempData, 1, destination, 1, destination, 1, length());
371
372    // Sum in center.
373    vadd(sourceC, 1, destination, 1, destination, 1, length());
374}
375
376void AudioBus::discreteCopyFrom(const AudioBus& sourceBus)
377{
378    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
379    unsigned numberOfDestinationChannels = numberOfChannels();
380
381    if (numberOfDestinationChannels < numberOfSourceChannels) {
382        // Down-mix by copying channels and dropping the remaining.
383        for (unsigned i = 0; i < numberOfDestinationChannels; ++i)
384            channel(i)->copyFrom(sourceBus.channel(i));
385    } else if (numberOfDestinationChannels > numberOfSourceChannels) {
386        // Up-mix by copying as many channels as we have, then zeroing remaining channels.
387        for (unsigned i = 0; i < numberOfSourceChannels; ++i)
388            channel(i)->copyFrom(sourceBus.channel(i));
389        for (unsigned i = numberOfSourceChannels; i < numberOfDestinationChannels; ++i)
390            channel(i)->zero();
391    }
392}
393
394void AudioBus::discreteSumFrom(const AudioBus& sourceBus)
395{
396    unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
397    unsigned numberOfDestinationChannels = numberOfChannels();
398
399    if (numberOfDestinationChannels < numberOfSourceChannels) {
400        // Down-mix by summing channels and dropping the remaining.
401        for (unsigned i = 0; i < numberOfDestinationChannels; ++i)
402            channel(i)->sumFrom(sourceBus.channel(i));
403    } else if (numberOfDestinationChannels > numberOfSourceChannels) {
404        // Up-mix by summing as many channels as we have.
405        for (unsigned i = 0; i < numberOfSourceChannels; ++i)
406            channel(i)->sumFrom(sourceBus.channel(i));
407    }
408}
409
410void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
411{
412    if (!topologyMatches(sourceBus)) {
413        ASSERT_NOT_REACHED();
414        zero();
415        return;
416    }
417
418    if (sourceBus.isSilent()) {
419        zero();
420        return;
421    }
422
423    unsigned numberOfChannels = this->numberOfChannels();
424    ASSERT(numberOfChannels <= MaxBusChannels);
425    if (numberOfChannels > MaxBusChannels)
426        return;
427
428    // If it is copying from the same bus and no need to change gain, just return.
429    if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1)
430        return;
431
432    AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
433    const float* sources[MaxBusChannels];
434    float* destinations[MaxBusChannels];
435
436    for (unsigned i = 0; i < numberOfChannels; ++i) {
437        sources[i] = sourceBusSafe.channel(i)->data();
438        destinations[i] = channel(i)->mutableData();
439    }
440
441    // We don't want to suddenly change the gain from mixing one time slice to the next,
442    // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
443
444    // Take master bus gain into account as well as the targetGain.
445    float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
446
447    // First time, snap directly to totalDesiredGain.
448    float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
449    m_isFirstTime = false;
450
451    const float DezipperRate = 0.005f;
452    unsigned framesToProcess = length();
453
454    // If the gain is within epsilon of totalDesiredGain, we can skip dezippering.
455    // FIXME: this value may need tweaking.
456    const float epsilon = 0.001f;
457    float gainDiff = fabs(totalDesiredGain - gain);
458
459    // Number of frames to de-zipper before we are close enough to the target gain.
460    // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop.
461    unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess;
462
463    if (framesToDezipper) {
464        if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper)
465            m_dezipperGainValues = std::make_unique<AudioFloatArray>(framesToDezipper);
466
467        float* gainValues = m_dezipperGainValues->data();
468        for (unsigned i = 0; i < framesToDezipper; ++i) {
469            gain += (totalDesiredGain - gain) * DezipperRate;
470
471            // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get
472            // rid of this DenormalDisabler::flushDenormalFloatToZero() call.
473            gain = DenormalDisabler::flushDenormalFloatToZero(gain);
474            *gainValues++ = gain;
475        }
476
477        for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
478            vmul(sources[channelIndex], 1, m_dezipperGainValues->data(), 1, destinations[channelIndex], 1, framesToDezipper);
479            sources[channelIndex] += framesToDezipper;
480            destinations[channelIndex] += framesToDezipper;
481        }
482    } else
483        gain = totalDesiredGain;
484
485    // Apply constant gain after de-zippering has converged on target gain.
486    if (framesToDezipper < framesToProcess) {
487        for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
488            vsmul(sources[channelIndex], 1, &gain, destinations[channelIndex], 1, framesToProcess - framesToDezipper);
489    }
490
491    // Save the target gain as the starting point for next time around.
492    *lastMixGain = gain;
493}
494
495void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
496{
497    // Make sure we're processing from the same type of bus.
498    // We *are* able to process from mono -> stereo
499    if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
500        ASSERT_NOT_REACHED();
501        return;
502    }
503
504    if (!gainValues || numberOfGainValues > sourceBus.length()) {
505        ASSERT_NOT_REACHED();
506        return;
507    }
508
509    if (sourceBus.length() == numberOfGainValues && sourceBus.length() == length() && sourceBus.isSilent()) {
510        zero();
511        return;
512    }
513
514    // We handle both the 1 -> N and N -> N case here.
515    const float* source = sourceBus.channel(0)->data();
516    for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
517        if (sourceBus.numberOfChannels() == numberOfChannels())
518            source = sourceBus.channel(channelIndex)->data();
519        float* destination = channel(channelIndex)->mutableData();
520        vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues);
521    }
522}
523
524PassRefPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
525{
526    // sourceBus's sample-rate must be known.
527    ASSERT(sourceBus && sourceBus->sampleRate());
528    if (!sourceBus || !sourceBus->sampleRate())
529        return 0;
530
531    double sourceSampleRate = sourceBus->sampleRate();
532    double destinationSampleRate = newSampleRate;
533    double sampleRateRatio = sourceSampleRate / destinationSampleRate;
534    unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
535
536    if (numberOfSourceChannels == 1)
537        mixToMono = false; // already mono
538
539    if (sourceSampleRate == destinationSampleRate) {
540        // No sample-rate conversion is necessary.
541        if (mixToMono)
542            return AudioBus::createByMixingToMono(sourceBus);
543
544        // Return exact copy.
545        return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
546    }
547
548    if (sourceBus->isSilent()) {
549        RefPtr<AudioBus> silentBus = create(numberOfSourceChannels, sourceBus->length() / sampleRateRatio);
550        silentBus->setSampleRate(newSampleRate);
551        return silentBus;
552    }
553
554    // First, mix to mono (if necessary) then sample-rate convert.
555    const AudioBus* resamplerSourceBus;
556    RefPtr<AudioBus> mixedMonoBus;
557    if (mixToMono) {
558        mixedMonoBus = AudioBus::createByMixingToMono(sourceBus);
559        resamplerSourceBus = mixedMonoBus.get();
560    } else {
561        // Directly resample without down-mixing.
562        resamplerSourceBus = sourceBus;
563    }
564
565    // Calculate destination length based on the sample-rates.
566    int sourceLength = resamplerSourceBus->length();
567    int destinationLength = sourceLength / sampleRateRatio;
568
569    // Create destination bus with same number of channels.
570    unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
571    RefPtr<AudioBus> destinationBus = create(numberOfDestinationChannels, destinationLength);
572
573    // Sample-rate convert each channel.
574    for (unsigned i = 0; i < numberOfDestinationChannels; ++i) {
575        const float* source = resamplerSourceBus->channel(i)->data();
576        float* destination = destinationBus->channel(i)->mutableData();
577
578        SincResampler resampler(sampleRateRatio);
579        resampler.process(source, destination, sourceLength);
580    }
581
582    destinationBus->clearSilentFlag();
583    destinationBus->setSampleRate(newSampleRate);
584    return destinationBus;
585}
586
587PassRefPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
588{
589    if (sourceBus->isSilent())
590        return create(1, sourceBus->length());
591
592    switch (sourceBus->numberOfChannels()) {
593    case 1:
594        // Simply create an exact copy.
595        return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
596    case 2:
597        {
598            unsigned n = sourceBus->length();
599            RefPtr<AudioBus> destinationBus = create(1, n);
600
601            const float* sourceL = sourceBus->channel(0)->data();
602            const float* sourceR = sourceBus->channel(1)->data();
603            float* destination = destinationBus->channel(0)->mutableData();
604
605            // Do the mono mixdown.
606            for (unsigned i = 0; i < n; ++i)
607                destination[i] = (sourceL[i] + sourceR[i]) / 2;
608
609            destinationBus->clearSilentFlag();
610            destinationBus->setSampleRate(sourceBus->sampleRate());
611            return destinationBus;
612        }
613    }
614
615    ASSERT_NOT_REACHED();
616    return 0;
617}
618
619bool AudioBus::isSilent() const
620{
621    for (size_t i = 0; i < m_channels.size(); ++i) {
622        if (!m_channels[i]->isSilent())
623            return false;
624    }
625    return true;
626}
627
628void AudioBus::clearSilentFlag()
629{
630    for (size_t i = 0; i < m_channels.size(); ++i)
631        m_channels[i]->clearSilentFlag();
632}
633
634} // WebCore
635
636#endif // ENABLE(WEB_AUDIO)
637