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