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 49PassRefPtr<AudioBus> AudioBus::create(unsigned numberOfChannels, size_t length, bool allocate) 50{ 51 ASSERT(numberOfChannels <= MaxBusChannels); 52 if (numberOfChannels > MaxBusChannels) 53 return 0; 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.append(WTF::move(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 170PassRefPtr<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 0; 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::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation) 217{ 218 if (&sourceBus == this) 219 return; 220 221 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 222 unsigned numberOfDestinationChannels = numberOfChannels(); 223 224 if (numberOfDestinationChannels == numberOfSourceChannels) { 225 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 226 channel(i)->copyFrom(sourceBus.channel(i)); 227 } else { 228 switch (channelInterpretation) { 229 case Speakers: 230 speakersCopyFrom(sourceBus); 231 break; 232 case Discrete: 233 discreteCopyFrom(sourceBus); 234 break; 235 default: 236 ASSERT_NOT_REACHED(); 237 } 238 } 239} 240 241void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation) 242{ 243 if (&sourceBus == this) 244 return; 245 246 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 247 unsigned numberOfDestinationChannels = numberOfChannels(); 248 249 if (numberOfDestinationChannels == numberOfSourceChannels) { 250 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 251 channel(i)->sumFrom(sourceBus.channel(i)); 252 } else { 253 switch (channelInterpretation) { 254 case Speakers: 255 speakersSumFrom(sourceBus); 256 break; 257 case Discrete: 258 discreteSumFrom(sourceBus); 259 break; 260 default: 261 ASSERT_NOT_REACHED(); 262 } 263 } 264} 265 266void AudioBus::speakersCopyFrom(const AudioBus& sourceBus) 267{ 268 // FIXME: Implement down mixing 5.1 to stereo. 269 // https://bugs.webkit.org/show_bug.cgi?id=79192 270 271 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 272 unsigned numberOfDestinationChannels = numberOfChannels(); 273 274 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) { 275 // Handle mono -> stereo case (for now simply copy mono channel into both left and right) 276 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... 277 const AudioChannel* sourceChannel = sourceBus.channel(0); 278 channel(0)->copyFrom(sourceChannel); 279 channel(1)->copyFrom(sourceChannel); 280 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) { 281 // Handle stereo -> mono case. output = 0.5 * (input.L + input.R). 282 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 283 284 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); 285 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data(); 286 287 float* destination = channelByType(ChannelLeft)->mutableData(); 288 vadd(sourceL, 1, sourceR, 1, destination, 1, length()); 289 float scale = 0.5; 290 vsmul(destination, 1, &scale, destination, 1, length()); 291 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) { 292 // Handle mono -> 5.1 case, copy mono channel to center. 293 channel(2)->copyFrom(sourceBus.channel(0)); 294 channel(0)->zero(); 295 channel(1)->zero(); 296 channel(3)->zero(); 297 channel(4)->zero(); 298 channel(5)->zero(); 299 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) { 300 // Handle 5.1 -> mono case. 301 zero(); 302 speakersSumFrom5_1_ToMono(sourceBus); 303 } else { 304 // Fallback for unknown combinations. 305 discreteCopyFrom(sourceBus); 306 } 307} 308 309void AudioBus::speakersSumFrom(const AudioBus& sourceBus) 310{ 311 // FIXME: Implement down mixing 5.1 to stereo. 312 // https://bugs.webkit.org/show_bug.cgi?id=79192 313 314 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 315 unsigned numberOfDestinationChannels = numberOfChannels(); 316 317 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) { 318 // Handle mono -> stereo case (summing mono channel into both left and right). 319 const AudioChannel* sourceChannel = sourceBus.channel(0); 320 channel(0)->sumFrom(sourceChannel); 321 channel(1)->sumFrom(sourceChannel); 322 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) { 323 // Handle stereo -> mono case. output += 0.5 * (input.L + input.R). 324 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 325 326 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); 327 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data(); 328 329 float* destination = channelByType(ChannelLeft)->mutableData(); 330 float scale = 0.5; 331 vsma(sourceL, 1, &scale, destination, 1, length()); 332 vsma(sourceR, 1, &scale, destination, 1, length()); 333 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) { 334 // Handle mono -> 5.1 case, sum mono channel into center. 335 channel(2)->sumFrom(sourceBus.channel(0)); 336 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) { 337 // Handle 5.1 -> mono case. 338 speakersSumFrom5_1_ToMono(sourceBus); 339 } else { 340 // Fallback for unknown combinations. 341 discreteSumFrom(sourceBus); 342 } 343} 344 345void AudioBus::speakersSumFrom5_1_ToMono(const AudioBus& sourceBus) 346{ 347 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 348 349 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); 350 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data(); 351 const float* sourceC = sourceBusSafe.channelByType(ChannelCenter)->data(); 352 const float* sourceSL = sourceBusSafe.channelByType(ChannelSurroundLeft)->data(); 353 const float* sourceSR = sourceBusSafe.channelByType(ChannelSurroundRight)->data(); 354 355 float* destination = channelByType(ChannelLeft)->mutableData(); 356 357 AudioFloatArray temp(length()); 358 float* tempData = temp.data(); 359 360 // Sum in L and R. 361 vadd(sourceL, 1, sourceR, 1, tempData, 1, length()); 362 float scale = 0.7071; 363 vsmul(tempData, 1, &scale, tempData, 1, length()); 364 vadd(tempData, 1, destination, 1, destination, 1, length()); 365 366 // Sum in SL and SR. 367 vadd(sourceSL, 1, sourceSR, 1, tempData, 1, length()); 368 scale = 0.5; 369 vsmul(tempData, 1, &scale, tempData, 1, length()); 370 vadd(tempData, 1, destination, 1, destination, 1, length()); 371 372 // Sum in center. 373 vadd(sourceC, 1, destination, 1, destination, 1, length()); 374} 375 376void AudioBus::discreteCopyFrom(const AudioBus& sourceBus) 377{ 378 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 379 unsigned numberOfDestinationChannels = numberOfChannels(); 380 381 if (numberOfDestinationChannels < numberOfSourceChannels) { 382 // Down-mix by copying channels and dropping the remaining. 383 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) 384 channel(i)->copyFrom(sourceBus.channel(i)); 385 } else if (numberOfDestinationChannels > numberOfSourceChannels) { 386 // Up-mix by copying as many channels as we have, then zeroing remaining channels. 387 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 388 channel(i)->copyFrom(sourceBus.channel(i)); 389 for (unsigned i = numberOfSourceChannels; i < numberOfDestinationChannels; ++i) 390 channel(i)->zero(); 391 } 392} 393 394void AudioBus::discreteSumFrom(const AudioBus& sourceBus) 395{ 396 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 397 unsigned numberOfDestinationChannels = numberOfChannels(); 398 399 if (numberOfDestinationChannels < numberOfSourceChannels) { 400 // Down-mix by summing channels and dropping the remaining. 401 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) 402 channel(i)->sumFrom(sourceBus.channel(i)); 403 } else if (numberOfDestinationChannels > numberOfSourceChannels) { 404 // Up-mix by summing as many channels as we have. 405 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 406 channel(i)->sumFrom(sourceBus.channel(i)); 407 } 408} 409 410void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain) 411{ 412 if (!topologyMatches(sourceBus)) { 413 ASSERT_NOT_REACHED(); 414 zero(); 415 return; 416 } 417 418 if (sourceBus.isSilent()) { 419 zero(); 420 return; 421 } 422 423 unsigned numberOfChannels = this->numberOfChannels(); 424 ASSERT(numberOfChannels <= MaxBusChannels); 425 if (numberOfChannels > MaxBusChannels) 426 return; 427 428 // If it is copying from the same bus and no need to change gain, just return. 429 if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1) 430 return; 431 432 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 433 const float* sources[MaxBusChannels]; 434 float* destinations[MaxBusChannels]; 435 436 for (unsigned i = 0; i < numberOfChannels; ++i) { 437 sources[i] = sourceBusSafe.channel(i)->data(); 438 destinations[i] = channel(i)->mutableData(); 439 } 440 441 // We don't want to suddenly change the gain from mixing one time slice to the next, 442 // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain. 443 444 // Take master bus gain into account as well as the targetGain. 445 float totalDesiredGain = static_cast<float>(m_busGain * targetGain); 446 447 // First time, snap directly to totalDesiredGain. 448 float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain); 449 m_isFirstTime = false; 450 451 const float DezipperRate = 0.005f; 452 unsigned framesToProcess = length(); 453 454 // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. 455 // FIXME: this value may need tweaking. 456 const float epsilon = 0.001f; 457 float gainDiff = fabs(totalDesiredGain - gain); 458 459 // Number of frames to de-zipper before we are close enough to the target gain. 460 // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop. 461 unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 462 463 if (framesToDezipper) { 464 if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper) 465 m_dezipperGainValues = std::make_unique<AudioFloatArray>(framesToDezipper); 466 467 float* gainValues = m_dezipperGainValues->data(); 468 for (unsigned i = 0; i < framesToDezipper; ++i) { 469 gain += (totalDesiredGain - gain) * DezipperRate; 470 471 // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get 472 // rid of this DenormalDisabler::flushDenormalFloatToZero() call. 473 gain = DenormalDisabler::flushDenormalFloatToZero(gain); 474 *gainValues++ = gain; 475 } 476 477 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 478 vmul(sources[channelIndex], 1, m_dezipperGainValues->data(), 1, destinations[channelIndex], 1, framesToDezipper); 479 sources[channelIndex] += framesToDezipper; 480 destinations[channelIndex] += framesToDezipper; 481 } 482 } else 483 gain = totalDesiredGain; 484 485 // Apply constant gain after de-zippering has converged on target gain. 486 if (framesToDezipper < framesToProcess) { 487 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) 488 vsmul(sources[channelIndex], 1, &gain, destinations[channelIndex], 1, framesToProcess - framesToDezipper); 489 } 490 491 // Save the target gain as the starting point for next time around. 492 *lastMixGain = gain; 493} 494 495void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues) 496{ 497 // Make sure we're processing from the same type of bus. 498 // We *are* able to process from mono -> stereo 499 if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) { 500 ASSERT_NOT_REACHED(); 501 return; 502 } 503 504 if (!gainValues || numberOfGainValues > sourceBus.length()) { 505 ASSERT_NOT_REACHED(); 506 return; 507 } 508 509 if (sourceBus.length() == numberOfGainValues && sourceBus.length() == length() && sourceBus.isSilent()) { 510 zero(); 511 return; 512 } 513 514 // We handle both the 1 -> N and N -> N case here. 515 const float* source = sourceBus.channel(0)->data(); 516 for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) { 517 if (sourceBus.numberOfChannels() == numberOfChannels()) 518 source = sourceBus.channel(channelIndex)->data(); 519 float* destination = channel(channelIndex)->mutableData(); 520 vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues); 521 } 522} 523 524PassRefPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate) 525{ 526 // sourceBus's sample-rate must be known. 527 ASSERT(sourceBus && sourceBus->sampleRate()); 528 if (!sourceBus || !sourceBus->sampleRate()) 529 return 0; 530 531 double sourceSampleRate = sourceBus->sampleRate(); 532 double destinationSampleRate = newSampleRate; 533 double sampleRateRatio = sourceSampleRate / destinationSampleRate; 534 unsigned numberOfSourceChannels = sourceBus->numberOfChannels(); 535 536 if (numberOfSourceChannels == 1) 537 mixToMono = false; // already mono 538 539 if (sourceSampleRate == destinationSampleRate) { 540 // No sample-rate conversion is necessary. 541 if (mixToMono) 542 return AudioBus::createByMixingToMono(sourceBus); 543 544 // Return exact copy. 545 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length()); 546 } 547 548 if (sourceBus->isSilent()) { 549 RefPtr<AudioBus> silentBus = create(numberOfSourceChannels, sourceBus->length() / sampleRateRatio); 550 silentBus->setSampleRate(newSampleRate); 551 return silentBus; 552 } 553 554 // First, mix to mono (if necessary) then sample-rate convert. 555 const AudioBus* resamplerSourceBus; 556 RefPtr<AudioBus> mixedMonoBus; 557 if (mixToMono) { 558 mixedMonoBus = AudioBus::createByMixingToMono(sourceBus); 559 resamplerSourceBus = mixedMonoBus.get(); 560 } else { 561 // Directly resample without down-mixing. 562 resamplerSourceBus = sourceBus; 563 } 564 565 // Calculate destination length based on the sample-rates. 566 int sourceLength = resamplerSourceBus->length(); 567 int destinationLength = sourceLength / sampleRateRatio; 568 569 // Create destination bus with same number of channels. 570 unsigned numberOfDestinationChannels = resamplerSourceBus->numberOfChannels(); 571 RefPtr<AudioBus> destinationBus = create(numberOfDestinationChannels, destinationLength); 572 573 // Sample-rate convert each channel. 574 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) { 575 const float* source = resamplerSourceBus->channel(i)->data(); 576 float* destination = destinationBus->channel(i)->mutableData(); 577 578 SincResampler resampler(sampleRateRatio); 579 resampler.process(source, destination, sourceLength); 580 } 581 582 destinationBus->clearSilentFlag(); 583 destinationBus->setSampleRate(newSampleRate); 584 return destinationBus; 585} 586 587PassRefPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus) 588{ 589 if (sourceBus->isSilent()) 590 return create(1, sourceBus->length()); 591 592 switch (sourceBus->numberOfChannels()) { 593 case 1: 594 // Simply create an exact copy. 595 return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length()); 596 case 2: 597 { 598 unsigned n = sourceBus->length(); 599 RefPtr<AudioBus> destinationBus = create(1, n); 600 601 const float* sourceL = sourceBus->channel(0)->data(); 602 const float* sourceR = sourceBus->channel(1)->data(); 603 float* destination = destinationBus->channel(0)->mutableData(); 604 605 // Do the mono mixdown. 606 for (unsigned i = 0; i < n; ++i) 607 destination[i] = (sourceL[i] + sourceR[i]) / 2; 608 609 destinationBus->clearSilentFlag(); 610 destinationBus->setSampleRate(sourceBus->sampleRate()); 611 return destinationBus; 612 } 613 } 614 615 ASSERT_NOT_REACHED(); 616 return 0; 617} 618 619bool AudioBus::isSilent() const 620{ 621 for (size_t i = 0; i < m_channels.size(); ++i) { 622 if (!m_channels[i]->isSilent()) 623 return false; 624 } 625 return true; 626} 627 628void AudioBus::clearSilentFlag() 629{ 630 for (size_t i = 0; i < m_channels.size(); ++i) 631 m_channels[i]->clearSilentFlag(); 632} 633 634} // WebCore 635 636#endif // ENABLE(WEB_AUDIO) 637