blob: cb2b74dbf2b19a0af8f153c68e74e4f7805f89c1 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/comfort_noise.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <cstdint>
15#include <memory>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000016
Yves Gerey988cc082018-10-23 12:03:01 +020017#include "api/array_view.h"
18#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
19#include "modules/audio_coding/neteq/audio_multi_vector.h"
20#include "modules/audio_coding/neteq/audio_vector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_coding/neteq/decoder_database.h"
22#include "modules/audio_coding/neteq/dsp_helper.h"
23#include "modules/audio_coding/neteq/sync_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020024#include "rtc_base/buffer.h"
25#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/logging.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000027
28namespace webrtc {
29
30void ComfortNoise::Reset() {
31 first_call_ = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000032}
33
ossua73f6c92016-10-24 08:25:28 -070034int ComfortNoise::UpdateParameters(const Packet& packet) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000035 // Get comfort noise decoder.
ossua73f6c92016-10-24 08:25:28 -070036 if (decoder_database_->SetActiveCngDecoder(packet.payload_type) != kOK) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000037 return kUnknownPayloadType;
38 }
ossu97ba30e2016-04-25 07:55:58 -070039 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
40 RTC_DCHECK(cng_decoder);
ossua73f6c92016-10-24 08:25:28 -070041 cng_decoder->UpdateSid(packet.payload);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000042 return kOK;
43}
44
Yves Gerey665174f2018-06-19 15:03:05 +020045int ComfortNoise::Generate(size_t requested_length, AudioMultiVector* output) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000046 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +020047 assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000048 fs_hz_ == 48000);
turaj@webrtc.org45d28402013-08-30 15:37:08 +000049 // Not adapted for multi-channel yet.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050 if (output->Channels() != 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010051 RTC_LOG(LS_ERROR) << "No multi-channel support";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000052 return kMultiChannelNotSupported;
53 }
54
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000055 size_t number_of_samples = requested_length;
ossu97ba30e2016-04-25 07:55:58 -070056 bool new_period = false;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000057 if (first_call_) {
58 // Generate noise and overlap slightly with old data.
59 number_of_samples = requested_length + overlap_length_;
ossu97ba30e2016-04-25 07:55:58 -070060 new_period = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000061 }
62 output->AssertSize(number_of_samples);
63 // Get the decoder from the database.
ossu97ba30e2016-04-25 07:55:58 -070064 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065 if (!cng_decoder) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010066 RTC_LOG(LS_ERROR) << "Unknwown payload type";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000067 return kUnknownPayloadType;
68 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020069
70 std::unique_ptr<int16_t[]> temp(new int16_t[number_of_samples]);
ossu97ba30e2016-04-25 07:55:58 -070071 if (!cng_decoder->Generate(
Yves Gerey665174f2018-06-19 15:03:05 +020072 rtc::ArrayView<int16_t>(temp.get(), number_of_samples), new_period)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000073 // Error returned.
74 output->Zeros(requested_length);
Mirko Bonadei675513b2017-11-09 11:09:25 +010075 RTC_LOG(LS_ERROR)
76 << "ComfortNoiseDecoder::Genererate failed to generate comfort noise";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000077 return kInternalError;
78 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020079 (*output)[0].OverwriteAt(temp.get(), number_of_samples, 0);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080
81 if (first_call_) {
82 // Set tapering window parameters. Values are in Q15.
Yves Gerey665174f2018-06-19 15:03:05 +020083 int16_t muting_window; // Mixing factor for overlap data.
84 int16_t muting_window_increment; // Mixing factor increment (negative).
85 int16_t unmuting_window; // Mixing factor for comfort noise.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000086 int16_t unmuting_window_increment; // Mixing factor increment.
87 if (fs_hz_ == 8000) {
88 muting_window = DspHelper::kMuteFactorStart8kHz;
89 muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
90 unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
91 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
92 } else if (fs_hz_ == 16000) {
93 muting_window = DspHelper::kMuteFactorStart16kHz;
94 muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
95 unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
96 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
97 } else if (fs_hz_ == 32000) {
98 muting_window = DspHelper::kMuteFactorStart32kHz;
99 muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
100 unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
101 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
102 } else { // fs_hz_ == 48000
103 muting_window = DspHelper::kMuteFactorStart48kHz;
104 muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
105 unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
106 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
107 }
108
109 // Do overlap-add between new vector and overlap.
110 size_t start_ix = sync_buffer_->Size() - overlap_length_;
111 for (size_t i = 0; i < overlap_length_; i++) {
112 /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
113 // The expression (*output)[0][i] is the i-th element in the first
114 // channel.
115 (*sync_buffer_)[0][start_ix + i] =
116 (((*sync_buffer_)[0][start_ix + i] * muting_window) +
Yves Gerey665174f2018-06-19 15:03:05 +0200117 ((*output)[0][i] * unmuting_window) + 16384) >>
118 15;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119 muting_window += muting_window_increment;
120 unmuting_window += unmuting_window_increment;
121 }
122 // Remove |overlap_length_| samples from the front of |output| since they
123 // were mixed into |sync_buffer_| above.
124 output->PopFront(overlap_length_);
125 }
126 first_call_ = false;
127 return kOK;
128}
129
130} // namespace webrtc