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
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.
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"
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
)
59 return adoptRef(new AudioBus(numberOfChannels
, length
, allocate
));
62 AudioBus::AudioBus(unsigned numberOfChannels
, size_t length
, bool allocate
)
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
)
92 for (unsigned i
= 0; i
< m_channels
.size(); ++i
)
93 m_channels
[i
]->resizeSmaller(newLength
);
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
)
108 switch (numberOfChannels()) {
110 if (channelType
== ChannelMono
|| channelType
== ChannelLeft
)
115 switch (channelType
) {
116 case ChannelLeft
: return channel(0);
117 case ChannelRight
: return channel(1);
118 default: return nullptr;
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;
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;
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();
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
174 PassRefPtr
<AudioBus
> AudioBus::createBufferFromRange(const AudioBus
* sourceBuffer
, unsigned startFrame
, unsigned endFrame
)
176 size_t numberOfSourceFrames
= sourceBuffer
->length();
177 unsigned numberOfChannels
= sourceBuffer
->numberOfChannels();
180 bool isRangeSafe
= startFrame
< endFrame
&& endFrame
<= numberOfSourceFrames
;
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
);
196 float AudioBus::maxAbsValue() const
199 for (unsigned i
= 0; i
< numberOfChannels(); ++i
) {
200 const AudioChannel
* channel
= this->channel(i
);
201 max
= std::max(max
, channel
->maxAbsValue());
207 void AudioBus::normalize()
209 float max
= maxAbsValue();
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)
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
));
232 switch (channelInterpretation
) {
234 speakersCopyFrom(sourceBus
);
237 discreteCopyFrom(sourceBus
);
240 ASSERT_NOT_REACHED();
245 void AudioBus::sumFrom(const AudioBus
& sourceBus
, ChannelInterpretation channelInterpretation
)
247 if (&sourceBus
== this)
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
));
257 switch (channelInterpretation
) {
259 speakersSumFrom(sourceBus
);
262 discreteSumFrom(sourceBus
);
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());
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));
303 } else if (numberOfDestinationChannels
== 1 && numberOfSourceChannels
== 6) {
304 // Handle 5.1 -> mono case.
306 speakersSumFrom5_1_ToMono(sourceBus
);
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();
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
);
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();
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());
371 vadd(sourceSL
, 1, sourceSR
, 1, tempData
, 1, length());
373 vsmul(tempData
, 1, &scale
, tempData
, 1, length());
374 vadd(tempData
, 1, destination
, 1, destination
, 1, length());
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
)
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();
422 if (sourceBus
.isSilent()) {
427 unsigned numberOfChannels
= this->numberOfChannels();
428 ASSERT(numberOfChannels
<= MaxBusChannels
);
429 if (numberOfChannels
> MaxBusChannels
)
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)
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
;
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.
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();
508 if (!gainValues
|| numberOfGainValues
> sourceBus
.length()) {
509 ASSERT_NOT_REACHED();
513 if (sourceBus
.length() == numberOfGainValues
&& sourceBus
.length() == length() && sourceBus
.isSilent()) {
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())
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.
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
);
558 // First, mix to mono (if necessary) then sample-rate convert.
559 const AudioBus
* resamplerSourceBus
;
560 RefPtr
<AudioBus
> mixedMonoBus
;
562 mixedMonoBus
= AudioBus::createByMixingToMono(sourceBus
);
563 resamplerSourceBus
= mixedMonoBus
.get();
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()) {
598 // Simply create an exact copy.
599 return AudioBus::createBufferFromRange(sourceBus
, 0, sourceBus
->length());
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();
623 bool AudioBus::isSilent() const
625 for (size_t i
= 0; i
< m_channels
.size(); ++i
) {
626 if (!m_channels
[i
]->isSilent())
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();
646 PassRefPtr
<AudioBus
> AudioBus::loadPlatformResource(const char* name
, float sampleRate
)
648 const WebData
& resource
= Platform::current()->loadResource(name
);
649 if (resource
.isEmpty())
652 RefPtr
<AudioBus
> audioBus
= decodeAudioFileData(resource
.data(), resource
.size());
657 // If the bus is already at the requested sample-rate then return as is.
658 if (audioBus
->sampleRate() == sampleRate
)
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
);
670 // If the bus needs no conversion then return as is.
671 if ((!mixToMono
|| audioBus
->numberOfChannels() == 1) && audioBus
->sampleRate() == sampleRate
)
674 return AudioBus::createBySampleRateConverting(audioBus
.get(), mixToMono
, sampleRate
);
679 #endif // ENABLE(WEB_AUDIO)