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