+// TODO(turajs): This can be moved to BackgroundNoise class.
+void Expand::GenerateBackgroundNoise(int16_t* random_vector,
+ size_t channel,
+ int16_t mute_slope,
+ bool too_many_expands,
+ size_t num_noise_samples,
+ int16_t* buffer) {
+ static const int kNoiseLpcOrder = BackgroundNoise::kMaxLpcOrder;
+ int16_t scaled_random_vector[kMaxSampleRate / 8000 * 125];
+ assert(kMaxSampleRate / 8000 * 125 >= (int)num_noise_samples);
+ int16_t* noise_samples = &buffer[kNoiseLpcOrder];
+ if (background_noise_->initialized()) {
+ // Use background noise parameters.
+ memcpy(noise_samples - kNoiseLpcOrder,
+ background_noise_->FilterState(channel),
+ sizeof(int16_t) * kNoiseLpcOrder);
+
+ int dc_offset = 0;
+ if (background_noise_->ScaleShift(channel) > 1) {
+ dc_offset = 1 << (background_noise_->ScaleShift(channel) - 1);
+ }
+
+ // Scale random vector to correct energy level.
+ WebRtcSpl_AffineTransformVector(
+ scaled_random_vector, random_vector,
+ background_noise_->Scale(channel), dc_offset,
+ background_noise_->ScaleShift(channel),
+ static_cast<int>(num_noise_samples));
+
+ WebRtcSpl_FilterARFastQ12(scaled_random_vector, noise_samples,
+ background_noise_->Filter(channel),
+ kNoiseLpcOrder + 1,
+ static_cast<int>(num_noise_samples));
+
+ background_noise_->SetFilterState(
+ channel,
+ &(noise_samples[num_noise_samples - kNoiseLpcOrder]),
+ kNoiseLpcOrder);
+
+ // Unmute the background noise.
+ int16_t bgn_mute_factor = background_noise_->MuteFactor(channel);
+ NetEqBackgroundNoiseMode bgn_mode = background_noise_->mode();
+ if (bgn_mode == kBgnFade && too_many_expands && bgn_mute_factor > 0) {
+ // Fade BGN to zero.
+ // Calculate muting slope, approximately -2^18 / fs_hz.
+ int16_t mute_slope;
+ if (fs_hz_ == 8000) {
+ mute_slope = -32;
+ } else if (fs_hz_ == 16000) {
+ mute_slope = -16;
+ } else if (fs_hz_ == 32000) {
+ mute_slope = -8;
+ } else {
+ mute_slope = -5;
+ }
+ // Use UnmuteSignal function with negative slope.
+ // |bgn_mute_factor| is in Q14. |mute_slope| is in Q20.
+ DspHelper::UnmuteSignal(noise_samples,
+ num_noise_samples,
+ &bgn_mute_factor,
+ mute_slope,
+ noise_samples);
+ } else if (bgn_mute_factor < 16384) {
+ // If mode is kBgnOff, or if kBgnFade has started fading,
+ // Use regular |mute_slope|.
+ if (!stop_muting_ && bgn_mode != kBgnOff &&
+ !(bgn_mode == kBgnFade && too_many_expands)) {
+ DspHelper::UnmuteSignal(noise_samples,
+ static_cast<int>(num_noise_samples),
+ &bgn_mute_factor,
+ mute_slope,
+ noise_samples);
+ } else {
+ // kBgnOn and stop muting, or
+ // kBgnOff (mute factor is always 0), or
+ // kBgnFade has reached 0.
+ WebRtcSpl_AffineTransformVector(noise_samples, noise_samples,
+ bgn_mute_factor, 8192, 14,
+ static_cast<int>(num_noise_samples));
+ }
+ }
+ // Update mute_factor in BackgroundNoise class.
+ background_noise_->SetMuteFactor(channel, bgn_mute_factor);
+ } else {
+ // BGN parameters have not been initialized; use zero noise.
+ memset(noise_samples, 0, sizeof(int16_t) * num_noise_samples);
+ }
+}
+
+void Expand::GenerateRandomVector(int seed_increment,
+ size_t length,
+ int16_t* random_vector) {
+ // TODO(turajs): According to hlundin The loop should not be needed. Should be
+ // just as good to generate all of the vector in one call.
+ size_t samples_generated = 0;
+ const size_t kMaxRandSamples = RandomVector::kRandomTableSize;
+ while(samples_generated < length) {
+ size_t rand_length = std::min(length - samples_generated, kMaxRandSamples);
+ random_vector_->IncreaseSeedIncrement(seed_increment);
+ random_vector_->Generate(rand_length, &random_vector[samples_generated]);
+ samples_generated += rand_length;
+ }
+}