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