Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / audio / AudioBus.cpp
blobcaca83fa2fcbae5d2e95c0af7b0b5642f6d39995
1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
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.
29 #include "config.h"
31 #if ENABLE(WEB_AUDIO)
33 #include "platform/audio/AudioBus.h"
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"
43 #include <assert.h>
44 #include <math.h>
45 #include <algorithm>
47 namespace blink {
49 using namespace VectorMath;
51 const unsigned MaxBusChannels = 32;
53 PassRefPtr<AudioBus> AudioBus::create(unsigned numberOfChannels, size_t length, bool allocate)
55 ASSERT(numberOfChannels <= MaxBusChannels);
56 if (numberOfChannels > MaxBusChannels)
57 return nullptr;
59 return adoptRef(new AudioBus(numberOfChannels, length, 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)
68 m_channels.reserveInitialCapacity(numberOfChannels);
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);
75 m_layout = LayoutCanonical; // for now this is the only layout we define
78 void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length)
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
86 void AudioBus::resizeSmaller(size_t newLength)
88 ASSERT(newLength <= m_length);
89 if (newLength <= m_length)
90 m_length = newLength;
92 for (unsigned i = 0; i < m_channels.size(); ++i)
93 m_channels[i]->resizeSmaller(newLength);
96 void AudioBus::zero()
98 for (unsigned i = 0; i < m_channels.size(); ++i)
99 m_channels[i]->zero();
102 AudioChannel* AudioBus::channelByType(unsigned channelType)
104 // For now we only support canonical channel layouts...
105 if (m_layout != LayoutCanonical)
106 return nullptr;
108 switch (numberOfChannels()) {
109 case 1: // mono
110 if (channelType == ChannelMono || channelType == ChannelLeft)
111 return channel(0);
112 return nullptr;
114 case 2: // stereo
115 switch (channelType) {
116 case ChannelLeft: return channel(0);
117 case ChannelRight: return channel(1);
118 default: return nullptr;
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 nullptr;
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 nullptr;
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 nullptr;
152 ASSERT_NOT_REACHED();
153 return nullptr;
156 const AudioChannel* AudioBus::channelByType(unsigned type) const
158 return const_cast<AudioBus*>(this)->channelByType(type);
161 // Returns true if the channel count and frame-size match.
162 bool AudioBus::topologyMatches(const AudioBus& bus) const
164 if (numberOfChannels() != bus.numberOfChannels())
165 return false; // channel mismatch
167 // Make sure source bus has enough frames.
168 if (length() > bus.length())
169 return false; // frame-size mismatch
171 return true;
174 PassRefPtr<AudioBus> AudioBus::createBufferFromRange(const AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame)
176 size_t numberOfSourceFrames = sourceBuffer->length();
177 unsigned numberOfChannels = sourceBuffer->numberOfChannels();
179 // Sanity checking
180 bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames;
181 ASSERT(isRangeSafe);
182 if (!isRangeSafe)
183 return nullptr;
185 size_t rangeLength = endFrame - startFrame;
187 RefPtr<AudioBus> audioBus = create(numberOfChannels, rangeLength);
188 audioBus->setSampleRate(sourceBuffer->sampleRate());
190 for (unsigned i = 0; i < numberOfChannels; ++i)
191 audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame);
193 return audioBus;
196 float AudioBus::maxAbsValue() const
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());
204 return max;
207 void AudioBus::normalize()
209 float max = maxAbsValue();
210 if (max)
211 scale(1.0f / max);
214 void AudioBus::scale(float scale)
216 for (unsigned i = 0; i < numberOfChannels(); ++i)
217 channel(i)->scale(scale);
220 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation)
222 if (&sourceBus == this)
223 return;
225 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
226 unsigned numberOfDestinationChannels = numberOfChannels();
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();
245 void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation)
247 if (&sourceBus == this)
248 return;
250 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
251 unsigned numberOfDestinationChannels = numberOfChannels();
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();
270 void AudioBus::speakersCopyFrom(const AudioBus& sourceBus)
272 // FIXME: Implement down mixing 5.1 to stereo.
273 // https://bugs.webkit.org/show_bug.cgi?id=79192
275 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
276 unsigned numberOfDestinationChannels = numberOfChannels();
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);
288 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
289 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
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);
313 void AudioBus::speakersSumFrom(const AudioBus& sourceBus)
315 // FIXME: Implement down mixing 5.1 to stereo.
316 // https://bugs.webkit.org/show_bug.cgi?id=79192
318 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
319 unsigned numberOfDestinationChannels = numberOfChannels();
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);
330 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
331 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
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);
349 void AudioBus::speakersSumFrom5_1_ToMono(const AudioBus& sourceBus)
351 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
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();
359 float* destination = channelByType(ChannelLeft)->mutableData();
361 AudioFloatArray temp(length());
362 float* tempData = temp.data();
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());
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());
376 // Sum in center.
377 vadd(sourceC, 1, destination, 1, destination, 1, length());
380 void AudioBus::discreteCopyFrom(const AudioBus& sourceBus)
382 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
383 unsigned numberOfDestinationChannels = numberOfChannels();
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();
398 void AudioBus::discreteSumFrom(const AudioBus& sourceBus)
400 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
401 unsigned numberOfDestinationChannels = numberOfChannels();
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));
414 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
416 if (!topologyMatches(sourceBus)) {
417 ASSERT_NOT_REACHED();
418 zero();
419 return;
422 if (sourceBus.isSilent()) {
423 zero();
424 return;
427 unsigned numberOfChannels = this->numberOfChannels();
428 ASSERT(numberOfChannels <= MaxBusChannels);
429 if (numberOfChannels > MaxBusChannels)
430 return;
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;
436 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
437 const float* sources[MaxBusChannels];
438 float* destinations[MaxBusChannels];
440 for (unsigned i = 0; i < numberOfChannels; ++i) {
441 sources[i] = sourceBusSafe.channel(i)->data();
442 destinations[i] = channel(i)->mutableData();
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.
448 // Take master bus gain into account as well as the targetGain.
449 float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
451 // First time, snap directly to totalDesiredGain.
452 float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
453 m_isFirstTime = false;
455 const float DezipperRate = 0.005f;
456 unsigned framesToProcess = length();
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);
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;
467 if (framesToDezipper) {
468 if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper)
469 m_dezipperGainValues = adoptPtr(new AudioFloatArray(framesToDezipper));
471 float* gainValues = m_dezipperGainValues->data();
472 for (unsigned i = 0; i < framesToDezipper; ++i) {
473 gain += (totalDesiredGain - gain) * DezipperRate;
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;
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;
486 } else
487 gain = totalDesiredGain;
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);
495 // Save the target gain as the starting point for next time around.
496 *lastMixGain = gain;
499 void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
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;
508 if (!gainValues || numberOfGainValues > sourceBus.length()) {
509 ASSERT_NOT_REACHED();
510 return;
513 if (sourceBus.length() == numberOfGainValues && sourceBus.length() == length() && sourceBus.isSilent()) {
514 zero();
515 return;
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);
528 PassRefPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
530 // sourceBus's sample-rate must be known.
531 ASSERT(sourceBus && sourceBus->sampleRate());
532 if (!sourceBus || !sourceBus->sampleRate())
533 return nullptr;
535 double sourceSampleRate = sourceBus->sampleRate();
536 double destinationSampleRate = newSampleRate;
537 double sampleRateRatio = sourceSampleRate / destinationSampleRate;
538 unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
540 if (numberOfSourceChannels == 1)
541 mixToMono = false; // already mono
543 if (sourceSampleRate == destinationSampleRate) {
544 // No sample-rate conversion is necessary.
545 if (mixToMono)
546 return AudioBus::createByMixingToMono(sourceBus);
548 // Return exact copy.
549 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
552 if (sourceBus->isSilent()) {
553 RefPtr<AudioBus> silentBus = create(numberOfSourceChannels, sourceBus->length() / sampleRateRatio);
554 silentBus->setSampleRate(newSampleRate);
555 return silentBus;
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;
569 // Calculate destination length based on the sample-rates.
570 int sourceLength = resamplerSourceBus->length();
571 int destinationLength = sourceLength / sampleRateRatio;
573 // Create destination bus with same number of channels.
574 unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels();
575 RefPtr<AudioBus> destinationBus = create(numberOfDestinationChannels, destinationLength);
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();
582 SincResampler resampler(sampleRateRatio);
583 resampler.process(source, destination, sourceLength);
586 destinationBus->clearSilentFlag();
587 destinationBus->setSampleRate(newSampleRate);
588 return destinationBus;
591 PassRefPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
593 if (sourceBus->isSilent())
594 return create(1, sourceBus->length());
596 switch (sourceBus->numberOfChannels()) {
597 case 1:
598 // Simply create an exact copy.
599 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
600 case 2:
602 unsigned n = sourceBus->length();
603 RefPtr<AudioBus> destinationBus = create(1, n);
605 const float* sourceL = sourceBus->channel(0)->data();
606 const float* sourceR = sourceBus->channel(1)->data();
607 float* destination = destinationBus->channel(0)->mutableData();
609 // Do the mono mixdown.
610 for (unsigned i = 0; i < n; ++i)
611 destination[i] = (sourceL[i] + sourceR[i]) / 2;
613 destinationBus->clearSilentFlag();
614 destinationBus->setSampleRate(sourceBus->sampleRate());
615 return destinationBus;
619 ASSERT_NOT_REACHED();
620 return nullptr;
623 bool AudioBus::isSilent() const
625 for (size_t i = 0; i < m_channels.size(); ++i) {
626 if (!m_channels[i]->isSilent())
627 return false;
629 return true;
632 void AudioBus::clearSilentFlag()
634 for (size_t i = 0; i < m_channels.size(); ++i)
635 m_channels[i]->clearSilentFlag();
638 PassRefPtr<AudioBus> decodeAudioFileData(const char* data, size_t size)
640 WebAudioBus webAudioBus;
641 if (Platform::current()->loadAudioResource(&webAudioBus, data, size))
642 return webAudioBus.release();
643 return nullptr;
646 PassRefPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, float sampleRate)
648 const WebData& resource = Platform::current()->loadResource(name);
649 if (resource.isEmpty())
650 return nullptr;
652 RefPtr<AudioBus> audioBus = decodeAudioFileData(resource.data(), resource.size());
654 if (!audioBus.get())
655 return nullptr;
657 // If the bus is already at the requested sample-rate then return as is.
658 if (audioBus->sampleRate() == sampleRate)
659 return audioBus;
661 return AudioBus::createBySampleRateConverting(audioBus.get(), false, sampleRate);
664 PassRefPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, float sampleRate)
666 RefPtr<AudioBus> audioBus = decodeAudioFileData(static_cast<const char*>(data), dataSize);
667 if (!audioBus.get())
668 return nullptr;
670 // If the bus needs no conversion then return as is.
671 if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRate() == sampleRate)
672 return audioBus;
674 return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sampleRate);
677 } // namespace blink
679 #endif // ENABLE(WEB_AUDIO)