blob: a55f13082fe91719534aee9da4a3457c2c1d9226 [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/modules/audio_coding/neteq4/comfort_noise.h"
12
13#include <assert.h>
14
15#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
16#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
17#include "webrtc/modules/audio_coding/neteq4/dsp_helper.h"
18#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
19#include "webrtc/modules/audio_coding/neteq4/sync_buffer.h"
20
21namespace webrtc {
22
23void ComfortNoise::Reset() {
24 first_call_ = true;
25 internal_error_code_ = 0;
26}
27
28int ComfortNoise::UpdateParameters(Packet* packet) {
29 assert(packet); // Existence is verified by caller.
30 // Get comfort noise decoder.
31 AudioDecoder* cng_decoder = decoder_database_->GetDecoder(
32 packet->header.payloadType);
33 if (!cng_decoder) {
34 delete [] packet->payload;
35 delete packet;
36 return kUnknownPayloadType;
37 }
38 decoder_database_->SetActiveCngDecoder(packet->header.payloadType);
39 CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
40 int16_t ret = WebRtcCng_UpdateSid(cng_inst,
41 packet->payload,
42 packet->payload_length);
43 delete [] packet->payload;
44 delete packet;
45 if (ret < 0) {
46 internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
47 return kInternalError;
48 }
49 return kOK;
50}
51
52int ComfortNoise::Generate(size_t requested_length,
53 AudioMultiVector<int16_t>* output) {
54 // TODO(hlundin): Change to an enumerator and skip assert.
55 assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
56 fs_hz_ == 48000);
turaj@webrtc.org1aa09382013-08-30 15:37:08 +000057 // Not adapted for multi-channel yet.
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000058 if (output->Channels() != 1) {
59 return kMultiChannelNotSupported;
60 }
61
62 int16_t number_of_samples = requested_length;
63 int16_t new_period = 0;
64 if (first_call_) {
65 // Generate noise and overlap slightly with old data.
66 number_of_samples = requested_length + overlap_length_;
67 new_period = 1;
68 }
69 output->AssertSize(number_of_samples);
70 // Get the decoder from the database.
71 AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
72 if (!cng_decoder) {
73 return kUnknownPayloadType;
74 }
75 CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
76 // The expression &(*output)[0][0] is a pointer to the first element in
77 // the first channel.
78 if (WebRtcCng_Generate(cng_inst, &(*output)[0][0], number_of_samples,
79 new_period) < 0) {
80 // Error returned.
81 output->Zeros(requested_length);
82 internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
83 return kInternalError;
84 }
85
86 if (first_call_) {
87 // Set tapering window parameters. Values are in Q15.
88 int16_t muting_window; // Mixing factor for overlap data.
89 int16_t muting_window_increment; // Mixing factor increment (negative).
90 int16_t unmuting_window; // Mixing factor for comfort noise.
91 int16_t unmuting_window_increment; // Mixing factor increment.
92 if (fs_hz_ == 8000) {
93 muting_window = DspHelper::kMuteFactorStart8kHz;
94 muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
95 unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
96 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
97 } else if (fs_hz_ == 16000) {
98 muting_window = DspHelper::kMuteFactorStart16kHz;
99 muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
100 unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
101 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
102 } else if (fs_hz_ == 32000) {
103 muting_window = DspHelper::kMuteFactorStart32kHz;
104 muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
105 unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
106 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
107 } else { // fs_hz_ == 48000
108 muting_window = DspHelper::kMuteFactorStart48kHz;
109 muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
110 unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
111 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
112 }
113
114 // Do overlap-add between new vector and overlap.
115 size_t start_ix = sync_buffer_->Size() - overlap_length_;
116 for (size_t i = 0; i < overlap_length_; i++) {
117 /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
118 // The expression (*output)[0][i] is the i-th element in the first
119 // channel.
120 (*sync_buffer_)[0][start_ix + i] =
121 (((*sync_buffer_)[0][start_ix + i] * muting_window) +
122 ((*output)[0][i] * unmuting_window) + 16384) >> 15;
123 muting_window += muting_window_increment;
124 unmuting_window += unmuting_window_increment;
125 }
126 // Remove |overlap_length_| samples from the front of |output| since they
127 // were mixed into |sync_buffer_| above.
128 output->PopFront(overlap_length_);
129 }
130 first_call_ = false;
131 return kOK;
132}
133
134} // namespace webrtc