Line data Source code
1 : /*
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/neteq/comfort_noise.h"
12 :
13 : #include <assert.h>
14 :
15 : #include "webrtc/base/logging.h"
16 : #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
17 : #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
18 : #include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
19 : #include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
20 :
21 : namespace webrtc {
22 :
23 0 : void ComfortNoise::Reset() {
24 0 : first_call_ = true;
25 0 : }
26 :
27 0 : int ComfortNoise::UpdateParameters(const Packet& packet) {
28 : // Get comfort noise decoder.
29 0 : if (decoder_database_->SetActiveCngDecoder(packet.payload_type) != kOK) {
30 0 : return kUnknownPayloadType;
31 : }
32 0 : ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
33 0 : RTC_DCHECK(cng_decoder);
34 0 : cng_decoder->UpdateSid(packet.payload);
35 0 : return kOK;
36 : }
37 :
38 0 : int ComfortNoise::Generate(size_t requested_length,
39 : AudioMultiVector* output) {
40 : // TODO(hlundin): Change to an enumerator and skip assert.
41 0 : assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
42 : fs_hz_ == 48000);
43 : // Not adapted for multi-channel yet.
44 0 : if (output->Channels() != 1) {
45 0 : LOG(LS_ERROR) << "No multi-channel support";
46 0 : return kMultiChannelNotSupported;
47 : }
48 :
49 0 : size_t number_of_samples = requested_length;
50 0 : bool new_period = false;
51 0 : if (first_call_) {
52 : // Generate noise and overlap slightly with old data.
53 0 : number_of_samples = requested_length + overlap_length_;
54 0 : new_period = true;
55 : }
56 0 : output->AssertSize(number_of_samples);
57 : // Get the decoder from the database.
58 0 : ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
59 0 : if (!cng_decoder) {
60 0 : LOG(LS_ERROR) << "Unknwown payload type";
61 0 : return kUnknownPayloadType;
62 : }
63 :
64 0 : std::unique_ptr<int16_t[]> temp(new int16_t[number_of_samples]);
65 0 : if (!cng_decoder->Generate(
66 : rtc::ArrayView<int16_t>(temp.get(), number_of_samples),
67 : new_period)) {
68 : // Error returned.
69 0 : output->Zeros(requested_length);
70 0 : LOG(LS_ERROR) <<
71 0 : "ComfortNoiseDecoder::Genererate failed to generate comfort noise";
72 0 : return kInternalError;
73 : }
74 0 : (*output)[0].OverwriteAt(temp.get(), number_of_samples, 0);
75 :
76 0 : if (first_call_) {
77 : // Set tapering window parameters. Values are in Q15.
78 : int16_t muting_window; // Mixing factor for overlap data.
79 : int16_t muting_window_increment; // Mixing factor increment (negative).
80 : int16_t unmuting_window; // Mixing factor for comfort noise.
81 : int16_t unmuting_window_increment; // Mixing factor increment.
82 0 : if (fs_hz_ == 8000) {
83 0 : muting_window = DspHelper::kMuteFactorStart8kHz;
84 0 : muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
85 0 : unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
86 0 : unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
87 0 : } else if (fs_hz_ == 16000) {
88 0 : muting_window = DspHelper::kMuteFactorStart16kHz;
89 0 : muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
90 0 : unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
91 0 : unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
92 0 : } else if (fs_hz_ == 32000) {
93 0 : muting_window = DspHelper::kMuteFactorStart32kHz;
94 0 : muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
95 0 : unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
96 0 : unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
97 : } else { // fs_hz_ == 48000
98 0 : muting_window = DspHelper::kMuteFactorStart48kHz;
99 0 : muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
100 0 : unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
101 0 : unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
102 : }
103 :
104 : // Do overlap-add between new vector and overlap.
105 0 : size_t start_ix = sync_buffer_->Size() - overlap_length_;
106 0 : for (size_t i = 0; i < overlap_length_; i++) {
107 : /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
108 : // The expression (*output)[0][i] is the i-th element in the first
109 : // channel.
110 0 : (*sync_buffer_)[0][start_ix + i] =
111 0 : (((*sync_buffer_)[0][start_ix + i] * muting_window) +
112 0 : ((*output)[0][i] * unmuting_window) + 16384) >> 15;
113 0 : muting_window += muting_window_increment;
114 0 : unmuting_window += unmuting_window_increment;
115 : }
116 : // Remove |overlap_length_| samples from the front of |output| since they
117 : // were mixed into |sync_buffer_| above.
118 0 : output->PopFront(overlap_length_);
119 : }
120 0 : first_call_ = false;
121 0 : return kOK;
122 : }
123 :
124 : } // namespace webrtc
|