/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/audio_coding/neteq/comfort_noise.h" #include #include #include "api/array_view.h" #include "modules/audio_coding/codecs/cng/webrtc_cng.h" #include "modules/audio_coding/neteq/audio_multi_vector.h" #include "modules/audio_coding/neteq/audio_vector.h" #include "modules/audio_coding/neteq/decoder_database.h" #include "modules/audio_coding/neteq/dsp_helper.h" #include "modules/audio_coding/neteq/sync_buffer.h" #include "rtc_base/buffer.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" namespace webrtc { void ComfortNoise::Reset() { first_call_ = true; } int ComfortNoise::UpdateParameters(const Packet& packet) { // Get comfort noise decoder. if (decoder_database_->SetActiveCngDecoder(packet.payload_type) != kOK) { return kUnknownPayloadType; } ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder(); RTC_DCHECK(cng_decoder); cng_decoder->UpdateSid(packet.payload); return kOK; } int ComfortNoise::Generate(size_t requested_length, AudioMultiVector* output) { // TODO(hlundin): Change to an enumerator and skip assert. RTC_DCHECK(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 || fs_hz_ == 48000); // Not adapted for multi-channel yet. if (output->Channels() != 1) { RTC_LOG(LS_ERROR) << "No multi-channel support"; return kMultiChannelNotSupported; } size_t number_of_samples = requested_length; bool new_period = false; if (first_call_) { // Generate noise and overlap slightly with old data. number_of_samples = requested_length + overlap_length_; new_period = true; } output->AssertSize(number_of_samples); // Get the decoder from the database. ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder(); if (!cng_decoder) { RTC_LOG(LS_ERROR) << "Unknwown payload type"; return kUnknownPayloadType; } std::unique_ptr temp(new int16_t[number_of_samples]); if (!cng_decoder->Generate( rtc::ArrayView(temp.get(), number_of_samples), new_period)) { // Error returned. output->Zeros(requested_length); RTC_LOG(LS_ERROR) << "ComfortNoiseDecoder::Genererate failed to generate comfort noise"; return kInternalError; } (*output)[0].OverwriteAt(temp.get(), number_of_samples, 0); if (first_call_) { // Set tapering window parameters. Values are in Q15. int16_t muting_window; // Mixing factor for overlap data. int16_t muting_window_increment; // Mixing factor increment (negative). int16_t unmuting_window; // Mixing factor for comfort noise. int16_t unmuting_window_increment; // Mixing factor increment. if (fs_hz_ == 8000) { muting_window = DspHelper::kMuteFactorStart8kHz; muting_window_increment = DspHelper::kMuteFactorIncrement8kHz; unmuting_window = DspHelper::kUnmuteFactorStart8kHz; unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz; } else if (fs_hz_ == 16000) { muting_window = DspHelper::kMuteFactorStart16kHz; muting_window_increment = DspHelper::kMuteFactorIncrement16kHz; unmuting_window = DspHelper::kUnmuteFactorStart16kHz; unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz; } else if (fs_hz_ == 32000) { muting_window = DspHelper::kMuteFactorStart32kHz; muting_window_increment = DspHelper::kMuteFactorIncrement32kHz; unmuting_window = DspHelper::kUnmuteFactorStart32kHz; unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz; } else { // fs_hz_ == 48000 muting_window = DspHelper::kMuteFactorStart48kHz; muting_window_increment = DspHelper::kMuteFactorIncrement48kHz; unmuting_window = DspHelper::kUnmuteFactorStart48kHz; unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz; } // Do overlap-add between new vector and overlap. size_t start_ix = sync_buffer_->Size() - overlap_length_; for (size_t i = 0; i < overlap_length_; i++) { /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */ // The expression (*output)[0][i] is the i-th element in the first // channel. (*sync_buffer_)[0][start_ix + i] = (((*sync_buffer_)[0][start_ix + i] * muting_window) + ((*output)[0][i] * unmuting_window) + 16384) >> 15; muting_window += muting_window_increment; unmuting_window += unmuting_window_increment; } // Remove `overlap_length_` samples from the front of `output` since they // were mixed into `sync_buffer_` above. output->PopFront(overlap_length_); } first_call_ = false; return kOK; } } // namespace webrtc