diff options
Diffstat (limited to 'chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc')
-rw-r--r-- | chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc b/chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc new file mode 100644 index 00000000000..31bb40c9275 --- /dev/null +++ b/chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc @@ -0,0 +1,135 @@ +/* + * 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 "webrtc/modules/audio_coding/neteq/comfort_noise.h" + +#include <assert.h> + +#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" +#include "webrtc/modules/audio_coding/neteq/decoder_database.h" +#include "webrtc/modules/audio_coding/neteq/dsp_helper.h" +#include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h" +#include "webrtc/modules/audio_coding/neteq/sync_buffer.h" + +namespace webrtc { + +void ComfortNoise::Reset() { + first_call_ = true; + internal_error_code_ = 0; +} + +int ComfortNoise::UpdateParameters(Packet* packet) { + assert(packet); // Existence is verified by caller. + // Get comfort noise decoder. + AudioDecoder* cng_decoder = decoder_database_->GetDecoder( + packet->header.payloadType); + if (!cng_decoder) { + delete [] packet->payload; + delete packet; + return kUnknownPayloadType; + } + decoder_database_->SetActiveCngDecoder(packet->header.payloadType); + CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state()); + int16_t ret = WebRtcCng_UpdateSid(cng_inst, + packet->payload, + packet->payload_length); + delete [] packet->payload; + delete packet; + if (ret < 0) { + internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst); + return kInternalError; + } + return kOK; +} + +int ComfortNoise::Generate(size_t requested_length, + AudioMultiVector* output) { + // TODO(hlundin): Change to an enumerator and skip assert. + assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 || + fs_hz_ == 48000); + // Not adapted for multi-channel yet. + if (output->Channels() != 1) { + return kMultiChannelNotSupported; + } + + size_t number_of_samples = requested_length; + int16_t new_period = 0; + if (first_call_) { + // Generate noise and overlap slightly with old data. + number_of_samples = requested_length + overlap_length_; + new_period = 1; + } + output->AssertSize(number_of_samples); + // Get the decoder from the database. + AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder(); + if (!cng_decoder) { + return kUnknownPayloadType; + } + CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state()); + // The expression &(*output)[0][0] is a pointer to the first element in + // the first channel. + if (WebRtcCng_Generate(cng_inst, &(*output)[0][0], + static_cast<int16_t>(number_of_samples), + new_period) < 0) { + // Error returned. + output->Zeros(requested_length); + internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst); + return kInternalError; + } + + 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 |