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