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