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