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