summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/webrtc/modules/audio_coding/neteq/comfort_noise.cc
diff options
context:
space:
mode:
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.cc135
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