blob: 8482e8dd1226e4b014fba0275968a9650201821d [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
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000011#include "webrtc/modules/audio_coding/neteq/comfort_noise.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000012
13#include <assert.h>
14
kwiberg087bd342017-02-10 08:15:44 -080015#include "webrtc/api/audio_codecs/audio_decoder.h"
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000016#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
17#include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
henrik.lundin@webrtc.org9c55f0f2014-06-09 08:10:28 +000018#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/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
38int ComfortNoise::Generate(size_t requested_length,
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44 +000039 AudioMultiVector* output) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000040 // TODO(hlundin): Change to an enumerator and skip assert.
41 assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
42 fs_hz_ == 48000);
turaj@webrtc.org45d28402013-08-30 15:37:08 +000043 // Not adapted for multi-channel yet.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000044 if (output->Channels() != 1) {
Henrik Lundind67a2192015-08-03 12:54:37 +020045 LOG(LS_ERROR) << "No multi-channel support";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000046 return kMultiChannelNotSupported;
47 }
48
turaj@webrtc.org362a55e2013-09-20 16:25:28 +000049 size_t number_of_samples = requested_length;
ossu97ba30e2016-04-25 07:55:58 -070050 bool new_period = false;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000051 if (first_call_) {
52 // Generate noise and overlap slightly with old data.
53 number_of_samples = requested_length + overlap_length_;
ossu97ba30e2016-04-25 07:55:58 -070054 new_period = true;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000055 }
56 output->AssertSize(number_of_samples);
57 // Get the decoder from the database.
ossu97ba30e2016-04-25 07:55:58 -070058 ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000059 if (!cng_decoder) {
Henrik Lundind67a2192015-08-03 12:54:37 +020060 LOG(LS_ERROR) << "Unknwown payload type";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000061 return kUnknownPayloadType;
62 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020063
64 std::unique_ptr<int16_t[]> temp(new int16_t[number_of_samples]);
ossu97ba30e2016-04-25 07:55:58 -070065 if (!cng_decoder->Generate(
minyue-webrtc79553cb2016-05-10 19:55:56 +020066 rtc::ArrayView<int16_t>(temp.get(), number_of_samples),
ossu97ba30e2016-04-25 07:55:58 -070067 new_period)) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000068 // Error returned.
69 output->Zeros(requested_length);
ossu97ba30e2016-04-25 07:55:58 -070070 LOG(LS_ERROR) <<
71 "ComfortNoiseDecoder::Genererate failed to generate comfort noise";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000072 return kInternalError;
73 }
minyue-webrtc79553cb2016-05-10 19:55:56 +020074 (*output)[0].OverwriteAt(temp.get(), number_of_samples, 0);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075
76 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 if (fs_hz_ == 8000) {
83 muting_window = DspHelper::kMuteFactorStart8kHz;
84 muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
85 unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
86 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
87 } else if (fs_hz_ == 16000) {
88 muting_window = DspHelper::kMuteFactorStart16kHz;
89 muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
90 unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
91 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
92 } else if (fs_hz_ == 32000) {
93 muting_window = DspHelper::kMuteFactorStart32kHz;
94 muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
95 unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
96 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
97 } else { // fs_hz_ == 48000
98 muting_window = DspHelper::kMuteFactorStart48kHz;
99 muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
100 unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
101 unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
102 }
103
104 // Do overlap-add between new vector and overlap.
105 size_t start_ix = sync_buffer_->Size() - overlap_length_;
106 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 (*sync_buffer_)[0][start_ix + i] =
111 (((*sync_buffer_)[0][start_ix + i] * muting_window) +
112 ((*output)[0][i] * unmuting_window) + 16384) >> 15;
113 muting_window += muting_window_increment;
114 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 output->PopFront(overlap_length_);
119 }
120 first_call_ = false;
121 return kOK;
122}
123
124} // namespace webrtc