| 541 | } |
| 542 | |
| 543 | void AudioBus::copyWithGainFrom(const AudioBus & sourceBus, float * lastMixGain, float targetGain) |
| 544 | { |
| 545 | if (!topologyMatches(sourceBus)) |
| 546 | { |
| 547 | // happens if a connection has been made, but the channel count has yet to be propagated. |
| 548 | zero(); |
| 549 | return; |
| 550 | } |
| 551 | |
| 552 | if (sourceBus.isSilent()) |
| 553 | { |
| 554 | zero(); |
| 555 | return; |
| 556 | } |
| 557 | |
| 558 | const int numberOfChannels = static_cast<int>(m_channels.size()); |
| 559 | ASSERT(numberOfChannels <= MaxBusChannels); |
| 560 | if (numberOfChannels > MaxBusChannels) return; |
| 561 | |
| 562 | // If it is copying from the same bus and no need to change gain, just return. |
| 563 | if ((this == &sourceBus) && (*lastMixGain == targetGain) && (targetGain == 1)) |
| 564 | { |
| 565 | return; |
| 566 | } |
| 567 | |
| 568 | AudioBus & sourceBusSafe = const_cast<AudioBus &>(sourceBus); |
| 569 | const float * sources[MaxBusChannels]; |
| 570 | float * destinations[MaxBusChannels]; |
| 571 | |
| 572 | for (int i = 0; i < numberOfChannels; ++i) |
| 573 | { |
| 574 | sources[i] = sourceBusSafe.channel(i)->data(); |
| 575 | destinations[i] = channel(i)->mutableData(); |
| 576 | } |
| 577 | |
| 578 | // We don't want to suddenly change the gain from mixing one time slice to the next, |
| 579 | // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain. |
| 580 | |
| 581 | // Take master bus gain into account as well as the targetGain. |
| 582 | float totalDesiredGain = static_cast<float>(m_busGain * targetGain); |
| 583 | |
| 584 | // First time, snap directly to totalDesiredGain. |
| 585 | float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain); |
| 586 | m_isFirstTime = false; |
| 587 | |
| 588 | const float DezipperRate = 0.005f; |
| 589 | int framesToProcess = length(); |
| 590 | |
| 591 | // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. |
| 592 | // FIXME: this value may need tweaking. |
| 593 | const float epsilon = 0.001f; |
| 594 | float gainDiff = fabs(totalDesiredGain - gain); |
| 595 | |
| 596 | // Number of frames to de-zipper before we are close enough to the target gain. |
| 597 | // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop. |
| 598 | int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; |
| 599 | |
| 600 | if (framesToDezipper) |