mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-27 02:07:42 +00:00
136 lines
5.3 KiB
C++
136 lines
5.3 KiB
C++
|
/*
|
||
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#include "webrtc/modules/audio_coding/neteq/comfort_noise.h"
|
||
|
|
||
|
#include <assert.h>
|
||
|
|
||
|
#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
|
||
|
#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
|
||
|
#include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
|
||
|
#include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
|
||
|
#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
void ComfortNoise::Reset() {
|
||
|
first_call_ = true;
|
||
|
internal_error_code_ = 0;
|
||
|
}
|
||
|
|
||
|
int ComfortNoise::UpdateParameters(Packet* packet) {
|
||
|
assert(packet); // Existence is verified by caller.
|
||
|
// Get comfort noise decoder.
|
||
|
AudioDecoder* cng_decoder = decoder_database_->GetDecoder(
|
||
|
packet->header.payloadType);
|
||
|
if (!cng_decoder) {
|
||
|
delete [] packet->payload;
|
||
|
delete packet;
|
||
|
return kUnknownPayloadType;
|
||
|
}
|
||
|
decoder_database_->SetActiveCngDecoder(packet->header.payloadType);
|
||
|
CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
|
||
|
int16_t ret = WebRtcCng_UpdateSid(cng_inst,
|
||
|
packet->payload,
|
||
|
packet->payload_length);
|
||
|
delete [] packet->payload;
|
||
|
delete packet;
|
||
|
if (ret < 0) {
|
||
|
internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
|
||
|
return kInternalError;
|
||
|
}
|
||
|
return kOK;
|
||
|
}
|
||
|
|
||
|
int ComfortNoise::Generate(size_t requested_length,
|
||
|
AudioMultiVector* output) {
|
||
|
// TODO(hlundin): Change to an enumerator and skip assert.
|
||
|
assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
|
||
|
fs_hz_ == 48000);
|
||
|
// Not adapted for multi-channel yet.
|
||
|
if (output->Channels() != 1) {
|
||
|
return kMultiChannelNotSupported;
|
||
|
}
|
||
|
|
||
|
size_t number_of_samples = requested_length;
|
||
|
int16_t new_period = 0;
|
||
|
if (first_call_) {
|
||
|
// Generate noise and overlap slightly with old data.
|
||
|
number_of_samples = requested_length + overlap_length_;
|
||
|
new_period = 1;
|
||
|
}
|
||
|
output->AssertSize(number_of_samples);
|
||
|
// Get the decoder from the database.
|
||
|
AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
|
||
|
if (!cng_decoder) {
|
||
|
return kUnknownPayloadType;
|
||
|
}
|
||
|
CNG_dec_inst* cng_inst = static_cast<CNG_dec_inst*>(cng_decoder->state());
|
||
|
// The expression &(*output)[0][0] is a pointer to the first element in
|
||
|
// the first channel.
|
||
|
if (WebRtcCng_Generate(cng_inst, &(*output)[0][0],
|
||
|
static_cast<int16_t>(number_of_samples),
|
||
|
new_period) < 0) {
|
||
|
// Error returned.
|
||
|
output->Zeros(requested_length);
|
||
|
internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
|
||
|
return kInternalError;
|
||
|
}
|
||
|
|
||
|
if (first_call_) {
|
||
|
// Set tapering window parameters. Values are in Q15.
|
||
|
int16_t muting_window; // Mixing factor for overlap data.
|
||
|
int16_t muting_window_increment; // Mixing factor increment (negative).
|
||
|
int16_t unmuting_window; // Mixing factor for comfort noise.
|
||
|
int16_t unmuting_window_increment; // Mixing factor increment.
|
||
|
if (fs_hz_ == 8000) {
|
||
|
muting_window = DspHelper::kMuteFactorStart8kHz;
|
||
|
muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
|
||
|
unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
|
||
|
unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
|
||
|
} else if (fs_hz_ == 16000) {
|
||
|
muting_window = DspHelper::kMuteFactorStart16kHz;
|
||
|
muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
|
||
|
unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
|
||
|
unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
|
||
|
} else if (fs_hz_ == 32000) {
|
||
|
muting_window = DspHelper::kMuteFactorStart32kHz;
|
||
|
muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
|
||
|
unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
|
||
|
unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
|
||
|
} else { // fs_hz_ == 48000
|
||
|
muting_window = DspHelper::kMuteFactorStart48kHz;
|
||
|
muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
|
||
|
unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
|
||
|
unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
|
||
|
}
|
||
|
|
||
|
// Do overlap-add between new vector and overlap.
|
||
|
size_t start_ix = sync_buffer_->Size() - overlap_length_;
|
||
|
for (size_t i = 0; i < overlap_length_; i++) {
|
||
|
/* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
|
||
|
// The expression (*output)[0][i] is the i-th element in the first
|
||
|
// channel.
|
||
|
(*sync_buffer_)[0][start_ix + i] =
|
||
|
(((*sync_buffer_)[0][start_ix + i] * muting_window) +
|
||
|
((*output)[0][i] * unmuting_window) + 16384) >> 15;
|
||
|
muting_window += muting_window_increment;
|
||
|
unmuting_window += unmuting_window_increment;
|
||
|
}
|
||
|
// Remove |overlap_length_| samples from the front of |output| since they
|
||
|
// were mixed into |sync_buffer_| above.
|
||
|
output->PopFront(overlap_length_);
|
||
|
}
|
||
|
first_call_ = false;
|
||
|
return kOK;
|
||
|
}
|
||
|
|
||
|
} // namespace webrtc
|