blob: b341acd5a50d6e58b8dd2365af5c6d6bda724689 [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>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/audio_codecs/audio_decoder.h"
16#include "modules/audio_coding/neteq/decoder_database.h"
17#include "modules/audio_coding/neteq/dsp_helper.h"
18#include "modules/audio_coding/neteq/sync_buffer.h"
19#include "rtc_base/logging.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000020
21namespace webrtc {
22
23void ComfortNoise::Reset() {
24 first_call_ = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000025}
26
ossua73f6c92016-10-24 08:25:28 -070027int ComfortNoise::UpdateParameters(const Packet& packet) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000028 // Get comfort noise decoder.
ossua73f6c92016-10-24 08:25:28 -070029 if (decoder_database_->SetActiveCngDecoder(packet.payload_type) != kOK) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000030 return kUnknownPayloadType;
31 }
ossu97ba30e2016-04-25 07:55:58 -070032 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
33 RTC_DCHECK(cng_decoder);
ossua73f6c92016-10-24 08:25:28 -070034 cng_decoder->UpdateSid(packet.payload);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000035 return kOK;
36}
37
Yves Gerey665174f2018-06-19 15:03:05 +020038int ComfortNoise::Generate(size_t requested_length, AudioMultiVector* output) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000039 // TODO(hlundin): Change to an enumerator and skip assert.
Yves Gerey665174f2018-06-19 15:03:05 +020040 assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000041 fs_hz_ == 48000);
turaj@webrtc.org45d28402013-08-30 15:37:08 +000042 // Not adapted for multi-channel yet.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000043 if (output->Channels() != 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010044 RTC_LOG(LS_ERROR) << "No multi-channel support";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000045 return kMultiChannelNotSupported;
46 }
47
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000048 size_t number_of_samples = requested_length;
ossu97ba30e2016-04-25 07:55:58 -070049 bool new_period = false;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000050 if (first_call_) {
51 // Generate noise and overlap slightly with old data.
52 number_of_samples = requested_length + overlap_length_;
ossu97ba30e2016-04-25 07:55:58 -070053 new_period = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000054 }
55 output->AssertSize(number_of_samples);
56 // Get the decoder from the database.
ossu97ba30e2016-04-25 07:55:58 -070057 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000058 if (!cng_decoder) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010059 RTC_LOG(LS_ERROR) << "Unknwown payload type";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000060 return kUnknownPayloadType;
61 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020062
63 std::unique_ptr<int16_t[]> temp(new int16_t[number_of_samples]);
ossu97ba30e2016-04-25 07:55:58 -070064 if (!cng_decoder->Generate(
Yves Gerey665174f2018-06-19 15:03:05 +020065 rtc::ArrayView<int16_t>(temp.get(), number_of_samples), new_period)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000066 // Error returned.
67 output->Zeros(requested_length);
Mirko Bonadei675513b2017-11-09 11:09:25 +010068 RTC_LOG(LS_ERROR)
69 << "ComfortNoiseDecoder::Genererate failed to generate comfort noise";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000070 return kInternalError;
71 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020072 (*output)[0].OverwriteAt(temp.get(), number_of_samples, 0);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000073
74 if (first_call_) {
75 // Set tapering window parameters. Values are in Q15.
Yves Gerey665174f2018-06-19 15:03:05 +020076 int16_t muting_window; // Mixing factor for overlap data.
77 int16_t muting_window_increment; // Mixing factor increment (negative).
78 int16_t unmuting_window; // Mixing factor for comfort noise.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000079 int16_t unmuting_window_increment; // Mixing factor increment.
80 if (fs_hz_ == 8000) {
81 muting_window = DspHelper::kMuteFactorStart8kHz;
82 muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
83 unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
84 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
85 } else if (fs_hz_ == 16000) {
86 muting_window = DspHelper::kMuteFactorStart16kHz;
87 muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
88 unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
89 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
90 } else if (fs_hz_ == 32000) {
91 muting_window = DspHelper::kMuteFactorStart32kHz;
92 muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
93 unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
94 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
95 } else { // fs_hz_ == 48000
96 muting_window = DspHelper::kMuteFactorStart48kHz;
97 muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
98 unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
99 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
100 }
101
102 // Do overlap-add between new vector and overlap.
103 size_t start_ix = sync_buffer_->Size() - overlap_length_;
104 for (size_t i = 0; i < overlap_length_; i++) {
105 /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
106 // The expression (*output)[0][i] is the i-th element in the first
107 // channel.
108 (*sync_buffer_)[0][start_ix + i] =
109 (((*sync_buffer_)[0][start_ix + i] * muting_window) +
Yves Gerey665174f2018-06-19 15:03:05 +0200110 ((*output)[0][i] * unmuting_window) + 16384) >>
111 15;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000112 muting_window += muting_window_increment;
113 unmuting_window += unmuting_window_increment;
114 }
115 // Remove |overlap_length_| samples from the front of |output| since they
116 // were mixed into |sync_buffer_| above.
117 output->PopFront(overlap_length_);
118 }
119 first_call_ = false;
120 return kOK;
121}
122
123} // namespace webrtc