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