Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file is for backwards compatibility only! Use
|
||||
// webrtc/api/audio_codecs/audio_decoder.h instead!
|
||||
// TODO(kwiberg): Remove it.
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
|
||||
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file is for backwards compatibility only! Use
|
||||
// webrtc/api/audio_codecs/audio_encoder.h instead!
|
||||
// TODO(ossu): Remove it.
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
|
||||
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (c) 2016 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 "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreateUnknownDecoder) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("rey", 8000, 1), absl::nullopt));
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreatePcmu) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// PCMu supports 8 kHz, and any number of channels.
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 0), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 1), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 2), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 3), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 16000, 1), absl::nullopt));
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreatePcma) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// PCMa supports 8 kHz, and any number of channels.
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 0), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 1), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 2), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 3), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("pcma", 16000, 1), absl::nullopt));
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreateIlbc) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// iLBC supports 8 kHz, 1 channel.
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 0), absl::nullopt));
|
||||
#ifdef WEBRTC_CODEC_ILBC
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 1), absl::nullopt));
|
||||
#endif
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 2), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 16000, 1), absl::nullopt));
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreateL16) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// L16 supports any clock rate and any number of channels up to 24.
|
||||
const int clockrates[] = {8000, 16000, 32000, 48000};
|
||||
const int num_channels[] = {1, 2, 3, 24};
|
||||
for (int clockrate : clockrates) {
|
||||
EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("l16", clockrate, 0),
|
||||
absl::nullopt));
|
||||
for (int channels : num_channels) {
|
||||
EXPECT_TRUE(adf->MakeAudioDecoder(
|
||||
SdpAudioFormat("l16", clockrate, channels), absl::nullopt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that using more channels than the maximum does not work
|
||||
TEST(AudioDecoderFactoryTest, MaxNrOfChannels) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
std::vector<std::string> codecs = {
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
"opus",
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_ILBC
|
||||
"ilbc",
|
||||
#endif
|
||||
"pcmu", "pcma", "l16", "G722", "G711",
|
||||
};
|
||||
|
||||
for (auto codec : codecs) {
|
||||
EXPECT_FALSE(adf->MakeAudioDecoder(
|
||||
SdpAudioFormat(codec, 32000, AudioDecoder::kMaxNumberOfChannels + 1),
|
||||
absl::nullopt));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreateG722) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// g722 supports 8 kHz, 1-2 channels.
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 0), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt));
|
||||
EXPECT_TRUE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 2), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 3), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 16000, 1), absl::nullopt));
|
||||
EXPECT_FALSE(
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 32000, 1), absl::nullopt));
|
||||
|
||||
// g722 actually uses a 16 kHz sample rate instead of the nominal 8 kHz.
|
||||
std::unique_ptr<AudioDecoder> dec =
|
||||
adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt);
|
||||
EXPECT_EQ(16000, dec->SampleRateHz());
|
||||
}
|
||||
|
||||
TEST(AudioDecoderFactoryTest, CreateOpus) {
|
||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||
CreateBuiltinAudioDecoderFactory();
|
||||
ASSERT_TRUE(adf);
|
||||
// Opus supports 48 kHz, 2 channels, and wants a "stereo" parameter whose
|
||||
// value is either "0" or "1".
|
||||
for (int hz : {8000, 16000, 32000, 48000}) {
|
||||
for (int channels : {0, 1, 2, 3}) {
|
||||
for (std::string stereo : {"XX", "0", "1", "2"}) {
|
||||
CodecParameterMap params;
|
||||
if (stereo != "XX") {
|
||||
params["stereo"] = stereo;
|
||||
}
|
||||
const bool good = (hz == 48000 && channels == 2 &&
|
||||
(stereo == "XX" || stereo == "0" || stereo == "1"));
|
||||
EXPECT_EQ(good,
|
||||
static_cast<bool>(adf->MakeAudioDecoder(
|
||||
SdpAudioFormat("opus", hz, channels, std::move(params)),
|
||||
absl::nullopt)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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 "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioEncoderFactoryTest
|
||||
: public ::testing::TestWithParam<rtc::scoped_refptr<AudioEncoderFactory>> {
|
||||
};
|
||||
|
||||
TEST_P(AudioEncoderFactoryTest, SupportsAtLeastOneFormat) {
|
||||
auto factory = GetParam();
|
||||
auto supported_encoders = factory->GetSupportedEncoders();
|
||||
EXPECT_FALSE(supported_encoders.empty());
|
||||
}
|
||||
|
||||
TEST_P(AudioEncoderFactoryTest, CanQueryAllSupportedFormats) {
|
||||
auto factory = GetParam();
|
||||
auto supported_encoders = factory->GetSupportedEncoders();
|
||||
for (const auto& spec : supported_encoders) {
|
||||
auto info = factory->QueryAudioEncoder(spec.format);
|
||||
EXPECT_TRUE(info);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AudioEncoderFactoryTest, CanConstructAllSupportedEncoders) {
|
||||
auto factory = GetParam();
|
||||
auto supported_encoders = factory->GetSupportedEncoders();
|
||||
for (const auto& spec : supported_encoders) {
|
||||
auto info = factory->QueryAudioEncoder(spec.format);
|
||||
auto encoder = factory->MakeAudioEncoder(127, spec.format, absl::nullopt);
|
||||
EXPECT_TRUE(encoder);
|
||||
EXPECT_EQ(encoder->SampleRateHz(), info->sample_rate_hz);
|
||||
EXPECT_EQ(encoder->NumChannels(), info->num_channels);
|
||||
EXPECT_EQ(encoder->RtpTimestampRateHz(), spec.format.clockrate_hz);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AudioEncoderFactoryTest, CanRunAllSupportedEncoders) {
|
||||
constexpr int kTestPayloadType = 127;
|
||||
auto factory = GetParam();
|
||||
auto supported_encoders = factory->GetSupportedEncoders();
|
||||
for (const auto& spec : supported_encoders) {
|
||||
auto encoder =
|
||||
factory->MakeAudioEncoder(kTestPayloadType, spec.format, absl::nullopt);
|
||||
EXPECT_TRUE(encoder);
|
||||
encoder->Reset();
|
||||
const int num_samples = rtc::checked_cast<int>(
|
||||
encoder->SampleRateHz() * encoder->NumChannels() / 100);
|
||||
rtc::Buffer out;
|
||||
rtc::BufferT<int16_t> audio;
|
||||
audio.SetData(num_samples, [](rtc::ArrayView<int16_t> audio) {
|
||||
for (size_t i = 0; i != audio.size(); ++i) {
|
||||
// Just put some numbers in there, ensure they're within range.
|
||||
audio[i] =
|
||||
static_cast<int16_t>(i & std::numeric_limits<int16_t>::max());
|
||||
}
|
||||
return audio.size();
|
||||
});
|
||||
// This is here to stop the test going forever with a broken encoder.
|
||||
constexpr int kMaxEncodeCalls = 100;
|
||||
int blocks = 0;
|
||||
for (; blocks < kMaxEncodeCalls; ++blocks) {
|
||||
AudioEncoder::EncodedInfo info = encoder->Encode(
|
||||
blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
|
||||
EXPECT_EQ(info.encoded_bytes, out.size());
|
||||
if (info.encoded_bytes > 0) {
|
||||
EXPECT_EQ(0u, info.encoded_timestamp);
|
||||
EXPECT_EQ(kTestPayloadType, info.payload_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_LT(blocks, kMaxEncodeCalls);
|
||||
const unsigned int next_timestamp =
|
||||
blocks * encoder->RtpTimestampRateHz() / 100;
|
||||
out.Clear();
|
||||
for (; blocks < kMaxEncodeCalls; ++blocks) {
|
||||
AudioEncoder::EncodedInfo info = encoder->Encode(
|
||||
blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
|
||||
EXPECT_EQ(info.encoded_bytes, out.size());
|
||||
if (info.encoded_bytes > 0) {
|
||||
EXPECT_EQ(next_timestamp, info.encoded_timestamp);
|
||||
EXPECT_EQ(kTestPayloadType, info.payload_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_LT(blocks, kMaxEncodeCalls);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest,
|
||||
AudioEncoderFactoryTest,
|
||||
::testing::Values(CreateBuiltinAudioEncoderFactory()));
|
||||
|
||||
TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
|
||||
using ::testing::ElementsAreArray;
|
||||
// Check that we claim to support the formats we expect from build flags, and
|
||||
// we've ordered them correctly.
|
||||
auto factory = CreateBuiltinAudioEncoderFactory();
|
||||
auto specs = factory->GetSupportedEncoders();
|
||||
|
||||
const std::vector<SdpAudioFormat> supported_formats = [&specs] {
|
||||
std::vector<SdpAudioFormat> formats;
|
||||
formats.reserve(specs.size());
|
||||
for (const auto& spec : specs) {
|
||||
formats.push_back(spec.format);
|
||||
}
|
||||
return formats;
|
||||
}();
|
||||
|
||||
const std::vector<SdpAudioFormat> expected_formats = {
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
{"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}},
|
||||
#endif
|
||||
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
|
||||
{"isac", 16000, 1},
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_ISAC
|
||||
{"isac", 32000, 1},
|
||||
#endif
|
||||
{"G722", 8000, 1},
|
||||
#ifdef WEBRTC_CODEC_ILBC
|
||||
{"ilbc", 8000, 1},
|
||||
#endif
|
||||
{"pcmu", 8000, 1},
|
||||
{"pcma", 8000, 1}
|
||||
};
|
||||
|
||||
ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
|
||||
}
|
||||
|
||||
// Tests that using more channels than the maximum does not work.
|
||||
TEST(BuiltinAudioEncoderFactoryTest, MaxNrOfChannels) {
|
||||
rtc::scoped_refptr<AudioEncoderFactory> aef =
|
||||
CreateBuiltinAudioEncoderFactory();
|
||||
std::vector<std::string> codecs = {
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
"opus",
|
||||
#endif
|
||||
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
|
||||
"isac",
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_ILBC
|
||||
"ilbc",
|
||||
#endif
|
||||
"pcmu",
|
||||
"pcma",
|
||||
"l16",
|
||||
"G722",
|
||||
"G711",
|
||||
};
|
||||
|
||||
for (auto codec : codecs) {
|
||||
EXPECT_FALSE(aef->MakeAudioEncoder(
|
||||
/*payload_type=*/111,
|
||||
/*format=*/
|
||||
SdpAudioFormat(codec, 32000, AudioEncoder::kMaxNumberOfChannels + 1),
|
||||
/*codec_pair_id=*/absl::nullopt));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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 "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kMaxFrameSizeMs = 60;
|
||||
|
||||
class AudioEncoderCng final : public AudioEncoder {
|
||||
public:
|
||||
explicit AudioEncoderCng(AudioEncoderCngConfig&& config);
|
||||
~AudioEncoderCng() override;
|
||||
|
||||
// Not copyable or moveable.
|
||||
AudioEncoderCng(const AudioEncoderCng&) = delete;
|
||||
AudioEncoderCng(AudioEncoderCng&&) = delete;
|
||||
AudioEncoderCng& operator=(const AudioEncoderCng&) = delete;
|
||||
AudioEncoderCng& operator=(AudioEncoderCng&&) = delete;
|
||||
|
||||
int SampleRateHz() const override;
|
||||
size_t NumChannels() const override;
|
||||
int RtpTimestampRateHz() const override;
|
||||
size_t Num10MsFramesInNextPacket() const override;
|
||||
size_t Max10MsFramesInAPacket() const override;
|
||||
int GetTargetBitrate() const override;
|
||||
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) override;
|
||||
void Reset() override;
|
||||
bool SetFec(bool enable) override;
|
||||
bool SetDtx(bool enable) override;
|
||||
bool SetApplication(Application application) override;
|
||||
void SetMaxPlaybackRate(int frequency_hz) override;
|
||||
rtc::ArrayView<std::unique_ptr<AudioEncoder>> ReclaimContainedEncoders()
|
||||
override;
|
||||
void OnReceivedUplinkPacketLossFraction(
|
||||
float uplink_packet_loss_fraction) override;
|
||||
void OnReceivedUplinkBandwidth(
|
||||
int target_audio_bitrate_bps,
|
||||
absl::optional<int64_t> bwe_period_ms) override;
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||
const override;
|
||||
|
||||
private:
|
||||
EncodedInfo EncodePassive(size_t frames_to_encode, rtc::Buffer* encoded);
|
||||
EncodedInfo EncodeActive(size_t frames_to_encode, rtc::Buffer* encoded);
|
||||
size_t SamplesPer10msFrame() const;
|
||||
|
||||
std::unique_ptr<AudioEncoder> speech_encoder_;
|
||||
const int cng_payload_type_;
|
||||
const int num_cng_coefficients_;
|
||||
const int sid_frame_interval_ms_;
|
||||
std::vector<int16_t> speech_buffer_;
|
||||
std::vector<uint32_t> rtp_timestamps_;
|
||||
bool last_frame_active_;
|
||||
std::unique_ptr<Vad> vad_;
|
||||
std::unique_ptr<ComfortNoiseEncoder> cng_encoder_;
|
||||
};
|
||||
|
||||
AudioEncoderCng::AudioEncoderCng(AudioEncoderCngConfig&& config)
|
||||
: speech_encoder_((static_cast<void>([&] {
|
||||
RTC_CHECK(config.IsOk()) << "Invalid configuration.";
|
||||
}()),
|
||||
std::move(config.speech_encoder))),
|
||||
cng_payload_type_(config.payload_type),
|
||||
num_cng_coefficients_(config.num_cng_coefficients),
|
||||
sid_frame_interval_ms_(config.sid_frame_interval_ms),
|
||||
last_frame_active_(true),
|
||||
vad_(config.vad ? std::unique_ptr<Vad>(config.vad)
|
||||
: CreateVad(config.vad_mode)),
|
||||
cng_encoder_(new ComfortNoiseEncoder(SampleRateHz(),
|
||||
sid_frame_interval_ms_,
|
||||
num_cng_coefficients_)) {}
|
||||
|
||||
AudioEncoderCng::~AudioEncoderCng() = default;
|
||||
|
||||
int AudioEncoderCng::SampleRateHz() const {
|
||||
return speech_encoder_->SampleRateHz();
|
||||
}
|
||||
|
||||
size_t AudioEncoderCng::NumChannels() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AudioEncoderCng::RtpTimestampRateHz() const {
|
||||
return speech_encoder_->RtpTimestampRateHz();
|
||||
}
|
||||
|
||||
size_t AudioEncoderCng::Num10MsFramesInNextPacket() const {
|
||||
return speech_encoder_->Num10MsFramesInNextPacket();
|
||||
}
|
||||
|
||||
size_t AudioEncoderCng::Max10MsFramesInAPacket() const {
|
||||
return speech_encoder_->Max10MsFramesInAPacket();
|
||||
}
|
||||
|
||||
int AudioEncoderCng::GetTargetBitrate() const {
|
||||
return speech_encoder_->GetTargetBitrate();
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderCng::EncodeImpl(
|
||||
uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) {
|
||||
const size_t samples_per_10ms_frame = SamplesPer10msFrame();
|
||||
RTC_CHECK_EQ(speech_buffer_.size(),
|
||||
rtp_timestamps_.size() * samples_per_10ms_frame);
|
||||
rtp_timestamps_.push_back(rtp_timestamp);
|
||||
RTC_DCHECK_EQ(samples_per_10ms_frame, audio.size());
|
||||
speech_buffer_.insert(speech_buffer_.end(), audio.cbegin(), audio.cend());
|
||||
const size_t frames_to_encode = speech_encoder_->Num10MsFramesInNextPacket();
|
||||
if (rtp_timestamps_.size() < frames_to_encode) {
|
||||
return EncodedInfo();
|
||||
}
|
||||
RTC_CHECK_LE(frames_to_encode * 10, kMaxFrameSizeMs)
|
||||
<< "Frame size cannot be larger than " << kMaxFrameSizeMs
|
||||
<< " ms when using VAD/CNG.";
|
||||
|
||||
// Group several 10 ms blocks per VAD call. Call VAD once or twice using the
|
||||
// following split sizes:
|
||||
// 10 ms = 10 + 0 ms; 20 ms = 20 + 0 ms; 30 ms = 30 + 0 ms;
|
||||
// 40 ms = 20 + 20 ms; 50 ms = 30 + 20 ms; 60 ms = 30 + 30 ms.
|
||||
size_t blocks_in_first_vad_call =
|
||||
(frames_to_encode > 3 ? 3 : frames_to_encode);
|
||||
if (frames_to_encode == 4)
|
||||
blocks_in_first_vad_call = 2;
|
||||
RTC_CHECK_GE(frames_to_encode, blocks_in_first_vad_call);
|
||||
const size_t blocks_in_second_vad_call =
|
||||
frames_to_encode - blocks_in_first_vad_call;
|
||||
|
||||
// Check if all of the buffer is passive speech. Start with checking the first
|
||||
// block.
|
||||
Vad::Activity activity = vad_->VoiceActivity(
|
||||
&speech_buffer_[0], samples_per_10ms_frame * blocks_in_first_vad_call,
|
||||
SampleRateHz());
|
||||
if (activity == Vad::kPassive && blocks_in_second_vad_call > 0) {
|
||||
// Only check the second block if the first was passive.
|
||||
activity = vad_->VoiceActivity(
|
||||
&speech_buffer_[samples_per_10ms_frame * blocks_in_first_vad_call],
|
||||
samples_per_10ms_frame * blocks_in_second_vad_call, SampleRateHz());
|
||||
}
|
||||
|
||||
EncodedInfo info;
|
||||
switch (activity) {
|
||||
case Vad::kPassive: {
|
||||
info = EncodePassive(frames_to_encode, encoded);
|
||||
last_frame_active_ = false;
|
||||
break;
|
||||
}
|
||||
case Vad::kActive: {
|
||||
info = EncodeActive(frames_to_encode, encoded);
|
||||
last_frame_active_ = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
speech_buffer_.erase(
|
||||
speech_buffer_.begin(),
|
||||
speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame);
|
||||
rtp_timestamps_.erase(rtp_timestamps_.begin(),
|
||||
rtp_timestamps_.begin() + frames_to_encode);
|
||||
return info;
|
||||
}
|
||||
|
||||
void AudioEncoderCng::Reset() {
|
||||
speech_encoder_->Reset();
|
||||
speech_buffer_.clear();
|
||||
rtp_timestamps_.clear();
|
||||
last_frame_active_ = true;
|
||||
vad_->Reset();
|
||||
cng_encoder_.reset(new ComfortNoiseEncoder(
|
||||
SampleRateHz(), sid_frame_interval_ms_, num_cng_coefficients_));
|
||||
}
|
||||
|
||||
bool AudioEncoderCng::SetFec(bool enable) {
|
||||
return speech_encoder_->SetFec(enable);
|
||||
}
|
||||
|
||||
bool AudioEncoderCng::SetDtx(bool enable) {
|
||||
return speech_encoder_->SetDtx(enable);
|
||||
}
|
||||
|
||||
bool AudioEncoderCng::SetApplication(Application application) {
|
||||
return speech_encoder_->SetApplication(application);
|
||||
}
|
||||
|
||||
void AudioEncoderCng::SetMaxPlaybackRate(int frequency_hz) {
|
||||
speech_encoder_->SetMaxPlaybackRate(frequency_hz);
|
||||
}
|
||||
|
||||
rtc::ArrayView<std::unique_ptr<AudioEncoder>>
|
||||
AudioEncoderCng::ReclaimContainedEncoders() {
|
||||
return rtc::ArrayView<std::unique_ptr<AudioEncoder>>(&speech_encoder_, 1);
|
||||
}
|
||||
|
||||
void AudioEncoderCng::OnReceivedUplinkPacketLossFraction(
|
||||
float uplink_packet_loss_fraction) {
|
||||
speech_encoder_->OnReceivedUplinkPacketLossFraction(
|
||||
uplink_packet_loss_fraction);
|
||||
}
|
||||
|
||||
void AudioEncoderCng::OnReceivedUplinkBandwidth(
|
||||
int target_audio_bitrate_bps,
|
||||
absl::optional<int64_t> bwe_period_ms) {
|
||||
speech_encoder_->OnReceivedUplinkBandwidth(target_audio_bitrate_bps,
|
||||
bwe_period_ms);
|
||||
}
|
||||
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>>
|
||||
AudioEncoderCng::GetFrameLengthRange() const {
|
||||
return speech_encoder_->GetFrameLengthRange();
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive(
|
||||
size_t frames_to_encode,
|
||||
rtc::Buffer* encoded) {
|
||||
bool force_sid = last_frame_active_;
|
||||
bool output_produced = false;
|
||||
const size_t samples_per_10ms_frame = SamplesPer10msFrame();
|
||||
AudioEncoder::EncodedInfo info;
|
||||
|
||||
for (size_t i = 0; i < frames_to_encode; ++i) {
|
||||
// It's important not to pass &info.encoded_bytes directly to
|
||||
// WebRtcCng_Encode(), since later loop iterations may return zero in
|
||||
// that value, in which case we don't want to overwrite any value from
|
||||
// an earlier iteration.
|
||||
size_t encoded_bytes_tmp =
|
||||
cng_encoder_->Encode(rtc::ArrayView<const int16_t>(
|
||||
&speech_buffer_[i * samples_per_10ms_frame],
|
||||
samples_per_10ms_frame),
|
||||
force_sid, encoded);
|
||||
|
||||
if (encoded_bytes_tmp > 0) {
|
||||
RTC_CHECK(!output_produced);
|
||||
info.encoded_bytes = encoded_bytes_tmp;
|
||||
output_produced = true;
|
||||
force_sid = false;
|
||||
}
|
||||
}
|
||||
|
||||
info.encoded_timestamp = rtp_timestamps_.front();
|
||||
info.payload_type = cng_payload_type_;
|
||||
info.send_even_if_empty = true;
|
||||
info.speech = false;
|
||||
return info;
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive(size_t frames_to_encode,
|
||||
rtc::Buffer* encoded) {
|
||||
const size_t samples_per_10ms_frame = SamplesPer10msFrame();
|
||||
AudioEncoder::EncodedInfo info;
|
||||
for (size_t i = 0; i < frames_to_encode; ++i) {
|
||||
info =
|
||||
speech_encoder_->Encode(rtp_timestamps_.front(),
|
||||
rtc::ArrayView<const int16_t>(
|
||||
&speech_buffer_[i * samples_per_10ms_frame],
|
||||
samples_per_10ms_frame),
|
||||
encoded);
|
||||
if (i + 1 == frames_to_encode) {
|
||||
RTC_CHECK_GT(info.encoded_bytes, 0) << "Encoder didn't deliver data.";
|
||||
} else {
|
||||
RTC_CHECK_EQ(info.encoded_bytes, 0)
|
||||
<< "Encoder delivered data too early.";
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
size_t AudioEncoderCng::SamplesPer10msFrame() const {
|
||||
return rtc::CheckedDivExact(10 * SampleRateHz(), 1000);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioEncoderCngConfig::AudioEncoderCngConfig() = default;
|
||||
AudioEncoderCngConfig::AudioEncoderCngConfig(AudioEncoderCngConfig&&) = default;
|
||||
AudioEncoderCngConfig::~AudioEncoderCngConfig() = default;
|
||||
|
||||
bool AudioEncoderCngConfig::IsOk() const {
|
||||
if (num_channels != 1)
|
||||
return false;
|
||||
if (!speech_encoder)
|
||||
return false;
|
||||
if (num_channels != speech_encoder->NumChannels())
|
||||
return false;
|
||||
if (sid_frame_interval_ms <
|
||||
static_cast<int>(speech_encoder->Max10MsFramesInAPacket() * 10))
|
||||
return false;
|
||||
if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER ||
|
||||
num_cng_coefficients <= 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> CreateComfortNoiseEncoder(
|
||||
AudioEncoderCngConfig&& config) {
|
||||
return std::make_unique<AudioEncoderCng>(std::move(config));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "common_audio/vad/include/vad.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct AudioEncoderCngConfig {
|
||||
// Moveable, not copyable.
|
||||
AudioEncoderCngConfig();
|
||||
AudioEncoderCngConfig(AudioEncoderCngConfig&&);
|
||||
~AudioEncoderCngConfig();
|
||||
|
||||
bool IsOk() const;
|
||||
|
||||
size_t num_channels = 1;
|
||||
int payload_type = 13;
|
||||
std::unique_ptr<AudioEncoder> speech_encoder;
|
||||
Vad::Aggressiveness vad_mode = Vad::kVadNormal;
|
||||
int sid_frame_interval_ms = 100;
|
||||
int num_cng_coefficients = 8;
|
||||
// The Vad pointer is mainly for testing. If a NULL pointer is passed, the
|
||||
// AudioEncoderCng creates (and destroys) a Vad object internally. If an
|
||||
// object is passed, the AudioEncoderCng assumes ownership of the Vad
|
||||
// object.
|
||||
Vad* vad = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<AudioEncoder> CreateComfortNoiseEncoder(
|
||||
AudioEncoderCngConfig&& config);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_CNG_AUDIO_ENCODER_CNG_H_
|
||||
|
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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 "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "common_audio/vad/mock/mock_vad.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/mock_audio_encoder.h"
|
||||
#include "test/testsupport/rtc_expect_death.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Eq;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::Not;
|
||||
using ::testing::Optional;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo.
|
||||
static const size_t kMockReturnEncodedBytes = 17;
|
||||
static const int kCngPayloadType = 18;
|
||||
} // namespace
|
||||
|
||||
class AudioEncoderCngTest : public ::testing::Test {
|
||||
protected:
|
||||
AudioEncoderCngTest()
|
||||
: mock_encoder_owner_(new MockAudioEncoder),
|
||||
mock_encoder_(mock_encoder_owner_.get()),
|
||||
mock_vad_(new MockVad),
|
||||
timestamp_(4711),
|
||||
num_audio_samples_10ms_(0),
|
||||
sample_rate_hz_(8000) {
|
||||
memset(audio_, 0, kMaxNumSamples * 2);
|
||||
EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
|
||||
}
|
||||
|
||||
AudioEncoderCngTest(const AudioEncoderCngTest&) = delete;
|
||||
AudioEncoderCngTest& operator=(const AudioEncoderCngTest&) = delete;
|
||||
|
||||
void TearDown() override {
|
||||
EXPECT_CALL(*mock_vad_, Die()).Times(1);
|
||||
cng_.reset();
|
||||
}
|
||||
|
||||
AudioEncoderCngConfig MakeCngConfig() {
|
||||
AudioEncoderCngConfig config;
|
||||
config.speech_encoder = std::move(mock_encoder_owner_);
|
||||
EXPECT_TRUE(config.speech_encoder);
|
||||
|
||||
// Let the AudioEncoderCng object use a MockVad instead of its internally
|
||||
// created Vad object.
|
||||
config.vad = mock_vad_;
|
||||
config.payload_type = kCngPayloadType;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void CreateCng(AudioEncoderCngConfig&& config) {
|
||||
num_audio_samples_10ms_ = static_cast<size_t>(10 * sample_rate_hz_ / 1000);
|
||||
ASSERT_LE(num_audio_samples_10ms_, kMaxNumSamples);
|
||||
if (config.speech_encoder) {
|
||||
EXPECT_CALL(*mock_encoder_, SampleRateHz())
|
||||
.WillRepeatedly(Return(sample_rate_hz_));
|
||||
// Max10MsFramesInAPacket() is just used to verify that the SID frame
|
||||
// period is not too small. The return value does not matter that much,
|
||||
// as long as it is smaller than 10.
|
||||
EXPECT_CALL(*mock_encoder_, Max10MsFramesInAPacket())
|
||||
.WillOnce(Return(1u));
|
||||
}
|
||||
cng_ = CreateComfortNoiseEncoder(std::move(config));
|
||||
}
|
||||
|
||||
void Encode() {
|
||||
ASSERT_TRUE(cng_) << "Must call CreateCng() first.";
|
||||
encoded_info_ = cng_->Encode(
|
||||
timestamp_,
|
||||
rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms_),
|
||||
&encoded_);
|
||||
timestamp_ += static_cast<uint32_t>(num_audio_samples_10ms_);
|
||||
}
|
||||
|
||||
// Expect `num_calls` calls to the encoder, all successful. The last call
|
||||
// claims to have encoded `kMockReturnEncodedBytes` bytes, and all the
|
||||
// preceding ones 0 bytes.
|
||||
void ExpectEncodeCalls(size_t num_calls) {
|
||||
InSequence s;
|
||||
AudioEncoder::EncodedInfo info;
|
||||
for (size_t j = 0; j < num_calls - 1; ++j) {
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).WillOnce(Return(info));
|
||||
}
|
||||
info.encoded_bytes = kMockReturnEncodedBytes;
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
|
||||
.WillOnce(
|
||||
Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
|
||||
}
|
||||
|
||||
// Verifies that the cng_ object waits until it has collected
|
||||
// `blocks_per_frame` blocks of audio, and then dispatches all of them to
|
||||
// the underlying codec (speech or cng).
|
||||
void CheckBlockGrouping(size_t blocks_per_frame, bool active_speech) {
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(blocks_per_frame));
|
||||
auto config = MakeCngConfig();
|
||||
const int num_cng_coefficients = config.num_cng_coefficients;
|
||||
CreateCng(std::move(config));
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillRepeatedly(Return(active_speech ? Vad::kActive : Vad::kPassive));
|
||||
|
||||
// Don't expect any calls to the encoder yet.
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
|
||||
for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
|
||||
Encode();
|
||||
EXPECT_EQ(0u, encoded_info_.encoded_bytes);
|
||||
}
|
||||
if (active_speech)
|
||||
ExpectEncodeCalls(blocks_per_frame);
|
||||
Encode();
|
||||
if (active_speech) {
|
||||
EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
|
||||
} else {
|
||||
EXPECT_EQ(static_cast<size_t>(num_cng_coefficients + 1),
|
||||
encoded_info_.encoded_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies that the audio is partitioned into larger blocks before calling
|
||||
// the VAD.
|
||||
void CheckVadInputSize(int input_frame_size_ms,
|
||||
int expected_first_block_size_ms,
|
||||
int expected_second_block_size_ms) {
|
||||
const size_t blocks_per_frame =
|
||||
static_cast<size_t>(input_frame_size_ms / 10);
|
||||
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(blocks_per_frame));
|
||||
|
||||
// Expect nothing to happen before the last block is sent to cng_.
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _)).Times(0);
|
||||
for (size_t i = 0; i < blocks_per_frame - 1; ++i) {
|
||||
Encode();
|
||||
}
|
||||
|
||||
// Let the VAD decision be passive, since an active decision may lead to
|
||||
// early termination of the decision loop.
|
||||
InSequence s;
|
||||
EXPECT_CALL(
|
||||
*mock_vad_,
|
||||
VoiceActivity(_, expected_first_block_size_ms * sample_rate_hz_ / 1000,
|
||||
sample_rate_hz_))
|
||||
.WillOnce(Return(Vad::kPassive));
|
||||
if (expected_second_block_size_ms > 0) {
|
||||
EXPECT_CALL(*mock_vad_,
|
||||
VoiceActivity(
|
||||
_, expected_second_block_size_ms * sample_rate_hz_ / 1000,
|
||||
sample_rate_hz_))
|
||||
.WillOnce(Return(Vad::kPassive));
|
||||
}
|
||||
|
||||
// With this call to Encode(), `mock_vad_` should be called according to the
|
||||
// above expectations.
|
||||
Encode();
|
||||
}
|
||||
|
||||
// Tests a frame with both active and passive speech. Returns true if the
|
||||
// decision was active speech, false if it was passive.
|
||||
bool CheckMixedActivePassive(Vad::Activity first_type,
|
||||
Vad::Activity second_type) {
|
||||
// Set the speech encoder frame size to 60 ms, to ensure that the VAD will
|
||||
// be called twice.
|
||||
const size_t blocks_per_frame = 6;
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(blocks_per_frame));
|
||||
InSequence s;
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(first_type));
|
||||
if (first_type == Vad::kPassive) {
|
||||
// Expect a second call to the VAD only if the first frame was passive.
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(second_type));
|
||||
}
|
||||
encoded_info_.payload_type = 0;
|
||||
for (size_t i = 0; i < blocks_per_frame; ++i) {
|
||||
Encode();
|
||||
}
|
||||
return encoded_info_.payload_type != kCngPayloadType;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> cng_;
|
||||
std::unique_ptr<MockAudioEncoder> mock_encoder_owner_;
|
||||
MockAudioEncoder* mock_encoder_;
|
||||
MockVad* mock_vad_; // Ownership is transferred to `cng_`.
|
||||
uint32_t timestamp_;
|
||||
int16_t audio_[kMaxNumSamples];
|
||||
size_t num_audio_samples_10ms_;
|
||||
rtc::Buffer encoded_;
|
||||
AudioEncoder::EncodedInfo encoded_info_;
|
||||
int sample_rate_hz_;
|
||||
};
|
||||
|
||||
TEST_F(AudioEncoderCngTest, CreateAndDestroy) {
|
||||
CreateCng(MakeCngConfig());
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillOnce(Return(17U));
|
||||
EXPECT_EQ(17U, cng_->Num10MsFramesInNextPacket());
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, CheckTargetAudioBitratePropagation) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_,
|
||||
OnReceivedUplinkBandwidth(4711, absl::optional<int64_t>()));
|
||||
cng_->OnReceivedUplinkBandwidth(4711, absl::nullopt);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, CheckPacketLossFractionPropagation) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_, OnReceivedUplinkPacketLossFraction(0.5));
|
||||
cng_->OnReceivedUplinkPacketLossFraction(0.5);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, CheckGetFrameLengthRangePropagation) {
|
||||
CreateCng(MakeCngConfig());
|
||||
auto expected_range =
|
||||
std::make_pair(TimeDelta::Millis(20), TimeDelta::Millis(20));
|
||||
EXPECT_CALL(*mock_encoder_, GetFrameLengthRange())
|
||||
.WillRepeatedly(Return(absl::make_optional(expected_range)));
|
||||
EXPECT_THAT(cng_->GetFrameLengthRange(), Optional(Eq(expected_range)));
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCallsVad) {
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(1U));
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(Vad::kPassive));
|
||||
Encode();
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects1BlockPassiveSpeech) {
|
||||
CheckBlockGrouping(1, false);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksPassiveSpeech) {
|
||||
CheckBlockGrouping(2, false);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksPassiveSpeech) {
|
||||
CheckBlockGrouping(3, false);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects1BlockActiveSpeech) {
|
||||
CheckBlockGrouping(1, true);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects2BlocksActiveSpeech) {
|
||||
CheckBlockGrouping(2, true);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodeCollects3BlocksActiveSpeech) {
|
||||
CheckBlockGrouping(3, true);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngTest, EncodePassive) {
|
||||
const size_t kBlocksPerFrame = 3;
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(kBlocksPerFrame));
|
||||
auto config = MakeCngConfig();
|
||||
const auto sid_frame_interval_ms = config.sid_frame_interval_ms;
|
||||
const auto num_cng_coefficients = config.num_cng_coefficients;
|
||||
CreateCng(std::move(config));
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillRepeatedly(Return(Vad::kPassive));
|
||||
// Expect no calls at all to the speech encoder mock.
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
|
||||
uint32_t expected_timestamp = timestamp_;
|
||||
for (size_t i = 0; i < 100; ++i) {
|
||||
Encode();
|
||||
// Check if it was time to call the cng encoder. This is done once every
|
||||
// `kBlocksPerFrame` calls.
|
||||
if ((i + 1) % kBlocksPerFrame == 0) {
|
||||
// Now check if a SID interval has elapsed.
|
||||
if ((i % (sid_frame_interval_ms / 10)) < kBlocksPerFrame) {
|
||||
// If so, verify that we got a CNG encoding.
|
||||
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
|
||||
EXPECT_FALSE(encoded_info_.speech);
|
||||
EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
|
||||
encoded_info_.encoded_bytes);
|
||||
EXPECT_EQ(expected_timestamp, encoded_info_.encoded_timestamp);
|
||||
}
|
||||
expected_timestamp += rtc::checked_cast<uint32_t>(
|
||||
kBlocksPerFrame * num_audio_samples_10ms_);
|
||||
} else {
|
||||
// Otherwise, expect no output.
|
||||
EXPECT_EQ(0u, encoded_info_.encoded_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies that the correct action is taken for frames with both active and
|
||||
// passive speech.
|
||||
TEST_F(AudioEncoderCngTest, MixedActivePassive) {
|
||||
CreateCng(MakeCngConfig());
|
||||
|
||||
// All of the frame is active speech.
|
||||
ExpectEncodeCalls(6);
|
||||
EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kActive));
|
||||
EXPECT_TRUE(encoded_info_.speech);
|
||||
|
||||
// First half of the frame is active speech.
|
||||
ExpectEncodeCalls(6);
|
||||
EXPECT_TRUE(CheckMixedActivePassive(Vad::kActive, Vad::kPassive));
|
||||
EXPECT_TRUE(encoded_info_.speech);
|
||||
|
||||
// Second half of the frame is active speech.
|
||||
ExpectEncodeCalls(6);
|
||||
EXPECT_TRUE(CheckMixedActivePassive(Vad::kPassive, Vad::kActive));
|
||||
EXPECT_TRUE(encoded_info_.speech);
|
||||
|
||||
// All of the frame is passive speech. Expect no calls to `mock_encoder_`.
|
||||
EXPECT_FALSE(CheckMixedActivePassive(Vad::kPassive, Vad::kPassive));
|
||||
EXPECT_FALSE(encoded_info_.speech);
|
||||
}
|
||||
|
||||
// These tests verify that the audio is partitioned into larger blocks before
|
||||
// calling the VAD.
|
||||
// The parameters for CheckVadInputSize are:
|
||||
// CheckVadInputSize(frame_size, expected_first_block_size,
|
||||
// expected_second_block_size);
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize10Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(10, 10, 0);
|
||||
}
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize20Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(20, 20, 0);
|
||||
}
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize30Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(30, 30, 0);
|
||||
}
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize40Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(40, 20, 20);
|
||||
}
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize50Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(50, 30, 20);
|
||||
}
|
||||
TEST_F(AudioEncoderCngTest, VadInputSize60Ms) {
|
||||
CreateCng(MakeCngConfig());
|
||||
CheckVadInputSize(60, 30, 30);
|
||||
}
|
||||
|
||||
// Verifies that the correct payload type is set when CNG is encoded.
|
||||
TEST_F(AudioEncoderCngTest, VerifyCngPayloadType) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket()).WillOnce(Return(1U));
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(Vad::kPassive));
|
||||
encoded_info_.payload_type = 0;
|
||||
Encode();
|
||||
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
|
||||
}
|
||||
|
||||
// Verifies that a SID frame is encoded immediately as the signal changes from
|
||||
// active speech to passive.
|
||||
TEST_F(AudioEncoderCngTest, VerifySidFrameAfterSpeech) {
|
||||
auto config = MakeCngConfig();
|
||||
const auto num_cng_coefficients = config.num_cng_coefficients;
|
||||
CreateCng(std::move(config));
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(1U));
|
||||
// Start with encoding noise.
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(Vad::kPassive));
|
||||
Encode();
|
||||
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
|
||||
EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
|
||||
encoded_info_.encoded_bytes);
|
||||
// Encode again, and make sure we got no frame at all (since the SID frame
|
||||
// period is 100 ms by default).
|
||||
Encode();
|
||||
EXPECT_EQ(0u, encoded_info_.encoded_bytes);
|
||||
|
||||
// Now encode active speech.
|
||||
encoded_info_.payload_type = 0;
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(Vad::kActive));
|
||||
EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _))
|
||||
.WillOnce(
|
||||
Invoke(MockAudioEncoder::FakeEncoding(kMockReturnEncodedBytes)));
|
||||
Encode();
|
||||
EXPECT_EQ(kMockReturnEncodedBytes, encoded_info_.encoded_bytes);
|
||||
|
||||
// Go back to noise again, and verify that a SID frame is emitted.
|
||||
EXPECT_CALL(*mock_vad_, VoiceActivity(_, _, _))
|
||||
.WillOnce(Return(Vad::kPassive));
|
||||
Encode();
|
||||
EXPECT_EQ(kCngPayloadType, encoded_info_.payload_type);
|
||||
EXPECT_EQ(static_cast<size_t>(num_cng_coefficients) + 1,
|
||||
encoded_info_.encoded_bytes);
|
||||
}
|
||||
|
||||
// Resetting the CNG should reset both the VAD and the encoder.
|
||||
TEST_F(AudioEncoderCngTest, Reset) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_, Reset()).Times(1);
|
||||
EXPECT_CALL(*mock_vad_, Reset()).Times(1);
|
||||
cng_->Reset();
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
|
||||
// This test fixture tests various error conditions that makes the
|
||||
// AudioEncoderCng die via CHECKs.
|
||||
class AudioEncoderCngDeathTest : public AudioEncoderCngTest {
|
||||
protected:
|
||||
AudioEncoderCngDeathTest() : AudioEncoderCngTest() {
|
||||
EXPECT_CALL(*mock_vad_, Die()).Times(1);
|
||||
delete mock_vad_;
|
||||
mock_vad_ = nullptr;
|
||||
}
|
||||
|
||||
// Override AudioEncoderCngTest::TearDown, since that one expects a call to
|
||||
// the destructor of `mock_vad_`. In this case, that object is already
|
||||
// deleted.
|
||||
void TearDown() override { cng_.reset(); }
|
||||
|
||||
AudioEncoderCngConfig MakeCngConfig() {
|
||||
// Don't provide a Vad mock object, since it would leak when the test dies.
|
||||
auto config = AudioEncoderCngTest::MakeCngConfig();
|
||||
config.vad = nullptr;
|
||||
return config;
|
||||
}
|
||||
|
||||
void TryWrongNumCoefficients(int num) {
|
||||
RTC_EXPECT_DEATH(
|
||||
[&] {
|
||||
auto config = MakeCngConfig();
|
||||
config.num_cng_coefficients = num;
|
||||
CreateCng(std::move(config));
|
||||
}(),
|
||||
"Invalid configuration");
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, WrongFrameSize) {
|
||||
CreateCng(MakeCngConfig());
|
||||
num_audio_samples_10ms_ *= 2; // 20 ms frame.
|
||||
RTC_EXPECT_DEATH(Encode(), "");
|
||||
num_audio_samples_10ms_ = 0; // Zero samples.
|
||||
RTC_EXPECT_DEATH(Encode(), "");
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsA) {
|
||||
TryWrongNumCoefficients(-1);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsB) {
|
||||
TryWrongNumCoefficients(0);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, WrongNumCoefficientsC) {
|
||||
TryWrongNumCoefficients(13);
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, NullSpeechEncoder) {
|
||||
auto config = MakeCngConfig();
|
||||
config.speech_encoder = nullptr;
|
||||
RTC_EXPECT_DEATH(CreateCng(std::move(config)), "");
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, StereoEncoder) {
|
||||
EXPECT_CALL(*mock_encoder_, NumChannels()).WillRepeatedly(Return(2));
|
||||
RTC_EXPECT_DEATH(CreateCng(MakeCngConfig()), "Invalid configuration");
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, StereoConfig) {
|
||||
RTC_EXPECT_DEATH(
|
||||
[&] {
|
||||
auto config = MakeCngConfig();
|
||||
config.num_channels = 2;
|
||||
CreateCng(std::move(config));
|
||||
}(),
|
||||
"Invalid configuration");
|
||||
}
|
||||
|
||||
TEST_F(AudioEncoderCngDeathTest, EncoderFrameSizeTooLarge) {
|
||||
CreateCng(MakeCngConfig());
|
||||
EXPECT_CALL(*mock_encoder_, Num10MsFramesInNextPacket())
|
||||
.WillRepeatedly(Return(7U));
|
||||
for (int i = 0; i < 6; ++i)
|
||||
Encode();
|
||||
RTC_EXPECT_DEATH(
|
||||
Encode(), "Frame size cannot be larger than 60 ms when using VAD/CNG.");
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/testsupport/file_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum {
|
||||
kSidShortIntervalUpdate = 1,
|
||||
kSidNormalIntervalUpdate = 100,
|
||||
kSidLongIntervalUpdate = 10000
|
||||
};
|
||||
|
||||
enum : size_t {
|
||||
kCNGNumParamsLow = 0,
|
||||
kCNGNumParamsNormal = 8,
|
||||
kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
|
||||
kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
|
||||
};
|
||||
|
||||
enum { kNoSid, kForceSid };
|
||||
|
||||
class CngTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp();
|
||||
|
||||
void TestCngEncode(int sample_rate_hz, int quality);
|
||||
|
||||
int16_t speech_data_[640]; // Max size of CNG internal buffers.
|
||||
};
|
||||
|
||||
class CngDeathTest : public CngTest {};
|
||||
|
||||
void CngTest::SetUp() {
|
||||
FILE* input_file;
|
||||
const std::string file_name =
|
||||
webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
|
||||
input_file = fopen(file_name.c_str(), "rb");
|
||||
ASSERT_TRUE(input_file != NULL);
|
||||
ASSERT_EQ(640, static_cast<int32_t>(
|
||||
fread(speech_data_, sizeof(int16_t), 640, input_file)));
|
||||
fclose(input_file);
|
||||
input_file = NULL;
|
||||
}
|
||||
|
||||
void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
|
||||
const size_t num_samples_10ms = rtc::CheckedDivExact(sample_rate_hz, 100);
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
|
||||
quality);
|
||||
EXPECT_EQ(0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(
|
||||
speech_data_, num_samples_10ms),
|
||||
kNoSid, &sid_data));
|
||||
EXPECT_EQ(static_cast<size_t>(quality + 1),
|
||||
cng_encoder.Encode(
|
||||
rtc::ArrayView<const int16_t>(speech_data_, num_samples_10ms),
|
||||
kForceSid, &sid_data));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
// Create CNG encoder, init with faulty values, free CNG encoder.
|
||||
TEST_F(CngDeathTest, CngInitFail) {
|
||||
// Call with too few parameters.
|
||||
EXPECT_DEATH(
|
||||
{
|
||||
ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate, kCNGNumParamsLow);
|
||||
},
|
||||
"");
|
||||
// Call with too many parameters.
|
||||
EXPECT_DEATH(
|
||||
{
|
||||
ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsTooHigh);
|
||||
},
|
||||
"");
|
||||
}
|
||||
|
||||
// Encode Cng with too long input vector.
|
||||
TEST_F(CngDeathTest, CngEncodeTooLong) {
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
// Create encoder.
|
||||
ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
// Run encoder with too much data.
|
||||
EXPECT_DEATH(
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 641),
|
||||
kNoSid, &sid_data),
|
||||
"");
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
|
||||
TEST_F(CngTest, CngEncode8000) {
|
||||
TestCngEncode(8000, kCNGNumParamsNormal);
|
||||
}
|
||||
|
||||
TEST_F(CngTest, CngEncode16000) {
|
||||
TestCngEncode(16000, kCNGNumParamsNormal);
|
||||
}
|
||||
|
||||
TEST_F(CngTest, CngEncode32000) {
|
||||
TestCngEncode(32000, kCNGNumParamsHigh);
|
||||
}
|
||||
|
||||
TEST_F(CngTest, CngEncode48000) {
|
||||
TestCngEncode(48000, kCNGNumParamsNormal);
|
||||
}
|
||||
|
||||
TEST_F(CngTest, CngEncode64000) {
|
||||
TestCngEncode(64000, kCNGNumParamsNormal);
|
||||
}
|
||||
|
||||
// Update SID parameters, for both 9 and 16 parameters.
|
||||
TEST_F(CngTest, CngUpdateSid) {
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
// Create and initialize encoder and decoder.
|
||||
ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
ComfortNoiseDecoder cng_decoder;
|
||||
|
||||
// Run normal Encode and UpdateSid.
|
||||
EXPECT_EQ(kCNGNumParamsNormal + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kForceSid, &sid_data));
|
||||
cng_decoder.UpdateSid(sid_data);
|
||||
|
||||
// Reinit with new length.
|
||||
cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
|
||||
cng_decoder.Reset();
|
||||
|
||||
// Expect 0 because of unstable parameters after switching length.
|
||||
EXPECT_EQ(0U,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kForceSid, &sid_data));
|
||||
EXPECT_EQ(
|
||||
kCNGNumParamsHigh + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_ + 160, 160),
|
||||
kForceSid, &sid_data));
|
||||
cng_decoder.UpdateSid(
|
||||
rtc::ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
|
||||
}
|
||||
|
||||
// Update SID parameters, with wrong parameters or without calling decode.
|
||||
TEST_F(CngTest, CngUpdateSidErroneous) {
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
// Encode.
|
||||
ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
ComfortNoiseDecoder cng_decoder;
|
||||
EXPECT_EQ(kCNGNumParamsNormal + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kForceSid, &sid_data));
|
||||
|
||||
// First run with valid parameters, then with too many CNG parameters.
|
||||
// The function will operate correctly by only reading the maximum number of
|
||||
// parameters, skipping the extra.
|
||||
EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
|
||||
cng_decoder.UpdateSid(sid_data);
|
||||
|
||||
// Make sure the input buffer is large enough. Since Encode() appends data, we
|
||||
// need to set the size manually only afterwards, or the buffer will be bigger
|
||||
// than anticipated.
|
||||
sid_data.SetSize(kCNGNumParamsTooHigh + 1);
|
||||
cng_decoder.UpdateSid(sid_data);
|
||||
}
|
||||
|
||||
// Test to generate cng data, by forcing SID. Both normal and faulty condition.
|
||||
TEST_F(CngTest, CngGenerate) {
|
||||
rtc::Buffer sid_data;
|
||||
int16_t out_data[640];
|
||||
|
||||
// Create and initialize encoder and decoder.
|
||||
ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
ComfortNoiseDecoder cng_decoder;
|
||||
|
||||
// Normal Encode.
|
||||
EXPECT_EQ(kCNGNumParamsNormal + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kForceSid, &sid_data));
|
||||
|
||||
// Normal UpdateSid.
|
||||
cng_decoder.UpdateSid(sid_data);
|
||||
|
||||
// Two normal Generate, one with new_period.
|
||||
EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 1));
|
||||
EXPECT_TRUE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 640), 0));
|
||||
|
||||
// Call Genereate with too much data.
|
||||
EXPECT_FALSE(cng_decoder.Generate(rtc::ArrayView<int16_t>(out_data, 641), 0));
|
||||
}
|
||||
|
||||
// Test automatic SID.
|
||||
TEST_F(CngTest, CngAutoSid) {
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
// Create and initialize encoder and decoder.
|
||||
ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
ComfortNoiseDecoder cng_decoder;
|
||||
|
||||
// Normal Encode, 100 msec, where no SID data should be generated.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_EQ(
|
||||
0U, cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kNoSid, &sid_data));
|
||||
}
|
||||
|
||||
// We have reached 100 msec, and SID data should be generated.
|
||||
EXPECT_EQ(kCNGNumParamsNormal + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kNoSid, &sid_data));
|
||||
}
|
||||
|
||||
// Test automatic SID, with very short interval.
|
||||
TEST_F(CngTest, CngAutoSidShort) {
|
||||
rtc::Buffer sid_data;
|
||||
|
||||
// Create and initialize encoder and decoder.
|
||||
ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
|
||||
kCNGNumParamsNormal);
|
||||
ComfortNoiseDecoder cng_decoder;
|
||||
|
||||
// First call will never generate SID, unless forced to.
|
||||
EXPECT_EQ(0U,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kNoSid, &sid_data));
|
||||
|
||||
// Normal Encode, 100 msec, SID data should be generated all the time.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_EQ(
|
||||
kCNGNumParamsNormal + 1,
|
||||
cng_encoder.Encode(rtc::ArrayView<const int16_t>(speech_data_, 160),
|
||||
kNoSid, &sid_data));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* 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 "modules/audio_coding/codecs/cng/webrtc_cng.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const size_t kCngMaxOutsizeOrder = 640;
|
||||
|
||||
// TODO(ossu): Rename the left-over WebRtcCng according to style guide.
|
||||
void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a);
|
||||
|
||||
const int32_t WebRtcCng_kDbov[94] = {
|
||||
1081109975, 858756178, 682134279, 541838517, 430397633, 341876992,
|
||||
271562548, 215709799, 171344384, 136103682, 108110997, 85875618,
|
||||
68213428, 54183852, 43039763, 34187699, 27156255, 21570980,
|
||||
17134438, 13610368, 10811100, 8587562, 6821343, 5418385,
|
||||
4303976, 3418770, 2715625, 2157098, 1713444, 1361037,
|
||||
1081110, 858756, 682134, 541839, 430398, 341877,
|
||||
271563, 215710, 171344, 136104, 108111, 85876,
|
||||
68213, 54184, 43040, 34188, 27156, 21571,
|
||||
17134, 13610, 10811, 8588, 6821, 5418,
|
||||
4304, 3419, 2716, 2157, 1713, 1361,
|
||||
1081, 859, 682, 542, 430, 342,
|
||||
272, 216, 171, 136, 108, 86,
|
||||
68, 54, 43, 34, 27, 22,
|
||||
17, 14, 11, 9, 7, 5,
|
||||
4, 3, 3, 2, 2, 1,
|
||||
1, 1, 1, 1};
|
||||
|
||||
const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
|
||||
32702, 32636, 32570, 32505, 32439, 32374,
|
||||
32309, 32244, 32179, 32114, 32049, 31985};
|
||||
|
||||
} // namespace
|
||||
|
||||
ComfortNoiseDecoder::ComfortNoiseDecoder() {
|
||||
/* Needed to get the right function pointers in SPLIB. */
|
||||
Reset();
|
||||
}
|
||||
|
||||
void ComfortNoiseDecoder::Reset() {
|
||||
dec_seed_ = 7777; /* For debugging only. */
|
||||
dec_target_energy_ = 0;
|
||||
dec_used_energy_ = 0;
|
||||
for (auto& c : dec_target_reflCoefs_)
|
||||
c = 0;
|
||||
for (auto& c : dec_used_reflCoefs_)
|
||||
c = 0;
|
||||
for (auto& c : dec_filtstate_)
|
||||
c = 0;
|
||||
for (auto& c : dec_filtstateLow_)
|
||||
c = 0;
|
||||
dec_order_ = 5;
|
||||
dec_target_scale_factor_ = 0;
|
||||
dec_used_scale_factor_ = 0;
|
||||
}
|
||||
|
||||
void ComfortNoiseDecoder::UpdateSid(rtc::ArrayView<const uint8_t> sid) {
|
||||
int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER];
|
||||
int32_t targetEnergy;
|
||||
size_t length = sid.size();
|
||||
/* Throw away reflection coefficients of higher order than we can handle. */
|
||||
if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1))
|
||||
length = WEBRTC_CNG_MAX_LPC_ORDER + 1;
|
||||
|
||||
dec_order_ = static_cast<uint16_t>(length - 1);
|
||||
|
||||
uint8_t sid0 = std::min<uint8_t>(sid[0], 93);
|
||||
targetEnergy = WebRtcCng_kDbov[sid0];
|
||||
/* Take down target energy to 75%. */
|
||||
targetEnergy = targetEnergy >> 1;
|
||||
targetEnergy += targetEnergy >> 2;
|
||||
|
||||
dec_target_energy_ = targetEnergy;
|
||||
|
||||
/* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */
|
||||
if (dec_order_ == WEBRTC_CNG_MAX_LPC_ORDER) {
|
||||
for (size_t i = 0; i < (dec_order_); i++) {
|
||||
refCs[i] = sid[i + 1] << 8; /* Q7 to Q15*/
|
||||
dec_target_reflCoefs_[i] = refCs[i];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < (dec_order_); i++) {
|
||||
refCs[i] = (sid[i + 1] - 127) * (1 << 8); /* Q7 to Q15. */
|
||||
dec_target_reflCoefs_[i] = refCs[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = (dec_order_); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
|
||||
refCs[i] = 0;
|
||||
dec_target_reflCoefs_[i] = refCs[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool ComfortNoiseDecoder::Generate(rtc::ArrayView<int16_t> out_data,
|
||||
bool new_period) {
|
||||
int16_t excitation[kCngMaxOutsizeOrder];
|
||||
int16_t low[kCngMaxOutsizeOrder];
|
||||
int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t ReflBetaStd = 26214; /* 0.8 in q15. */
|
||||
int16_t ReflBetaCompStd = 6553; /* 0.2 in q15. */
|
||||
int16_t ReflBetaNewP = 19661; /* 0.6 in q15. */
|
||||
int16_t ReflBetaCompNewP = 13107; /* 0.4 in q15. */
|
||||
int16_t Beta, BetaC; /* These are in Q15. */
|
||||
int32_t targetEnergy;
|
||||
int16_t En;
|
||||
int16_t temp16;
|
||||
const size_t num_samples = out_data.size();
|
||||
|
||||
if (num_samples > kCngMaxOutsizeOrder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (new_period) {
|
||||
dec_used_scale_factor_ = dec_target_scale_factor_;
|
||||
Beta = ReflBetaNewP;
|
||||
BetaC = ReflBetaCompNewP;
|
||||
} else {
|
||||
Beta = ReflBetaStd;
|
||||
BetaC = ReflBetaCompStd;
|
||||
}
|
||||
|
||||
/* Calculate new scale factor in Q13 */
|
||||
dec_used_scale_factor_ = rtc::checked_cast<int16_t>(
|
||||
WEBRTC_SPL_MUL_16_16_RSFT(dec_used_scale_factor_, Beta >> 2, 13) +
|
||||
WEBRTC_SPL_MUL_16_16_RSFT(dec_target_scale_factor_, BetaC >> 2, 13));
|
||||
|
||||
dec_used_energy_ = dec_used_energy_ >> 1;
|
||||
dec_used_energy_ += dec_target_energy_ >> 1;
|
||||
|
||||
/* Do the same for the reflection coeffs, albeit in Q15. */
|
||||
for (size_t i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) {
|
||||
dec_used_reflCoefs_[i] =
|
||||
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_used_reflCoefs_[i], Beta, 15);
|
||||
dec_used_reflCoefs_[i] +=
|
||||
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_target_reflCoefs_[i], BetaC, 15);
|
||||
}
|
||||
|
||||
/* Compute the polynomial coefficients. */
|
||||
WebRtcCng_K2a16(dec_used_reflCoefs_, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
|
||||
|
||||
targetEnergy = dec_used_energy_;
|
||||
|
||||
/* Calculate scaling factor based on filter energy. */
|
||||
En = 8192; /* 1.0 in Q13. */
|
||||
for (size_t i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) {
|
||||
/* Floating point value for reference.
|
||||
E *= 1.0 - (dec_used_reflCoefs_[i] / 32768.0) *
|
||||
(dec_used_reflCoefs_[i] / 32768.0);
|
||||
*/
|
||||
|
||||
/* Same in fixed point. */
|
||||
/* K(i).^2 in Q15. */
|
||||
temp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(dec_used_reflCoefs_[i],
|
||||
dec_used_reflCoefs_[i], 15);
|
||||
/* 1 - K(i).^2 in Q15. */
|
||||
temp16 = 0x7fff - temp16;
|
||||
En = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15);
|
||||
}
|
||||
|
||||
/* float scaling= sqrt(E * dec_target_energy_ / (1 << 24)); */
|
||||
|
||||
/* Calculate sqrt(En * target_energy / excitation energy) */
|
||||
targetEnergy = WebRtcSpl_Sqrt(dec_used_energy_);
|
||||
|
||||
En = (int16_t)WebRtcSpl_Sqrt(En) << 6;
|
||||
En = (En * 3) >> 1; /* 1.5 estimates sqrt(2). */
|
||||
dec_used_scale_factor_ = (int16_t)((En * targetEnergy) >> 12);
|
||||
|
||||
/* Generate excitation. */
|
||||
/* Excitation energy per sample is 2.^24 - Q13 N(0,1). */
|
||||
for (size_t i = 0; i < num_samples; i++) {
|
||||
excitation[i] = WebRtcSpl_RandN(&dec_seed_) >> 1;
|
||||
}
|
||||
|
||||
/* Scale to correct energy. */
|
||||
WebRtcSpl_ScaleVector(excitation, excitation, dec_used_scale_factor_,
|
||||
num_samples, 13);
|
||||
|
||||
/* `lpPoly` - Coefficients in Q12.
|
||||
* `excitation` - Speech samples.
|
||||
* `nst->dec_filtstate` - State preservation.
|
||||
* `out_data` - Filtered speech samples. */
|
||||
WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation,
|
||||
num_samples, dec_filtstate_, WEBRTC_CNG_MAX_LPC_ORDER,
|
||||
dec_filtstateLow_, WEBRTC_CNG_MAX_LPC_ORDER,
|
||||
out_data.data(), low, num_samples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ComfortNoiseEncoder::ComfortNoiseEncoder(int fs, int interval, int quality)
|
||||
: enc_nrOfCoefs_(quality),
|
||||
enc_sampfreq_(fs),
|
||||
enc_interval_(interval),
|
||||
enc_msSinceSid_(0),
|
||||
enc_Energy_(0),
|
||||
enc_reflCoefs_{0},
|
||||
enc_corrVector_{0},
|
||||
enc_seed_(7777) /* For debugging only. */ {
|
||||
RTC_CHECK_GT(quality, 0);
|
||||
RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
|
||||
}
|
||||
|
||||
void ComfortNoiseEncoder::Reset(int fs, int interval, int quality) {
|
||||
RTC_CHECK_GT(quality, 0);
|
||||
RTC_CHECK_LE(quality, WEBRTC_CNG_MAX_LPC_ORDER);
|
||||
enc_nrOfCoefs_ = quality;
|
||||
enc_sampfreq_ = fs;
|
||||
enc_interval_ = interval;
|
||||
enc_msSinceSid_ = 0;
|
||||
enc_Energy_ = 0;
|
||||
for (auto& c : enc_reflCoefs_)
|
||||
c = 0;
|
||||
for (auto& c : enc_corrVector_)
|
||||
c = 0;
|
||||
enc_seed_ = 7777; /* For debugging only. */
|
||||
}
|
||||
|
||||
size_t ComfortNoiseEncoder::Encode(rtc::ArrayView<const int16_t> speech,
|
||||
bool force_sid,
|
||||
rtc::Buffer* output) {
|
||||
int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t hanningW[kCngMaxOutsizeOrder];
|
||||
int16_t ReflBeta = 19661; /* 0.6 in q15. */
|
||||
int16_t ReflBetaComp = 13107; /* 0.4 in q15. */
|
||||
int32_t outEnergy;
|
||||
int outShifts;
|
||||
size_t i;
|
||||
int stab;
|
||||
int acorrScale;
|
||||
size_t index;
|
||||
size_t ind, factor;
|
||||
int32_t* bptr;
|
||||
int32_t blo, bhi;
|
||||
int16_t negate;
|
||||
const int16_t* aptr;
|
||||
int16_t speechBuf[kCngMaxOutsizeOrder];
|
||||
|
||||
const size_t num_samples = speech.size();
|
||||
RTC_CHECK_LE(num_samples, kCngMaxOutsizeOrder);
|
||||
|
||||
for (i = 0; i < num_samples; i++) {
|
||||
speechBuf[i] = speech[i];
|
||||
}
|
||||
|
||||
factor = num_samples;
|
||||
|
||||
/* Calculate energy and a coefficients. */
|
||||
outEnergy = WebRtcSpl_Energy(speechBuf, num_samples, &outShifts);
|
||||
while (outShifts > 0) {
|
||||
/* We can only do 5 shifts without destroying accuracy in
|
||||
* division factor. */
|
||||
if (outShifts > 5) {
|
||||
outEnergy <<= (outShifts - 5);
|
||||
outShifts = 5;
|
||||
} else {
|
||||
factor /= 2;
|
||||
outShifts--;
|
||||
}
|
||||
}
|
||||
outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor);
|
||||
|
||||
if (outEnergy > 1) {
|
||||
/* Create Hanning Window. */
|
||||
WebRtcSpl_GetHanningWindow(hanningW, num_samples / 2);
|
||||
for (i = 0; i < (num_samples / 2); i++)
|
||||
hanningW[num_samples - i - 1] = hanningW[i];
|
||||
|
||||
WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, num_samples,
|
||||
14);
|
||||
|
||||
WebRtcSpl_AutoCorrelation(speechBuf, num_samples, enc_nrOfCoefs_,
|
||||
corrVector, &acorrScale);
|
||||
|
||||
if (*corrVector == 0)
|
||||
*corrVector = WEBRTC_SPL_WORD16_MAX;
|
||||
|
||||
/* Adds the bandwidth expansion. */
|
||||
aptr = WebRtcCng_kCorrWindow;
|
||||
bptr = corrVector;
|
||||
|
||||
/* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */
|
||||
for (ind = 0; ind < enc_nrOfCoefs_; ind++) {
|
||||
/* The below code multiplies the 16 b corrWindow values (Q15) with
|
||||
* the 32 b corrvector (Q0) and shifts the result down 15 steps. */
|
||||
negate = *bptr < 0;
|
||||
if (negate)
|
||||
*bptr = -*bptr;
|
||||
|
||||
blo = (int32_t)*aptr * (*bptr & 0xffff);
|
||||
bhi = ((blo >> 16) & 0xffff) +
|
||||
((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff));
|
||||
blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
|
||||
|
||||
*bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t)blo >> 15);
|
||||
if (negate)
|
||||
*bptr = -*bptr;
|
||||
bptr++;
|
||||
}
|
||||
/* End of bandwidth expansion. */
|
||||
|
||||
stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs, enc_nrOfCoefs_);
|
||||
|
||||
if (!stab) {
|
||||
/* Disregard from this frame */
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
for (i = 0; i < enc_nrOfCoefs_; i++)
|
||||
refCs[i] = 0;
|
||||
}
|
||||
|
||||
if (force_sid) {
|
||||
/* Read instantaneous values instead of averaged. */
|
||||
for (i = 0; i < enc_nrOfCoefs_; i++)
|
||||
enc_reflCoefs_[i] = refCs[i];
|
||||
enc_Energy_ = outEnergy;
|
||||
} else {
|
||||
/* Average history with new values. */
|
||||
for (i = 0; i < enc_nrOfCoefs_; i++) {
|
||||
enc_reflCoefs_[i] =
|
||||
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(enc_reflCoefs_[i], ReflBeta, 15);
|
||||
enc_reflCoefs_[i] +=
|
||||
(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(refCs[i], ReflBetaComp, 15);
|
||||
}
|
||||
enc_Energy_ = (outEnergy >> 2) + (enc_Energy_ >> 1) + (enc_Energy_ >> 2);
|
||||
}
|
||||
|
||||
if (enc_Energy_ < 1) {
|
||||
enc_Energy_ = 1;
|
||||
}
|
||||
|
||||
if ((enc_msSinceSid_ > (enc_interval_ - 1)) || force_sid) {
|
||||
/* Search for best dbov value. */
|
||||
index = 0;
|
||||
for (i = 1; i < 93; i++) {
|
||||
/* Always round downwards. */
|
||||
if ((enc_Energy_ - WebRtcCng_kDbov[i]) > 0) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((i == 93) && (index == 0))
|
||||
index = 94;
|
||||
|
||||
const size_t output_coefs = enc_nrOfCoefs_ + 1;
|
||||
output->AppendData(output_coefs, [&](rtc::ArrayView<uint8_t> output) {
|
||||
output[0] = (uint8_t)index;
|
||||
|
||||
/* Quantize coefficients with tweak for WebRtc implementation of
|
||||
* RFC3389. */
|
||||
if (enc_nrOfCoefs_ == WEBRTC_CNG_MAX_LPC_ORDER) {
|
||||
for (i = 0; i < enc_nrOfCoefs_; i++) {
|
||||
/* Q15 to Q7 with rounding. */
|
||||
output[i + 1] = ((enc_reflCoefs_[i] + 128) >> 8);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < enc_nrOfCoefs_; i++) {
|
||||
/* Q15 to Q7 with rounding. */
|
||||
output[i + 1] = (127 + ((enc_reflCoefs_[i] + 128) >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
return output_coefs;
|
||||
});
|
||||
|
||||
enc_msSinceSid_ =
|
||||
static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
|
||||
return output_coefs;
|
||||
} else {
|
||||
enc_msSinceSid_ +=
|
||||
static_cast<int16_t>((1000 * num_samples) / enc_sampfreq_);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
/* Values in `k` are Q15, and `a` Q12. */
|
||||
void WebRtcCng_K2a16(int16_t* k, int useOrder, int16_t* a) {
|
||||
int16_t any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
|
||||
int16_t* aptr;
|
||||
int16_t* aptr2;
|
||||
int16_t* anyptr;
|
||||
const int16_t* kptr;
|
||||
int m, i;
|
||||
|
||||
kptr = k;
|
||||
*a = 4096; /* i.e., (Word16_MAX >> 3) + 1 */
|
||||
*any = *a;
|
||||
a[1] = (*k + 4) >> 3;
|
||||
for (m = 1; m < useOrder; m++) {
|
||||
kptr++;
|
||||
aptr = a;
|
||||
aptr++;
|
||||
aptr2 = &a[m];
|
||||
anyptr = any;
|
||||
anyptr++;
|
||||
|
||||
any[m + 1] = (*kptr + 4) >> 3;
|
||||
for (i = 0; i < m; i++) {
|
||||
*anyptr++ =
|
||||
(*aptr++) +
|
||||
(int16_t)((((int32_t)(*aptr2--) * (int32_t)*kptr) + 16384) >> 15);
|
||||
}
|
||||
|
||||
aptr = a;
|
||||
anyptr = any;
|
||||
for (i = 0; i < (m + 2); i++) {
|
||||
*aptr++ = *anyptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
|
||||
#define WEBRTC_CNG_MAX_LPC_ORDER 12
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ComfortNoiseDecoder {
|
||||
public:
|
||||
ComfortNoiseDecoder();
|
||||
~ComfortNoiseDecoder() = default;
|
||||
|
||||
ComfortNoiseDecoder(const ComfortNoiseDecoder&) = delete;
|
||||
ComfortNoiseDecoder& operator=(const ComfortNoiseDecoder&) = delete;
|
||||
|
||||
void Reset();
|
||||
|
||||
// Updates the CN state when a new SID packet arrives.
|
||||
// `sid` is a view of the SID packet without the headers.
|
||||
void UpdateSid(rtc::ArrayView<const uint8_t> sid);
|
||||
|
||||
// Generates comfort noise.
|
||||
// `out_data` will be filled with samples - its size determines the number of
|
||||
// samples generated. When `new_period` is true, CNG history will be reset
|
||||
// before any audio is generated. Returns `false` if outData is too large -
|
||||
// currently 640 bytes (equalling 10ms at 64kHz).
|
||||
// TODO(ossu): Specify better limits for the size of out_data. Either let it
|
||||
// be unbounded or limit to 10ms in the current sample rate.
|
||||
bool Generate(rtc::ArrayView<int16_t> out_data, bool new_period);
|
||||
|
||||
private:
|
||||
uint32_t dec_seed_;
|
||||
int32_t dec_target_energy_;
|
||||
int32_t dec_used_energy_;
|
||||
int16_t dec_target_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t dec_used_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t dec_filtstate_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int16_t dec_filtstateLow_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
uint16_t dec_order_;
|
||||
int16_t dec_target_scale_factor_; /* Q29 */
|
||||
int16_t dec_used_scale_factor_; /* Q29 */
|
||||
};
|
||||
|
||||
class ComfortNoiseEncoder {
|
||||
public:
|
||||
// Creates a comfort noise encoder.
|
||||
// `fs` selects sample rate: 8000 for narrowband or 16000 for wideband.
|
||||
// `interval` sets the interval at which to generate SID data (in ms).
|
||||
// `quality` selects the number of refl. coeffs. Maximum allowed is 12.
|
||||
ComfortNoiseEncoder(int fs, int interval, int quality);
|
||||
~ComfortNoiseEncoder() = default;
|
||||
|
||||
ComfortNoiseEncoder(const ComfortNoiseEncoder&) = delete;
|
||||
ComfortNoiseEncoder& operator=(const ComfortNoiseEncoder&) = delete;
|
||||
|
||||
// Resets the comfort noise encoder to its initial state.
|
||||
// Parameters are set as during construction.
|
||||
void Reset(int fs, int interval, int quality);
|
||||
|
||||
// Analyzes background noise from `speech` and appends coefficients to
|
||||
// `output`. Returns the number of coefficients generated. If `force_sid` is
|
||||
// true, a SID frame is forced and the internal sid interval counter is reset.
|
||||
// Will fail if the input size is too large (> 640 samples, see
|
||||
// ComfortNoiseDecoder::Generate).
|
||||
size_t Encode(rtc::ArrayView<const int16_t> speech,
|
||||
bool force_sid,
|
||||
rtc::Buffer* output);
|
||||
|
||||
private:
|
||||
size_t enc_nrOfCoefs_;
|
||||
int enc_sampfreq_;
|
||||
int16_t enc_interval_;
|
||||
int16_t enc_msSinceSid_;
|
||||
int32_t enc_Energy_;
|
||||
int16_t enc_reflCoefs_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
int32_t enc_corrVector_[WEBRTC_CNG_MAX_LPC_ORDER + 1];
|
||||
uint32_t enc_seed_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_CNG_WEBRTC_CNG_H_
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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 "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "modules/audio_coding/codecs/g711/g711_interface.h"
|
||||
#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void AudioDecoderPcmU::Reset() {}
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoderPcmU::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
return LegacyEncodedAudioFrame::SplitBySamples(
|
||||
this, std::move(payload), timestamp, 8 * num_channels_, 8);
|
||||
}
|
||||
|
||||
int AudioDecoderPcmU::SampleRateHz() const {
|
||||
return 8000;
|
||||
}
|
||||
|
||||
size_t AudioDecoderPcmU::Channels() const {
|
||||
return num_channels_;
|
||||
}
|
||||
|
||||
int AudioDecoderPcmU::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
|
||||
// Adjust the encoded length down to ensure the same number of samples in each
|
||||
// channel.
|
||||
const size_t encoded_len_adjusted =
|
||||
PacketDuration(encoded, encoded_len) *
|
||||
Channels(); // 1 byte per sample per channel
|
||||
int16_t temp_type = 1; // Default is speech.
|
||||
size_t ret =
|
||||
WebRtcG711_DecodeU(encoded, encoded_len_adjusted, decoded, &temp_type);
|
||||
*speech_type = ConvertSpeechType(temp_type);
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
int AudioDecoderPcmU::PacketDuration(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
// One encoded byte per sample per channel.
|
||||
return static_cast<int>(encoded_len / Channels());
|
||||
}
|
||||
|
||||
int AudioDecoderPcmU::PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return PacketDuration(encoded, encoded_len);
|
||||
}
|
||||
|
||||
void AudioDecoderPcmA::Reset() {}
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoderPcmA::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
return LegacyEncodedAudioFrame::SplitBySamples(
|
||||
this, std::move(payload), timestamp, 8 * num_channels_, 8);
|
||||
}
|
||||
|
||||
int AudioDecoderPcmA::SampleRateHz() const {
|
||||
return 8000;
|
||||
}
|
||||
|
||||
size_t AudioDecoderPcmA::Channels() const {
|
||||
return num_channels_;
|
||||
}
|
||||
|
||||
int AudioDecoderPcmA::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
|
||||
// Adjust the encoded length down to ensure the same number of samples in each
|
||||
// channel.
|
||||
const size_t encoded_len_adjusted =
|
||||
PacketDuration(encoded, encoded_len) *
|
||||
Channels(); // 1 byte per sample per channel
|
||||
int16_t temp_type = 1; // Default is speech.
|
||||
size_t ret =
|
||||
WebRtcG711_DecodeA(encoded, encoded_len_adjusted, decoded, &temp_type);
|
||||
*speech_type = ConvertSpeechType(temp_type);
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
int AudioDecoderPcmA::PacketDuration(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
// One encoded byte per sample per channel.
|
||||
return static_cast<int>(encoded_len / Channels());
|
||||
}
|
||||
|
||||
int AudioDecoderPcmA::PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return PacketDuration(encoded, encoded_len);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDecoderPcmU final : public AudioDecoder {
|
||||
public:
|
||||
explicit AudioDecoderPcmU(size_t num_channels) : num_channels_(num_channels) {
|
||||
RTC_DCHECK_GE(num_channels, 1);
|
||||
}
|
||||
|
||||
AudioDecoderPcmU(const AudioDecoderPcmU&) = delete;
|
||||
AudioDecoderPcmU& operator=(const AudioDecoderPcmU&) = delete;
|
||||
|
||||
void Reset() override;
|
||||
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp) override;
|
||||
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
|
||||
int PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const override;
|
||||
int SampleRateHz() const override;
|
||||
size_t Channels() const override;
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
private:
|
||||
const size_t num_channels_;
|
||||
};
|
||||
|
||||
class AudioDecoderPcmA final : public AudioDecoder {
|
||||
public:
|
||||
explicit AudioDecoderPcmA(size_t num_channels) : num_channels_(num_channels) {
|
||||
RTC_DCHECK_GE(num_channels, 1);
|
||||
}
|
||||
|
||||
AudioDecoderPcmA(const AudioDecoderPcmA&) = delete;
|
||||
AudioDecoderPcmA& operator=(const AudioDecoderPcmA&) = delete;
|
||||
|
||||
void Reset() override;
|
||||
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp) override;
|
||||
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
|
||||
int PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const override;
|
||||
int SampleRateHz() const override;
|
||||
size_t Channels() const override;
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
private:
|
||||
const size_t num_channels_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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 "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "modules/audio_coding/codecs/g711/g711_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
bool AudioEncoderPcm::Config::IsOk() const {
|
||||
return (frame_size_ms % 10 == 0) && (num_channels >= 1);
|
||||
}
|
||||
|
||||
AudioEncoderPcm::AudioEncoderPcm(const Config& config, int sample_rate_hz)
|
||||
: sample_rate_hz_(sample_rate_hz),
|
||||
num_channels_(config.num_channels),
|
||||
payload_type_(config.payload_type),
|
||||
num_10ms_frames_per_packet_(
|
||||
static_cast<size_t>(config.frame_size_ms / 10)),
|
||||
full_frame_samples_(config.num_channels * config.frame_size_ms *
|
||||
sample_rate_hz / 1000),
|
||||
first_timestamp_in_buffer_(0) {
|
||||
RTC_CHECK_GT(sample_rate_hz, 0) << "Sample rate must be larger than 0 Hz";
|
||||
RTC_CHECK_EQ(config.frame_size_ms % 10, 0)
|
||||
<< "Frame size must be an integer multiple of 10 ms.";
|
||||
speech_buffer_.reserve(full_frame_samples_);
|
||||
}
|
||||
|
||||
AudioEncoderPcm::~AudioEncoderPcm() = default;
|
||||
|
||||
int AudioEncoderPcm::SampleRateHz() const {
|
||||
return sample_rate_hz_;
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcm::NumChannels() const {
|
||||
return num_channels_;
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcm::Num10MsFramesInNextPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcm::Max10MsFramesInAPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
int AudioEncoderPcm::GetTargetBitrate() const {
|
||||
return static_cast<int>(8 * BytesPerSample() * SampleRateHz() *
|
||||
NumChannels());
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderPcm::EncodeImpl(
|
||||
uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) {
|
||||
if (speech_buffer_.empty()) {
|
||||
first_timestamp_in_buffer_ = rtp_timestamp;
|
||||
}
|
||||
speech_buffer_.insert(speech_buffer_.end(), audio.begin(), audio.end());
|
||||
if (speech_buffer_.size() < full_frame_samples_) {
|
||||
return EncodedInfo();
|
||||
}
|
||||
RTC_CHECK_EQ(speech_buffer_.size(), full_frame_samples_);
|
||||
EncodedInfo info;
|
||||
info.encoded_timestamp = first_timestamp_in_buffer_;
|
||||
info.payload_type = payload_type_;
|
||||
info.encoded_bytes = encoded->AppendData(
|
||||
full_frame_samples_ * BytesPerSample(),
|
||||
[&](rtc::ArrayView<uint8_t> encoded) {
|
||||
return EncodeCall(&speech_buffer_[0], full_frame_samples_,
|
||||
encoded.data());
|
||||
});
|
||||
speech_buffer_.clear();
|
||||
info.encoder_type = GetCodecType();
|
||||
return info;
|
||||
}
|
||||
|
||||
void AudioEncoderPcm::Reset() {
|
||||
speech_buffer_.clear();
|
||||
}
|
||||
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>>
|
||||
AudioEncoderPcm::GetFrameLengthRange() const {
|
||||
return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
|
||||
TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcmA::EncodeCall(const int16_t* audio,
|
||||
size_t input_len,
|
||||
uint8_t* encoded) {
|
||||
return WebRtcG711_EncodeA(audio, input_len, encoded);
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcmA::BytesPerSample() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
AudioEncoder::CodecType AudioEncoderPcmA::GetCodecType() const {
|
||||
return AudioEncoder::CodecType::kPcmA;
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
|
||||
size_t input_len,
|
||||
uint8_t* encoded) {
|
||||
return WebRtcG711_EncodeU(audio, input_len, encoded);
|
||||
}
|
||||
|
||||
size_t AudioEncoderPcmU::BytesPerSample() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
AudioEncoder::CodecType AudioEncoderPcmU::GetCodecType() const {
|
||||
return AudioEncoder::CodecType::kPcmU;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/units/time_delta.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioEncoderPcm : public AudioEncoder {
|
||||
public:
|
||||
struct Config {
|
||||
public:
|
||||
bool IsOk() const;
|
||||
|
||||
int frame_size_ms;
|
||||
size_t num_channels;
|
||||
int payload_type;
|
||||
|
||||
protected:
|
||||
explicit Config(int pt)
|
||||
: frame_size_ms(20), num_channels(1), payload_type(pt) {}
|
||||
};
|
||||
|
||||
~AudioEncoderPcm() override;
|
||||
|
||||
int SampleRateHz() const override;
|
||||
size_t NumChannels() const override;
|
||||
size_t Num10MsFramesInNextPacket() const override;
|
||||
size_t Max10MsFramesInAPacket() const override;
|
||||
int GetTargetBitrate() const override;
|
||||
void Reset() override;
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||
const override;
|
||||
|
||||
protected:
|
||||
AudioEncoderPcm(const Config& config, int sample_rate_hz);
|
||||
|
||||
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) override;
|
||||
|
||||
virtual size_t EncodeCall(const int16_t* audio,
|
||||
size_t input_len,
|
||||
uint8_t* encoded) = 0;
|
||||
|
||||
virtual size_t BytesPerSample() const = 0;
|
||||
|
||||
// Used to set EncodedInfoLeaf::encoder_type in
|
||||
// AudioEncoderPcm::EncodeImpl
|
||||
virtual AudioEncoder::CodecType GetCodecType() const = 0;
|
||||
|
||||
private:
|
||||
const int sample_rate_hz_;
|
||||
const size_t num_channels_;
|
||||
const int payload_type_;
|
||||
const size_t num_10ms_frames_per_packet_;
|
||||
const size_t full_frame_samples_;
|
||||
std::vector<int16_t> speech_buffer_;
|
||||
uint32_t first_timestamp_in_buffer_;
|
||||
};
|
||||
|
||||
class AudioEncoderPcmA final : public AudioEncoderPcm {
|
||||
public:
|
||||
struct Config : public AudioEncoderPcm::Config {
|
||||
Config() : AudioEncoderPcm::Config(8) {}
|
||||
};
|
||||
|
||||
explicit AudioEncoderPcmA(const Config& config)
|
||||
: AudioEncoderPcm(config, kSampleRateHz) {}
|
||||
|
||||
AudioEncoderPcmA(const AudioEncoderPcmA&) = delete;
|
||||
AudioEncoderPcmA& operator=(const AudioEncoderPcmA&) = delete;
|
||||
|
||||
protected:
|
||||
size_t EncodeCall(const int16_t* audio,
|
||||
size_t input_len,
|
||||
uint8_t* encoded) override;
|
||||
|
||||
size_t BytesPerSample() const override;
|
||||
|
||||
AudioEncoder::CodecType GetCodecType() const override;
|
||||
|
||||
private:
|
||||
static const int kSampleRateHz = 8000;
|
||||
};
|
||||
|
||||
class AudioEncoderPcmU final : public AudioEncoderPcm {
|
||||
public:
|
||||
struct Config : public AudioEncoderPcm::Config {
|
||||
Config() : AudioEncoderPcm::Config(0) {}
|
||||
};
|
||||
|
||||
explicit AudioEncoderPcmU(const Config& config)
|
||||
: AudioEncoderPcm(config, kSampleRateHz) {}
|
||||
|
||||
AudioEncoderPcmU(const AudioEncoderPcmU&) = delete;
|
||||
AudioEncoderPcmU& operator=(const AudioEncoderPcmU&) = delete;
|
||||
|
||||
protected:
|
||||
size_t EncodeCall(const int16_t* audio,
|
||||
size_t input_len,
|
||||
uint8_t* encoded) override;
|
||||
|
||||
size_t BytesPerSample() const override;
|
||||
|
||||
AudioEncoder::CodecType GetCodecType() const override;
|
||||
|
||||
private:
|
||||
static const int kSampleRateHz = 8000;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_G711_AUDIO_ENCODER_PCM_H_
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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 <string.h>
|
||||
|
||||
#include "modules/third_party/g711/g711.h"
|
||||
#include "modules/audio_coding/codecs/g711/g711_interface.h"
|
||||
|
||||
size_t WebRtcG711_EncodeA(const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded) {
|
||||
size_t n;
|
||||
for (n = 0; n < len; n++)
|
||||
encoded[n] = linear_to_alaw(speechIn[n]);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t WebRtcG711_EncodeU(const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded) {
|
||||
size_t n;
|
||||
for (n = 0; n < len; n++)
|
||||
encoded[n] = linear_to_ulaw(speechIn[n]);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t WebRtcG711_DecodeA(const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType) {
|
||||
size_t n;
|
||||
for (n = 0; n < len; n++)
|
||||
decoded[n] = alaw_to_linear(encoded[n]);
|
||||
*speechType = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t WebRtcG711_DecodeU(const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType) {
|
||||
size_t n;
|
||||
for (n = 0; n < len; n++)
|
||||
decoded[n] = ulaw_to_linear(encoded[n]);
|
||||
*speechType = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
int16_t WebRtcG711_Version(char* version, int16_t lenBytes) {
|
||||
strncpy(version, "2.0.0", lenBytes);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Comfort noise constants
|
||||
#define G711_WEBRTC_SPEECH 1
|
||||
#define G711_WEBRTC_CNG 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG711_EncodeA(...)
|
||||
*
|
||||
* This function encodes a G711 A-law frame and inserts it into a packet.
|
||||
* Input speech length has be of any length.
|
||||
*
|
||||
* Input:
|
||||
* - speechIn : Input speech vector
|
||||
* - len : Samples in speechIn
|
||||
*
|
||||
* Output:
|
||||
* - encoded : The encoded data vector
|
||||
*
|
||||
* Return value : Length (in bytes) of coded data.
|
||||
* Always equal to len input parameter.
|
||||
*/
|
||||
|
||||
size_t WebRtcG711_EncodeA(const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG711_EncodeU(...)
|
||||
*
|
||||
* This function encodes a G711 U-law frame and inserts it into a packet.
|
||||
* Input speech length has be of any length.
|
||||
*
|
||||
* Input:
|
||||
* - speechIn : Input speech vector
|
||||
* - len : Samples in speechIn
|
||||
*
|
||||
* Output:
|
||||
* - encoded : The encoded data vector
|
||||
*
|
||||
* Return value : Length (in bytes) of coded data.
|
||||
* Always equal to len input parameter.
|
||||
*/
|
||||
|
||||
size_t WebRtcG711_EncodeU(const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG711_DecodeA(...)
|
||||
*
|
||||
* This function decodes a packet G711 A-law frame.
|
||||
*
|
||||
* Input:
|
||||
* - encoded : Encoded data
|
||||
* - len : Bytes in encoded vector
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The decoded vector
|
||||
* - speechType : 1 normal, 2 CNG (for G711 it should
|
||||
* always return 1 since G711 does not have a
|
||||
* built-in DTX/CNG scheme)
|
||||
*
|
||||
* Return value : >0 - Samples in decoded vector
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
size_t WebRtcG711_DecodeA(const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG711_DecodeU(...)
|
||||
*
|
||||
* This function decodes a packet G711 U-law frame.
|
||||
*
|
||||
* Input:
|
||||
* - encoded : Encoded data
|
||||
* - len : Bytes in encoded vector
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The decoded vector
|
||||
* - speechType : 1 normal, 2 CNG (for G711 it should
|
||||
* always return 1 since G711 does not have a
|
||||
* built-in DTX/CNG scheme)
|
||||
*
|
||||
* Return value : >0 - Samples in decoded vector
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
size_t WebRtcG711_DecodeU(const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
|
||||
/**********************************************************************
|
||||
* WebRtcG711_Version(...)
|
||||
*
|
||||
* This function gives the version string of the G.711 codec.
|
||||
*
|
||||
* Input:
|
||||
* - lenBytes: the size of Allocated space (in Bytes) where
|
||||
* the version number is written to (in string format).
|
||||
*
|
||||
* Output:
|
||||
* - version: Pointer to a buffer where the version number is
|
||||
* written to.
|
||||
*
|
||||
*/
|
||||
|
||||
int16_t WebRtcG711_Version(char* version, int16_t lenBytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* testG711.cpp : Defines the entry point for the console application.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* include API */
|
||||
#include "modules/audio_coding/codecs/g711/g711_interface.h"
|
||||
|
||||
/* Runtime statistics */
|
||||
#include <time.h>
|
||||
#define CLOCKS_PER_SEC_G711 1000
|
||||
|
||||
/* function for reading audio data from PCM file */
|
||||
bool readframe(int16_t* data, FILE* inp, size_t length) {
|
||||
size_t rlen = fread(data, sizeof(int16_t), length, inp);
|
||||
if (rlen >= length)
|
||||
return false;
|
||||
memset(data + rlen, 0, (length - rlen) * sizeof(int16_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
char inname[80], outname[40], bitname[40];
|
||||
FILE* inp;
|
||||
FILE* outp;
|
||||
FILE* bitp = NULL;
|
||||
int framecnt;
|
||||
bool endfile;
|
||||
|
||||
size_t framelength = 80;
|
||||
|
||||
/* Runtime statistics */
|
||||
double starttime;
|
||||
double runtime;
|
||||
double length_file;
|
||||
|
||||
size_t stream_len = 0;
|
||||
int16_t shortdata[480];
|
||||
int16_t decoded[480];
|
||||
uint8_t streamdata[1000];
|
||||
int16_t speechType[1];
|
||||
char law[2];
|
||||
char versionNumber[40];
|
||||
|
||||
/* handling wrong input arguments in the command line */
|
||||
if ((argc != 5) && (argc != 6)) {
|
||||
printf("\n\nWrong number of arguments or flag values.\n\n");
|
||||
|
||||
printf("\n");
|
||||
printf("\nG.711 test application\n\n");
|
||||
printf("Usage:\n\n");
|
||||
printf("./testG711.exe framelength law infile outfile \n\n");
|
||||
printf("framelength: Framelength in samples.\n");
|
||||
printf("law : Coding law, A och u.\n");
|
||||
printf("infile : Normal speech input file\n");
|
||||
printf("outfile : Speech output file\n\n");
|
||||
printf("outbits : Output bitstream file [optional]\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Get version and print */
|
||||
WebRtcG711_Version(versionNumber, 40);
|
||||
|
||||
printf("-----------------------------------\n");
|
||||
printf("G.711 version: %s\n\n", versionNumber);
|
||||
/* Get frame length */
|
||||
int framelength_int = atoi(argv[1]);
|
||||
if (framelength_int < 0) {
|
||||
printf(" G.722: Invalid framelength %d.\n", framelength_int);
|
||||
exit(1);
|
||||
}
|
||||
framelength = static_cast<size_t>(framelength_int);
|
||||
|
||||
/* Get compression law */
|
||||
strcpy(law, argv[2]);
|
||||
|
||||
/* Get Input and Output files */
|
||||
sscanf(argv[3], "%s", inname);
|
||||
sscanf(argv[4], "%s", outname);
|
||||
if (argc == 6) {
|
||||
sscanf(argv[5], "%s", bitname);
|
||||
if ((bitp = fopen(bitname, "wb")) == NULL) {
|
||||
printf(" G.711: Cannot read file %s.\n", bitname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((inp = fopen(inname, "rb")) == NULL) {
|
||||
printf(" G.711: Cannot read file %s.\n", inname);
|
||||
exit(1);
|
||||
}
|
||||
if ((outp = fopen(outname, "wb")) == NULL) {
|
||||
printf(" G.711: Cannot write file %s.\n", outname);
|
||||
exit(1);
|
||||
}
|
||||
printf("\nInput: %s\nOutput: %s\n", inname, outname);
|
||||
if (argc == 6) {
|
||||
printf("\nBitfile: %s\n", bitname);
|
||||
}
|
||||
|
||||
starttime = clock() / (double)CLOCKS_PER_SEC_G711; /* Runtime statistics */
|
||||
|
||||
/* Initialize encoder and decoder */
|
||||
framecnt = 0;
|
||||
endfile = false;
|
||||
while (!endfile) {
|
||||
framecnt++;
|
||||
/* Read speech block */
|
||||
endfile = readframe(shortdata, inp, framelength);
|
||||
|
||||
/* G.711 encoding */
|
||||
if (!strcmp(law, "A")) {
|
||||
/* A-law encoding */
|
||||
stream_len = WebRtcG711_EncodeA(shortdata, framelength, streamdata);
|
||||
if (argc == 6) {
|
||||
/* Write bits to file */
|
||||
if (fwrite(streamdata, sizeof(unsigned char), stream_len, bitp) !=
|
||||
stream_len) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
WebRtcG711_DecodeA(streamdata, stream_len, decoded, speechType);
|
||||
} else if (!strcmp(law, "u")) {
|
||||
/* u-law encoding */
|
||||
stream_len = WebRtcG711_EncodeU(shortdata, framelength, streamdata);
|
||||
if (argc == 6) {
|
||||
/* Write bits to file */
|
||||
if (fwrite(streamdata, sizeof(unsigned char), stream_len, bitp) !=
|
||||
stream_len) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
WebRtcG711_DecodeU(streamdata, stream_len, decoded, speechType);
|
||||
} else {
|
||||
printf("Wrong law mode\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Write coded speech to file */
|
||||
if (fwrite(decoded, sizeof(short), framelength, outp) != framelength) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
runtime = (double)(clock() / (double)CLOCKS_PER_SEC_G711 - starttime);
|
||||
length_file = ((double)framecnt * (double)framelength / 8000);
|
||||
printf("\n\nLength of speech file: %.1f s\n", length_file);
|
||||
printf("Time to run G.711: %.2f s (%.2f %% of realtime)\n\n", runtime,
|
||||
(100 * runtime / length_file));
|
||||
printf("---------------------END----------------------\n");
|
||||
|
||||
fclose(inp);
|
||||
fclose(outp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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 "modules/audio_coding/codecs/g722/audio_decoder_g722.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "modules/audio_coding/codecs/g722/g722_interface.h"
|
||||
#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioDecoderG722Impl::AudioDecoderG722Impl() {
|
||||
WebRtcG722_CreateDecoder(&dec_state_);
|
||||
WebRtcG722_DecoderInit(dec_state_);
|
||||
}
|
||||
|
||||
AudioDecoderG722Impl::~AudioDecoderG722Impl() {
|
||||
WebRtcG722_FreeDecoder(dec_state_);
|
||||
}
|
||||
|
||||
bool AudioDecoderG722Impl::HasDecodePlc() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
int AudioDecoderG722Impl::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
|
||||
int16_t temp_type = 1; // Default is speech.
|
||||
size_t ret =
|
||||
WebRtcG722_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
|
||||
*speech_type = ConvertSpeechType(temp_type);
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
void AudioDecoderG722Impl::Reset() {
|
||||
WebRtcG722_DecoderInit(dec_state_);
|
||||
}
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoderG722Impl::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
return LegacyEncodedAudioFrame::SplitBySamples(this, std::move(payload),
|
||||
timestamp, 8, 16);
|
||||
}
|
||||
|
||||
int AudioDecoderG722Impl::PacketDuration(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
// 1/2 encoded byte per sample per channel.
|
||||
return static_cast<int>(2 * encoded_len / Channels());
|
||||
}
|
||||
|
||||
int AudioDecoderG722Impl::PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return PacketDuration(encoded, encoded_len);
|
||||
}
|
||||
|
||||
int AudioDecoderG722Impl::SampleRateHz() const {
|
||||
return 16000;
|
||||
}
|
||||
|
||||
size_t AudioDecoderG722Impl::Channels() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
AudioDecoderG722StereoImpl::AudioDecoderG722StereoImpl() {
|
||||
WebRtcG722_CreateDecoder(&dec_state_left_);
|
||||
WebRtcG722_CreateDecoder(&dec_state_right_);
|
||||
WebRtcG722_DecoderInit(dec_state_left_);
|
||||
WebRtcG722_DecoderInit(dec_state_right_);
|
||||
}
|
||||
|
||||
AudioDecoderG722StereoImpl::~AudioDecoderG722StereoImpl() {
|
||||
WebRtcG722_FreeDecoder(dec_state_left_);
|
||||
WebRtcG722_FreeDecoder(dec_state_right_);
|
||||
}
|
||||
|
||||
int AudioDecoderG722StereoImpl::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz);
|
||||
// Adjust the encoded length down to ensure the same number of samples in each
|
||||
// channel.
|
||||
const size_t encoded_len_adjusted = PacketDuration(encoded, encoded_len) *
|
||||
Channels() /
|
||||
2; // 1/2 byte per sample per channel
|
||||
int16_t temp_type = 1; // Default is speech.
|
||||
// De-interleave the bit-stream into two separate payloads.
|
||||
uint8_t* encoded_deinterleaved = new uint8_t[encoded_len_adjusted];
|
||||
SplitStereoPacket(encoded, encoded_len_adjusted, encoded_deinterleaved);
|
||||
// Decode left and right.
|
||||
size_t decoded_len =
|
||||
WebRtcG722_Decode(dec_state_left_, encoded_deinterleaved,
|
||||
encoded_len_adjusted / 2, decoded, &temp_type);
|
||||
size_t ret = WebRtcG722_Decode(
|
||||
dec_state_right_, &encoded_deinterleaved[encoded_len_adjusted / 2],
|
||||
encoded_len_adjusted / 2, &decoded[decoded_len], &temp_type);
|
||||
if (ret == decoded_len) {
|
||||
ret += decoded_len; // Return total number of samples.
|
||||
// Interleave output.
|
||||
for (size_t k = ret / 2; k < ret; k++) {
|
||||
int16_t temp = decoded[k];
|
||||
memmove(&decoded[2 * k - ret + 2], &decoded[2 * k - ret + 1],
|
||||
(ret - k - 1) * sizeof(int16_t));
|
||||
decoded[2 * k - ret + 1] = temp;
|
||||
}
|
||||
}
|
||||
*speech_type = ConvertSpeechType(temp_type);
|
||||
delete[] encoded_deinterleaved;
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
int AudioDecoderG722StereoImpl::PacketDuration(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
// 1/2 encoded byte per sample per channel. Make sure the length represents
|
||||
// an equal number of bytes per channel. Otherwise, we cannot de-interleave
|
||||
// the encoded data later.
|
||||
return static_cast<int>(2 * (encoded_len / Channels()));
|
||||
}
|
||||
|
||||
int AudioDecoderG722StereoImpl::SampleRateHz() const {
|
||||
return 16000;
|
||||
}
|
||||
|
||||
size_t AudioDecoderG722StereoImpl::Channels() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
void AudioDecoderG722StereoImpl::Reset() {
|
||||
WebRtcG722_DecoderInit(dec_state_left_);
|
||||
WebRtcG722_DecoderInit(dec_state_right_);
|
||||
}
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoderG722StereoImpl::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
return LegacyEncodedAudioFrame::SplitBySamples(this, std::move(payload),
|
||||
timestamp, 2 * 8, 16);
|
||||
}
|
||||
|
||||
// Split the stereo packet and place left and right channel after each other
|
||||
// in the output array.
|
||||
void AudioDecoderG722StereoImpl::SplitStereoPacket(
|
||||
const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
uint8_t* encoded_deinterleaved) {
|
||||
// Regroup the 4 bits/sample so |l1 l2| |r1 r2| |l3 l4| |r3 r4| ...,
|
||||
// where "lx" is 4 bits representing left sample number x, and "rx" right
|
||||
// sample. Two samples fit in one byte, represented with |...|.
|
||||
for (size_t i = 0; i + 1 < encoded_len; i += 2) {
|
||||
uint8_t right_byte = ((encoded[i] & 0x0F) << 4) + (encoded[i + 1] & 0x0F);
|
||||
encoded_deinterleaved[i] = (encoded[i] & 0xF0) + (encoded[i + 1] >> 4);
|
||||
encoded_deinterleaved[i + 1] = right_byte;
|
||||
}
|
||||
|
||||
// Move one byte representing right channel each loop, and place it at the
|
||||
// end of the bytestream vector. After looping the data is reordered to:
|
||||
// |l1 l2| |l3 l4| ... |l(N-1) lN| |r1 r2| |r3 r4| ... |r(N-1) r(N)|,
|
||||
// where N is the total number of samples.
|
||||
for (size_t i = 0; i < encoded_len / 2; i++) {
|
||||
uint8_t right_byte = encoded_deinterleaved[i + 1];
|
||||
memmove(&encoded_deinterleaved[i + 1], &encoded_deinterleaved[i + 2],
|
||||
encoded_len - i - 2);
|
||||
encoded_deinterleaved[encoded_len - 1] = right_byte;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
|
||||
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
|
||||
typedef struct WebRtcG722DecInst G722DecInst;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDecoderG722Impl final : public AudioDecoder {
|
||||
public:
|
||||
AudioDecoderG722Impl();
|
||||
~AudioDecoderG722Impl() override;
|
||||
|
||||
AudioDecoderG722Impl(const AudioDecoderG722Impl&) = delete;
|
||||
AudioDecoderG722Impl& operator=(const AudioDecoderG722Impl&) = delete;
|
||||
|
||||
bool HasDecodePlc() const override;
|
||||
void Reset() override;
|
||||
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp) override;
|
||||
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
|
||||
int PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const override;
|
||||
int SampleRateHz() const override;
|
||||
size_t Channels() const override;
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
private:
|
||||
G722DecInst* dec_state_;
|
||||
};
|
||||
|
||||
class AudioDecoderG722StereoImpl final : public AudioDecoder {
|
||||
public:
|
||||
AudioDecoderG722StereoImpl();
|
||||
~AudioDecoderG722StereoImpl() override;
|
||||
|
||||
AudioDecoderG722StereoImpl(const AudioDecoderG722StereoImpl&) = delete;
|
||||
AudioDecoderG722StereoImpl& operator=(const AudioDecoderG722StereoImpl&) =
|
||||
delete;
|
||||
|
||||
void Reset() override;
|
||||
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp) override;
|
||||
int SampleRateHz() const override;
|
||||
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
|
||||
size_t Channels() const override;
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
private:
|
||||
// Splits the stereo-interleaved payload in `encoded` into separate payloads
|
||||
// for left and right channels. The separated payloads are written to
|
||||
// `encoded_deinterleaved`, which must hold at least `encoded_len` samples.
|
||||
// The left channel starts at offset 0, while the right channel starts at
|
||||
// offset encoded_len / 2 into `encoded_deinterleaved`.
|
||||
void SplitStereoPacket(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
uint8_t* encoded_deinterleaved);
|
||||
|
||||
G722DecInst* dec_state_left_;
|
||||
G722DecInst* dec_state_right_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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 "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "modules/audio_coding/codecs/g722/g722_interface.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const size_t kSampleRateHz = 16000;
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioEncoderG722Impl::AudioEncoderG722Impl(const AudioEncoderG722Config& config,
|
||||
int payload_type)
|
||||
: num_channels_(config.num_channels),
|
||||
payload_type_(payload_type),
|
||||
num_10ms_frames_per_packet_(
|
||||
static_cast<size_t>(config.frame_size_ms / 10)),
|
||||
num_10ms_frames_buffered_(0),
|
||||
first_timestamp_in_buffer_(0),
|
||||
encoders_(new EncoderState[num_channels_]),
|
||||
interleave_buffer_(2 * num_channels_) {
|
||||
RTC_CHECK(config.IsOk());
|
||||
const size_t samples_per_channel =
|
||||
kSampleRateHz / 100 * num_10ms_frames_per_packet_;
|
||||
for (size_t i = 0; i < num_channels_; ++i) {
|
||||
encoders_[i].speech_buffer.reset(new int16_t[samples_per_channel]);
|
||||
encoders_[i].encoded_buffer.SetSize(samples_per_channel / 2);
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
AudioEncoderG722Impl::~AudioEncoderG722Impl() = default;
|
||||
|
||||
int AudioEncoderG722Impl::SampleRateHz() const {
|
||||
return kSampleRateHz;
|
||||
}
|
||||
|
||||
size_t AudioEncoderG722Impl::NumChannels() const {
|
||||
return num_channels_;
|
||||
}
|
||||
|
||||
int AudioEncoderG722Impl::RtpTimestampRateHz() const {
|
||||
// The RTP timestamp rate for G.722 is 8000 Hz, even though it is a 16 kHz
|
||||
// codec.
|
||||
return kSampleRateHz / 2;
|
||||
}
|
||||
|
||||
size_t AudioEncoderG722Impl::Num10MsFramesInNextPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
size_t AudioEncoderG722Impl::Max10MsFramesInAPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
int AudioEncoderG722Impl::GetTargetBitrate() const {
|
||||
// 4 bits/sample, 16000 samples/s/channel.
|
||||
return static_cast<int>(64000 * NumChannels());
|
||||
}
|
||||
|
||||
void AudioEncoderG722Impl::Reset() {
|
||||
num_10ms_frames_buffered_ = 0;
|
||||
for (size_t i = 0; i < num_channels_; ++i)
|
||||
RTC_CHECK_EQ(0, WebRtcG722_EncoderInit(encoders_[i].encoder));
|
||||
}
|
||||
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>>
|
||||
AudioEncoderG722Impl::GetFrameLengthRange() const {
|
||||
return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
|
||||
TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderG722Impl::EncodeImpl(
|
||||
uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) {
|
||||
if (num_10ms_frames_buffered_ == 0)
|
||||
first_timestamp_in_buffer_ = rtp_timestamp;
|
||||
|
||||
// Deinterleave samples and save them in each channel's buffer.
|
||||
const size_t start = kSampleRateHz / 100 * num_10ms_frames_buffered_;
|
||||
for (size_t i = 0; i < kSampleRateHz / 100; ++i)
|
||||
for (size_t j = 0; j < num_channels_; ++j)
|
||||
encoders_[j].speech_buffer[start + i] = audio[i * num_channels_ + j];
|
||||
|
||||
// If we don't yet have enough samples for a packet, we're done for now.
|
||||
if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) {
|
||||
return EncodedInfo();
|
||||
}
|
||||
|
||||
// Encode each channel separately.
|
||||
RTC_CHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
|
||||
num_10ms_frames_buffered_ = 0;
|
||||
const size_t samples_per_channel = SamplesPerChannel();
|
||||
for (size_t i = 0; i < num_channels_; ++i) {
|
||||
const size_t bytes_encoded = WebRtcG722_Encode(
|
||||
encoders_[i].encoder, encoders_[i].speech_buffer.get(),
|
||||
samples_per_channel, encoders_[i].encoded_buffer.data());
|
||||
RTC_CHECK_EQ(bytes_encoded, samples_per_channel / 2);
|
||||
}
|
||||
|
||||
const size_t bytes_to_encode = samples_per_channel / 2 * num_channels_;
|
||||
EncodedInfo info;
|
||||
info.encoded_bytes = encoded->AppendData(
|
||||
bytes_to_encode, [&](rtc::ArrayView<uint8_t> encoded) {
|
||||
// Interleave the encoded bytes of the different channels. Each separate
|
||||
// channel and the interleaved stream encodes two samples per byte, most
|
||||
// significant half first.
|
||||
for (size_t i = 0; i < samples_per_channel / 2; ++i) {
|
||||
for (size_t j = 0; j < num_channels_; ++j) {
|
||||
uint8_t two_samples = encoders_[j].encoded_buffer.data()[i];
|
||||
interleave_buffer_.data()[j] = two_samples >> 4;
|
||||
interleave_buffer_.data()[num_channels_ + j] = two_samples & 0xf;
|
||||
}
|
||||
for (size_t j = 0; j < num_channels_; ++j)
|
||||
encoded[i * num_channels_ + j] =
|
||||
interleave_buffer_.data()[2 * j] << 4 |
|
||||
interleave_buffer_.data()[2 * j + 1];
|
||||
}
|
||||
|
||||
return bytes_to_encode;
|
||||
});
|
||||
info.encoded_timestamp = first_timestamp_in_buffer_;
|
||||
info.payload_type = payload_type_;
|
||||
info.encoder_type = CodecType::kG722;
|
||||
return info;
|
||||
}
|
||||
|
||||
AudioEncoderG722Impl::EncoderState::EncoderState() {
|
||||
RTC_CHECK_EQ(0, WebRtcG722_CreateEncoder(&encoder));
|
||||
}
|
||||
|
||||
AudioEncoderG722Impl::EncoderState::~EncoderState() {
|
||||
RTC_CHECK_EQ(0, WebRtcG722_FreeEncoder(encoder));
|
||||
}
|
||||
|
||||
size_t AudioEncoderG722Impl::SamplesPerChannel() const {
|
||||
return kSampleRateHz / 100 * num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/g722/audio_encoder_g722_config.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "modules/audio_coding/codecs/g722/g722_interface.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioEncoderG722Impl final : public AudioEncoder {
|
||||
public:
|
||||
AudioEncoderG722Impl(const AudioEncoderG722Config& config, int payload_type);
|
||||
~AudioEncoderG722Impl() override;
|
||||
|
||||
AudioEncoderG722Impl(const AudioEncoderG722Impl&) = delete;
|
||||
AudioEncoderG722Impl& operator=(const AudioEncoderG722Impl&) = delete;
|
||||
|
||||
int SampleRateHz() const override;
|
||||
size_t NumChannels() const override;
|
||||
int RtpTimestampRateHz() const override;
|
||||
size_t Num10MsFramesInNextPacket() const override;
|
||||
size_t Max10MsFramesInAPacket() const override;
|
||||
int GetTargetBitrate() const override;
|
||||
void Reset() override;
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||
const override;
|
||||
|
||||
protected:
|
||||
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) override;
|
||||
|
||||
private:
|
||||
// The encoder state for one channel.
|
||||
struct EncoderState {
|
||||
G722EncInst* encoder;
|
||||
std::unique_ptr<int16_t[]> speech_buffer; // Queued up for encoding.
|
||||
rtc::Buffer encoded_buffer; // Already encoded.
|
||||
EncoderState();
|
||||
~EncoderState();
|
||||
};
|
||||
|
||||
size_t SamplesPerChannel() const;
|
||||
|
||||
const size_t num_channels_;
|
||||
const int payload_type_;
|
||||
const size_t num_10ms_frames_per_packet_;
|
||||
size_t num_10ms_frames_buffered_;
|
||||
uint32_t first_timestamp_in_buffer_;
|
||||
const std::unique_ptr<EncoderState[]> encoders_;
|
||||
rtc::Buffer interleave_buffer_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_G722_AUDIO_ENCODER_G722_H_
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/g722/g722_interface.h"
|
||||
#include "modules/third_party/g722/g722_enc_dec.h"
|
||||
|
||||
int16_t WebRtcG722_CreateEncoder(G722EncInst **G722enc_inst)
|
||||
{
|
||||
*G722enc_inst=(G722EncInst*)malloc(sizeof(G722EncoderState));
|
||||
if (*G722enc_inst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcG722_EncoderInit(G722EncInst *G722enc_inst)
|
||||
{
|
||||
// Create and/or reset the G.722 encoder
|
||||
// Bitrate 64 kbps and wideband mode (2)
|
||||
G722enc_inst = (G722EncInst *) WebRtc_g722_encode_init(
|
||||
(G722EncoderState*) G722enc_inst, 64000, 2);
|
||||
if (G722enc_inst == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int WebRtcG722_FreeEncoder(G722EncInst *G722enc_inst)
|
||||
{
|
||||
// Free encoder memory
|
||||
return WebRtc_g722_encode_release((G722EncoderState*) G722enc_inst);
|
||||
}
|
||||
|
||||
size_t WebRtcG722_Encode(G722EncInst *G722enc_inst,
|
||||
const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded)
|
||||
{
|
||||
unsigned char *codechar = (unsigned char*) encoded;
|
||||
// Encode the input speech vector
|
||||
return WebRtc_g722_encode((G722EncoderState*) G722enc_inst, codechar,
|
||||
speechIn, len);
|
||||
}
|
||||
|
||||
int16_t WebRtcG722_CreateDecoder(G722DecInst **G722dec_inst)
|
||||
{
|
||||
*G722dec_inst=(G722DecInst*)malloc(sizeof(G722DecoderState));
|
||||
if (*G722dec_inst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcG722_DecoderInit(G722DecInst* inst) {
|
||||
// Create and/or reset the G.722 decoder
|
||||
// Bitrate 64 kbps and wideband mode (2)
|
||||
WebRtc_g722_decode_init((G722DecoderState*)inst, 64000, 2);
|
||||
}
|
||||
|
||||
int WebRtcG722_FreeDecoder(G722DecInst *G722dec_inst)
|
||||
{
|
||||
// Free encoder memory
|
||||
return WebRtc_g722_decode_release((G722DecoderState*) G722dec_inst);
|
||||
}
|
||||
|
||||
size_t WebRtcG722_Decode(G722DecInst *G722dec_inst,
|
||||
const uint8_t *encoded,
|
||||
size_t len,
|
||||
int16_t *decoded,
|
||||
int16_t *speechType)
|
||||
{
|
||||
// Decode the G.722 encoder stream
|
||||
*speechType=G722_WEBRTC_SPEECH;
|
||||
return WebRtc_g722_decode((G722DecoderState*) G722dec_inst, decoded,
|
||||
encoded, len);
|
||||
}
|
||||
|
||||
int16_t WebRtcG722_Version(char *versionStr, short len)
|
||||
{
|
||||
// Get version string
|
||||
char version[30] = "2.0.0\n";
|
||||
if (strlen(version) < (unsigned int)len)
|
||||
{
|
||||
strcpy(versionStr, version);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Solution to support multiple instances
|
||||
*/
|
||||
|
||||
typedef struct WebRtcG722EncInst G722EncInst;
|
||||
typedef struct WebRtcG722DecInst G722DecInst;
|
||||
|
||||
/*
|
||||
* Comfort noise constants
|
||||
*/
|
||||
|
||||
#define G722_WEBRTC_SPEECH 1
|
||||
#define G722_WEBRTC_CNG 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_CreateEncoder(...)
|
||||
*
|
||||
* Create memory used for G722 encoder
|
||||
*
|
||||
* Input:
|
||||
* - G722enc_inst : G722 instance for encoder
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
int16_t WebRtcG722_CreateEncoder(G722EncInst** G722enc_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_EncoderInit(...)
|
||||
*
|
||||
* This function initializes a G722 instance
|
||||
*
|
||||
* Input:
|
||||
* - G722enc_inst : G722 instance, i.e. the user that should receive
|
||||
* be initialized
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcG722_EncoderInit(G722EncInst* G722enc_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_FreeEncoder(...)
|
||||
*
|
||||
* Free the memory used for G722 encoder
|
||||
*
|
||||
* Input:
|
||||
* - G722enc_inst : G722 instance for encoder
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
int WebRtcG722_FreeEncoder(G722EncInst* G722enc_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_Encode(...)
|
||||
*
|
||||
* This function encodes G722 encoded data.
|
||||
*
|
||||
* Input:
|
||||
* - G722enc_inst : G722 instance, i.e. the user that should encode
|
||||
* a packet
|
||||
* - speechIn : Input speech vector
|
||||
* - len : Samples in speechIn
|
||||
*
|
||||
* Output:
|
||||
* - encoded : The encoded data vector
|
||||
*
|
||||
* Return value : Length (in bytes) of coded data
|
||||
*/
|
||||
|
||||
size_t WebRtcG722_Encode(G722EncInst* G722enc_inst,
|
||||
const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_CreateDecoder(...)
|
||||
*
|
||||
* Create memory used for G722 encoder
|
||||
*
|
||||
* Input:
|
||||
* - G722dec_inst : G722 instance for decoder
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
int16_t WebRtcG722_CreateDecoder(G722DecInst** G722dec_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_DecoderInit(...)
|
||||
*
|
||||
* This function initializes a G722 instance
|
||||
*
|
||||
* Input:
|
||||
* - inst : G722 instance
|
||||
*/
|
||||
|
||||
void WebRtcG722_DecoderInit(G722DecInst* inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_FreeDecoder(...)
|
||||
*
|
||||
* Free the memory used for G722 decoder
|
||||
*
|
||||
* Input:
|
||||
* - G722dec_inst : G722 instance for decoder
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int WebRtcG722_FreeDecoder(G722DecInst* G722dec_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_Decode(...)
|
||||
*
|
||||
* This function decodes a packet with G729 frame(s). Output speech length
|
||||
* will be a multiple of 80 samples (80*frames/packet).
|
||||
*
|
||||
* Input:
|
||||
* - G722dec_inst : G722 instance, i.e. the user that should decode
|
||||
* a packet
|
||||
* - encoded : Encoded G722 frame(s)
|
||||
* - len : Bytes in encoded vector
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The decoded vector
|
||||
* - speechType : 1 normal, 2 CNG (Since G722 does not have its own
|
||||
* DTX/CNG scheme it should always return 1)
|
||||
*
|
||||
* Return value : Samples in decoded vector
|
||||
*/
|
||||
|
||||
size_t WebRtcG722_Decode(G722DecInst* G722dec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcG722_Version(...)
|
||||
*
|
||||
* Get a string with the current version of the codec
|
||||
*/
|
||||
|
||||
int16_t WebRtcG722_Version(char* versionStr, short len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_ */
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* testG722.cpp : Defines the entry point for the console application.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* include API */
|
||||
#include "modules/audio_coding/codecs/g722/g722_interface.h"
|
||||
|
||||
/* Runtime statistics */
|
||||
#include <time.h>
|
||||
#define CLOCKS_PER_SEC_G722 100000
|
||||
|
||||
// Forward declaration
|
||||
typedef struct WebRtcG722EncInst G722EncInst;
|
||||
typedef struct WebRtcG722DecInst G722DecInst;
|
||||
|
||||
/* function for reading audio data from PCM file */
|
||||
bool readframe(int16_t* data, FILE* inp, size_t length) {
|
||||
size_t rlen = fread(data, sizeof(int16_t), length, inp);
|
||||
if (rlen >= length)
|
||||
return false;
|
||||
memset(data + rlen, 0, (length - rlen) * sizeof(int16_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
char inname[60], outbit[40], outname[40];
|
||||
FILE *inp, *outbitp, *outp;
|
||||
|
||||
int framecnt;
|
||||
bool endfile;
|
||||
size_t framelength = 160;
|
||||
G722EncInst* G722enc_inst;
|
||||
G722DecInst* G722dec_inst;
|
||||
|
||||
/* Runtime statistics */
|
||||
double starttime;
|
||||
double runtime = 0;
|
||||
double length_file;
|
||||
|
||||
size_t stream_len = 0;
|
||||
int16_t shortdata[960];
|
||||
int16_t decoded[960];
|
||||
uint8_t streamdata[80 * 6];
|
||||
int16_t speechType[1];
|
||||
|
||||
/* handling wrong input arguments in the command line */
|
||||
if (argc != 5) {
|
||||
printf("\n\nWrong number of arguments or flag values.\n\n");
|
||||
|
||||
printf("\n");
|
||||
printf("Usage:\n\n");
|
||||
printf("./testG722.exe framelength infile outbitfile outspeechfile \n\n");
|
||||
printf("with:\n");
|
||||
printf("framelength : Framelength in samples.\n\n");
|
||||
printf("infile : Normal speech input file\n\n");
|
||||
printf("outbitfile : Bitstream output file\n\n");
|
||||
printf("outspeechfile: Speech output file\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Get frame length */
|
||||
int framelength_int = atoi(argv[1]);
|
||||
if (framelength_int < 0) {
|
||||
printf(" G.722: Invalid framelength %d.\n", framelength_int);
|
||||
exit(1);
|
||||
}
|
||||
framelength = static_cast<size_t>(framelength_int);
|
||||
|
||||
/* Get Input and Output files */
|
||||
sscanf(argv[2], "%s", inname);
|
||||
sscanf(argv[3], "%s", outbit);
|
||||
sscanf(argv[4], "%s", outname);
|
||||
|
||||
if ((inp = fopen(inname, "rb")) == NULL) {
|
||||
printf(" G.722: Cannot read file %s.\n", inname);
|
||||
exit(1);
|
||||
}
|
||||
if ((outbitp = fopen(outbit, "wb")) == NULL) {
|
||||
printf(" G.722: Cannot write file %s.\n", outbit);
|
||||
exit(1);
|
||||
}
|
||||
if ((outp = fopen(outname, "wb")) == NULL) {
|
||||
printf(" G.722: Cannot write file %s.\n", outname);
|
||||
exit(1);
|
||||
}
|
||||
printf("\nInput:%s\nOutput bitstream:%s\nOutput:%s\n", inname, outbit,
|
||||
outname);
|
||||
|
||||
/* Create and init */
|
||||
WebRtcG722_CreateEncoder((G722EncInst**)&G722enc_inst);
|
||||
WebRtcG722_CreateDecoder((G722DecInst**)&G722dec_inst);
|
||||
WebRtcG722_EncoderInit((G722EncInst*)G722enc_inst);
|
||||
WebRtcG722_DecoderInit((G722DecInst*)G722dec_inst);
|
||||
|
||||
/* Initialize encoder and decoder */
|
||||
framecnt = 0;
|
||||
endfile = false;
|
||||
while (!endfile) {
|
||||
framecnt++;
|
||||
|
||||
/* Read speech block */
|
||||
endfile = readframe(shortdata, inp, framelength);
|
||||
|
||||
/* Start clock before call to encoder and decoder */
|
||||
starttime = clock() / (double)CLOCKS_PER_SEC_G722;
|
||||
|
||||
/* G.722 encoding + decoding */
|
||||
stream_len = WebRtcG722_Encode((G722EncInst*)G722enc_inst, shortdata,
|
||||
framelength, streamdata);
|
||||
WebRtcG722_Decode(G722dec_inst, streamdata, stream_len, decoded,
|
||||
speechType);
|
||||
|
||||
/* Stop clock after call to encoder and decoder */
|
||||
runtime += (double)((clock() / (double)CLOCKS_PER_SEC_G722) - starttime);
|
||||
|
||||
/* Write coded bits to file */
|
||||
if (fwrite(streamdata, sizeof(short), stream_len / 2, outbitp) !=
|
||||
stream_len / 2) {
|
||||
return -1;
|
||||
}
|
||||
/* Write coded speech to file */
|
||||
if (fwrite(decoded, sizeof(short), framelength, outp) != framelength) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
WebRtcG722_FreeEncoder((G722EncInst*)G722enc_inst);
|
||||
WebRtcG722_FreeDecoder((G722DecInst*)G722dec_inst);
|
||||
|
||||
length_file = ((double)framecnt * (double)framelength / 16000);
|
||||
printf("\n\nLength of speech file: %.1f s\n", length_file);
|
||||
printf("Time to run G.722: %.2f s (%.2f %% of realtime)\n\n", runtime,
|
||||
(100 * runtime / length_file));
|
||||
printf("---------------------END----------------------\n");
|
||||
|
||||
fclose(inp);
|
||||
fclose(outbitp);
|
||||
fclose(outp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AbsQuant.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/abs_quant.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* predictive noise shaping encoding of scaled start state
|
||||
* (subrutine for WebRtcIlbcfix_StateSearch)
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_AbsQuant(
|
||||
IlbcEncoder *iLBCenc_inst,
|
||||
/* (i) Encoder instance */
|
||||
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
|
||||
and idxVec, uses state_first as
|
||||
input) */
|
||||
int16_t *in, /* (i) vector to encode */
|
||||
int16_t *weightDenum /* (i) denominator of synthesis filter */
|
||||
) {
|
||||
int16_t *syntOut;
|
||||
size_t quantLen[2];
|
||||
|
||||
/* Stack based */
|
||||
int16_t syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS];
|
||||
int16_t in_weightedVec[STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
|
||||
int16_t *in_weighted = &in_weightedVec[LPC_FILTERORDER];
|
||||
|
||||
/* Initialize the buffers */
|
||||
WebRtcSpl_MemSetW16(syntOutBuf, 0, LPC_FILTERORDER+STATE_SHORT_LEN_30MS);
|
||||
syntOut = &syntOutBuf[LPC_FILTERORDER];
|
||||
/* Start with zero state */
|
||||
WebRtcSpl_MemSetW16(in_weightedVec, 0, LPC_FILTERORDER);
|
||||
|
||||
/* Perform the quantization loop in two sections of length quantLen[i],
|
||||
where the perceptual weighting filter is updated at the subframe
|
||||
border */
|
||||
|
||||
if (iLBC_encbits->state_first) {
|
||||
quantLen[0]=SUBL;
|
||||
quantLen[1]=iLBCenc_inst->state_short_len-SUBL;
|
||||
} else {
|
||||
quantLen[0]=iLBCenc_inst->state_short_len-SUBL;
|
||||
quantLen[1]=SUBL;
|
||||
}
|
||||
|
||||
/* Calculate the weighted residual, switch perceptual weighting
|
||||
filter at the subframe border */
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
in, in_weighted,
|
||||
weightDenum, LPC_FILTERORDER+1, quantLen[0]);
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
&in[quantLen[0]], &in_weighted[quantLen[0]],
|
||||
&weightDenum[LPC_FILTERORDER+1], LPC_FILTERORDER+1, quantLen[1]);
|
||||
|
||||
WebRtcIlbcfix_AbsQuantLoop(
|
||||
syntOut,
|
||||
in_weighted,
|
||||
weightDenum,
|
||||
quantLen,
|
||||
iLBC_encbits->idxVec);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AbsQuant.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* predictive noise shaping encoding of scaled start state
|
||||
* (subrutine for WebRtcIlbcfix_StateSearch)
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_AbsQuant(
|
||||
IlbcEncoder* iLBCenc_inst,
|
||||
/* (i) Encoder instance */
|
||||
iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
|
||||
and idxVec, uses state_first as
|
||||
input) */
|
||||
int16_t* in, /* (i) vector to encode */
|
||||
int16_t* weightDenum /* (i) denominator of synthesis filter */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AbsQuantLoop.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/sort_sq.h"
|
||||
|
||||
void WebRtcIlbcfix_AbsQuantLoop(int16_t *syntOutIN, int16_t *in_weightedIN,
|
||||
int16_t *weightDenumIN, size_t *quantLenIN,
|
||||
int16_t *idxVecIN ) {
|
||||
size_t k1, k2;
|
||||
int16_t index;
|
||||
int32_t toQW32;
|
||||
int32_t toQ32;
|
||||
int16_t tmp16a;
|
||||
int16_t xq;
|
||||
|
||||
int16_t *syntOut = syntOutIN;
|
||||
int16_t *in_weighted = in_weightedIN;
|
||||
int16_t *weightDenum = weightDenumIN;
|
||||
size_t *quantLen = quantLenIN;
|
||||
int16_t *idxVec = idxVecIN;
|
||||
|
||||
for(k1=0;k1<2;k1++) {
|
||||
for(k2=0;k2<quantLen[k1];k2++){
|
||||
|
||||
/* Filter to get the predicted value */
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
syntOut, syntOut,
|
||||
weightDenum, LPC_FILTERORDER+1, 1);
|
||||
|
||||
/* the quantizer */
|
||||
toQW32 = (int32_t)(*in_weighted) - (int32_t)(*syntOut);
|
||||
|
||||
toQ32 = (((int32_t)toQW32)<<2);
|
||||
|
||||
if (toQ32 > 32767) {
|
||||
toQ32 = (int32_t) 32767;
|
||||
} else if (toQ32 < -32768) {
|
||||
toQ32 = (int32_t) -32768;
|
||||
}
|
||||
|
||||
/* Quantize the state */
|
||||
if (toQW32<(-7577)) {
|
||||
/* To prevent negative overflow */
|
||||
index=0;
|
||||
} else if (toQW32>8151) {
|
||||
/* To prevent positive overflow */
|
||||
index=7;
|
||||
} else {
|
||||
/* Find the best quantization index
|
||||
(state_sq3Tbl is in Q13 and toQ is in Q11)
|
||||
*/
|
||||
WebRtcIlbcfix_SortSq(&xq, &index,
|
||||
(int16_t)toQ32,
|
||||
WebRtcIlbcfix_kStateSq3, 8);
|
||||
}
|
||||
|
||||
/* Store selected index */
|
||||
(*idxVec++) = index;
|
||||
|
||||
/* Compute decoded sample and update of the prediction filter */
|
||||
tmp16a = ((WebRtcIlbcfix_kStateSq3[index] + 2 ) >> 2);
|
||||
|
||||
*syntOut = (int16_t) (tmp16a + (int32_t)(*in_weighted) - toQW32);
|
||||
|
||||
syntOut++; in_weighted++;
|
||||
}
|
||||
/* Update perceptual weighting filter at subframe border */
|
||||
weightDenum += 11;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AbsQuantLoop.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* predictive noise shaping encoding of scaled start state
|
||||
* (subrutine for WebRtcIlbcfix_StateSearch)
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_AbsQuantLoop(int16_t* syntOutIN,
|
||||
int16_t* in_weightedIN,
|
||||
int16_t* weightDenumIN,
|
||||
size_t* quantLenIN,
|
||||
int16_t* idxVecIN);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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 "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/ilbc.h"
|
||||
#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioDecoderIlbcImpl::AudioDecoderIlbcImpl() {
|
||||
WebRtcIlbcfix_DecoderCreate(&dec_state_);
|
||||
WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
|
||||
}
|
||||
|
||||
AudioDecoderIlbcImpl::~AudioDecoderIlbcImpl() {
|
||||
WebRtcIlbcfix_DecoderFree(dec_state_);
|
||||
}
|
||||
|
||||
bool AudioDecoderIlbcImpl::HasDecodePlc() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
int AudioDecoderIlbcImpl::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(sample_rate_hz, 8000);
|
||||
int16_t temp_type = 1; // Default is speech.
|
||||
int ret = WebRtcIlbcfix_Decode(dec_state_, encoded, encoded_len, decoded,
|
||||
&temp_type);
|
||||
*speech_type = ConvertSpeechType(temp_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t AudioDecoderIlbcImpl::DecodePlc(size_t num_frames, int16_t* decoded) {
|
||||
return WebRtcIlbcfix_NetEqPlc(dec_state_, decoded, num_frames);
|
||||
}
|
||||
|
||||
void AudioDecoderIlbcImpl::Reset() {
|
||||
WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
|
||||
}
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoderIlbcImpl::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
std::vector<ParseResult> results;
|
||||
size_t bytes_per_frame;
|
||||
int timestamps_per_frame;
|
||||
if (payload.size() >= 950) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "AudioDecoderIlbcImpl::ParsePayload: Payload too large";
|
||||
return results;
|
||||
}
|
||||
if (payload.size() % 38 == 0) {
|
||||
// 20 ms frames.
|
||||
bytes_per_frame = 38;
|
||||
timestamps_per_frame = 160;
|
||||
} else if (payload.size() % 50 == 0) {
|
||||
// 30 ms frames.
|
||||
bytes_per_frame = 50;
|
||||
timestamps_per_frame = 240;
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "AudioDecoderIlbcImpl::ParsePayload: Invalid payload";
|
||||
return results;
|
||||
}
|
||||
|
||||
RTC_DCHECK_EQ(0, payload.size() % bytes_per_frame);
|
||||
if (payload.size() == bytes_per_frame) {
|
||||
std::unique_ptr<EncodedAudioFrame> frame(
|
||||
new LegacyEncodedAudioFrame(this, std::move(payload)));
|
||||
results.emplace_back(timestamp, 0, std::move(frame));
|
||||
} else {
|
||||
size_t byte_offset;
|
||||
uint32_t timestamp_offset;
|
||||
for (byte_offset = 0, timestamp_offset = 0; byte_offset < payload.size();
|
||||
byte_offset += bytes_per_frame,
|
||||
timestamp_offset += timestamps_per_frame) {
|
||||
std::unique_ptr<EncodedAudioFrame> frame(new LegacyEncodedAudioFrame(
|
||||
this, rtc::Buffer(payload.data() + byte_offset, bytes_per_frame)));
|
||||
results.emplace_back(timestamp + timestamp_offset, 0, std::move(frame));
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
int AudioDecoderIlbcImpl::SampleRateHz() const {
|
||||
return 8000;
|
||||
}
|
||||
|
||||
size_t AudioDecoderIlbcImpl::Channels() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
|
||||
typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDecoderIlbcImpl final : public AudioDecoder {
|
||||
public:
|
||||
AudioDecoderIlbcImpl();
|
||||
~AudioDecoderIlbcImpl() override;
|
||||
|
||||
AudioDecoderIlbcImpl(const AudioDecoderIlbcImpl&) = delete;
|
||||
AudioDecoderIlbcImpl& operator=(const AudioDecoderIlbcImpl&) = delete;
|
||||
|
||||
bool HasDecodePlc() const override;
|
||||
size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
|
||||
void Reset() override;
|
||||
std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp) override;
|
||||
int SampleRateHz() const override;
|
||||
size_t Channels() const override;
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
private:
|
||||
IlbcDecoderInstance* dec_state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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 "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/ilbc.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kSampleRateHz = 8000;
|
||||
|
||||
int GetIlbcBitrate(int ptime) {
|
||||
switch (ptime) {
|
||||
case 20:
|
||||
case 40:
|
||||
// 38 bytes per frame of 20 ms => 15200 bits/s.
|
||||
return 15200;
|
||||
case 30:
|
||||
case 60:
|
||||
// 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
|
||||
return 13333;
|
||||
default:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config,
|
||||
int payload_type)
|
||||
: frame_size_ms_(config.frame_size_ms),
|
||||
payload_type_(payload_type),
|
||||
num_10ms_frames_per_packet_(
|
||||
static_cast<size_t>(config.frame_size_ms / 10)),
|
||||
encoder_(nullptr) {
|
||||
RTC_CHECK(config.IsOk());
|
||||
Reset();
|
||||
}
|
||||
|
||||
AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
|
||||
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
|
||||
}
|
||||
|
||||
int AudioEncoderIlbcImpl::SampleRateHz() const {
|
||||
return kSampleRateHz;
|
||||
}
|
||||
|
||||
size_t AudioEncoderIlbcImpl::NumChannels() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t AudioEncoderIlbcImpl::Num10MsFramesInNextPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
size_t AudioEncoderIlbcImpl::Max10MsFramesInAPacket() const {
|
||||
return num_10ms_frames_per_packet_;
|
||||
}
|
||||
|
||||
int AudioEncoderIlbcImpl::GetTargetBitrate() const {
|
||||
return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) *
|
||||
10);
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoderIlbcImpl::EncodeImpl(
|
||||
uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) {
|
||||
// Save timestamp if starting a new packet.
|
||||
if (num_10ms_frames_buffered_ == 0)
|
||||
first_timestamp_in_buffer_ = rtp_timestamp;
|
||||
|
||||
// Buffer input.
|
||||
std::copy(audio.cbegin(), audio.cend(),
|
||||
input_buffer_ + kSampleRateHz / 100 * num_10ms_frames_buffered_);
|
||||
|
||||
// If we don't yet have enough buffered input for a whole packet, we're done
|
||||
// for now.
|
||||
if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) {
|
||||
return EncodedInfo();
|
||||
}
|
||||
|
||||
// Encode buffered input.
|
||||
RTC_DCHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
|
||||
num_10ms_frames_buffered_ = 0;
|
||||
size_t encoded_bytes = encoded->AppendData(
|
||||
RequiredOutputSizeBytes(), [&](rtc::ArrayView<uint8_t> encoded) {
|
||||
const int r = WebRtcIlbcfix_Encode(
|
||||
encoder_, input_buffer_,
|
||||
kSampleRateHz / 100 * num_10ms_frames_per_packet_, encoded.data());
|
||||
RTC_CHECK_GE(r, 0);
|
||||
|
||||
return static_cast<size_t>(r);
|
||||
});
|
||||
|
||||
RTC_DCHECK_EQ(encoded_bytes, RequiredOutputSizeBytes());
|
||||
|
||||
EncodedInfo info;
|
||||
info.encoded_bytes = encoded_bytes;
|
||||
info.encoded_timestamp = first_timestamp_in_buffer_;
|
||||
info.payload_type = payload_type_;
|
||||
info.encoder_type = CodecType::kIlbc;
|
||||
return info;
|
||||
}
|
||||
|
||||
void AudioEncoderIlbcImpl::Reset() {
|
||||
if (encoder_)
|
||||
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
|
||||
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
|
||||
const int encoder_frame_size_ms =
|
||||
frame_size_ms_ > 30 ? frame_size_ms_ / 2 : frame_size_ms_;
|
||||
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms));
|
||||
num_10ms_frames_buffered_ = 0;
|
||||
}
|
||||
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>>
|
||||
AudioEncoderIlbcImpl::GetFrameLengthRange() const {
|
||||
return {{TimeDelta::Millis(num_10ms_frames_per_packet_ * 10),
|
||||
TimeDelta::Millis(num_10ms_frames_per_packet_ * 10)}};
|
||||
}
|
||||
|
||||
size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const {
|
||||
switch (num_10ms_frames_per_packet_) {
|
||||
case 2:
|
||||
return 38;
|
||||
case 3:
|
||||
return 50;
|
||||
case 4:
|
||||
return 2 * 38;
|
||||
case 6:
|
||||
return 2 * 50;
|
||||
default:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/ilbc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioEncoderIlbcImpl final : public AudioEncoder {
|
||||
public:
|
||||
AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config, int payload_type);
|
||||
~AudioEncoderIlbcImpl() override;
|
||||
|
||||
AudioEncoderIlbcImpl(const AudioEncoderIlbcImpl&) = delete;
|
||||
AudioEncoderIlbcImpl& operator=(const AudioEncoderIlbcImpl&) = delete;
|
||||
|
||||
int SampleRateHz() const override;
|
||||
size_t NumChannels() const override;
|
||||
size_t Num10MsFramesInNextPacket() const override;
|
||||
size_t Max10MsFramesInAPacket() const override;
|
||||
int GetTargetBitrate() const override;
|
||||
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) override;
|
||||
void Reset() override;
|
||||
absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||
const override;
|
||||
|
||||
private:
|
||||
size_t RequiredOutputSizeBytes() const;
|
||||
|
||||
static constexpr size_t kMaxSamplesPerPacket = 480;
|
||||
const int frame_size_ms_;
|
||||
const int payload_type_;
|
||||
const size_t num_10ms_frames_per_packet_;
|
||||
size_t num_10ms_frames_buffered_;
|
||||
uint32_t first_timestamp_in_buffer_;
|
||||
int16_t input_buffer_[kMaxSamplesPerPacket];
|
||||
IlbcEncoderInstance* encoder_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AugmentedCbCorr.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_AugmentedCbCorr(
|
||||
int16_t *target, /* (i) Target vector */
|
||||
int16_t *buffer, /* (i) Memory buffer */
|
||||
int16_t *interpSamples, /* (i) buffer with
|
||||
interpolated samples */
|
||||
int32_t *crossDot, /* (o) The cross correlation between
|
||||
the target and the Augmented
|
||||
vector */
|
||||
size_t low, /* (i) Lag to start from (typically
|
||||
20) */
|
||||
size_t high, /* (i) Lag to end at (typically 39) */
|
||||
int scale) /* (i) Scale factor to use for
|
||||
the crossDot */
|
||||
{
|
||||
size_t lagcount;
|
||||
size_t ilow;
|
||||
int16_t *targetPtr;
|
||||
int32_t *crossDotPtr;
|
||||
int16_t *iSPtr=interpSamples;
|
||||
|
||||
/* Calculate the correlation between the target and the
|
||||
interpolated codebook. The correlation is calculated in
|
||||
3 sections with the interpolated part in the middle */
|
||||
crossDotPtr=crossDot;
|
||||
for (lagcount=low; lagcount<=high; lagcount++) {
|
||||
|
||||
ilow = lagcount - 4;
|
||||
|
||||
/* Compute dot product for the first (lagcount-4) samples */
|
||||
(*crossDotPtr) = WebRtcSpl_DotProductWithScale(target, buffer-lagcount, ilow, scale);
|
||||
|
||||
/* Compute dot product on the interpolated samples */
|
||||
(*crossDotPtr) += WebRtcSpl_DotProductWithScale(target+ilow, iSPtr, 4, scale);
|
||||
targetPtr = target + lagcount;
|
||||
iSPtr += lagcount-ilow;
|
||||
|
||||
/* Compute dot product for the remaining samples */
|
||||
(*crossDotPtr) += WebRtcSpl_DotProductWithScale(targetPtr, buffer-lagcount, SUBL-lagcount, scale);
|
||||
crossDotPtr++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_AugmentedCbCorr.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Calculate correlation between target and Augmented codebooks
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_AugmentedCbCorr(
|
||||
int16_t* target, /* (i) Target vector */
|
||||
int16_t* buffer, /* (i) Memory buffer */
|
||||
int16_t* interpSamples, /* (i) buffer with
|
||||
interpolated samples */
|
||||
int32_t* crossDot, /* (o) The cross correlation between
|
||||
the target and the Augmented
|
||||
vector */
|
||||
size_t low, /* (i) Lag to start from (typically
|
||||
20) */
|
||||
size_t high, /* (i) Lag to end at (typically 39 */
|
||||
int scale); /* (i) Scale factor to use for the crossDot */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_BwExpand.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* lpc bandwidth expansion
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
/* The output is in the same domain as the input */
|
||||
void WebRtcIlbcfix_BwExpand(
|
||||
int16_t *out, /* (o) the bandwidth expanded lpc coefficients */
|
||||
int16_t *in, /* (i) the lpc coefficients before bandwidth
|
||||
expansion */
|
||||
int16_t *coef, /* (i) the bandwidth expansion factor Q15 */
|
||||
int16_t length /* (i) the length of lpc coefficient vectors */
|
||||
) {
|
||||
int i;
|
||||
|
||||
out[0] = in[0];
|
||||
for (i = 1; i < length; i++) {
|
||||
/* out[i] = coef[i] * in[i] with rounding.
|
||||
in[] and out[] are in Q12 and coef[] is in Q15
|
||||
*/
|
||||
out[i] = (int16_t)((coef[i] * in[i] + 16384) >> 15);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_BwExpand.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* lpc bandwidth expansion
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_BwExpand(
|
||||
int16_t* out, /* (o) the bandwidth expanded lpc coefficients */
|
||||
int16_t* in, /* (i) the lpc coefficients before bandwidth
|
||||
expansion */
|
||||
int16_t* coef, /* (i) the bandwidth expansion factor Q15 */
|
||||
int16_t length /* (i) the length of lpc coefficient vectors */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbConstruct.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/gain_dequant.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/get_cd_vec.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
// An arithmetic operation that is allowed to overflow. (It's still undefined
|
||||
// behavior, so not a good idea; this just makes UBSan ignore the violation, so
|
||||
// that our old code can continue to do what it's always been doing.)
|
||||
static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow")
|
||||
OverflowingAddS32S32ToS32(int32_t a, int32_t b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct decoded vector from codebook and gains.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
bool WebRtcIlbcfix_CbConstruct(
|
||||
int16_t* decvector, /* (o) Decoded vector */
|
||||
const int16_t* index, /* (i) Codebook indices */
|
||||
const int16_t* gain_index, /* (i) Gain quantization indices */
|
||||
int16_t* mem, /* (i) Buffer for codevector construction */
|
||||
size_t lMem, /* (i) Length of buffer */
|
||||
size_t veclen) { /* (i) Length of vector */
|
||||
size_t j;
|
||||
int16_t gain[CB_NSTAGES];
|
||||
/* Stack based */
|
||||
int16_t cbvec0[SUBL];
|
||||
int16_t cbvec1[SUBL];
|
||||
int16_t cbvec2[SUBL];
|
||||
int32_t a32;
|
||||
int16_t *gainPtr;
|
||||
|
||||
/* gain de-quantization */
|
||||
|
||||
gain[0] = WebRtcIlbcfix_GainDequant(gain_index[0], 16384, 0);
|
||||
gain[1] = WebRtcIlbcfix_GainDequant(gain_index[1], gain[0], 1);
|
||||
gain[2] = WebRtcIlbcfix_GainDequant(gain_index[2], gain[1], 2);
|
||||
|
||||
/* codebook vector construction and construction of total vector */
|
||||
|
||||
/* Stack based */
|
||||
if (!WebRtcIlbcfix_GetCbVec(cbvec0, mem, (size_t)index[0], lMem, veclen))
|
||||
return false; // Failure.
|
||||
if (!WebRtcIlbcfix_GetCbVec(cbvec1, mem, (size_t)index[1], lMem, veclen))
|
||||
return false; // Failure.
|
||||
if (!WebRtcIlbcfix_GetCbVec(cbvec2, mem, (size_t)index[2], lMem, veclen))
|
||||
return false; // Failure.
|
||||
|
||||
gainPtr = &gain[0];
|
||||
for (j=0;j<veclen;j++) {
|
||||
a32 = (*gainPtr++) * cbvec0[j];
|
||||
a32 += (*gainPtr++) * cbvec1[j];
|
||||
a32 = OverflowingAddS32S32ToS32(a32, (*gainPtr) * cbvec2[j]);
|
||||
gainPtr -= 2;
|
||||
decvector[j] = (int16_t)((a32 + 8192) >> 14);
|
||||
}
|
||||
|
||||
return true; // Success.
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbConstruct.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct decoded vector from codebook and gains.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
// Returns true on success, false on failure.
|
||||
ABSL_MUST_USE_RESULT
|
||||
bool WebRtcIlbcfix_CbConstruct(
|
||||
int16_t* decvector, /* (o) Decoded vector */
|
||||
const int16_t* index, /* (i) Codebook indices */
|
||||
const int16_t* gain_index, /* (i) Gain quantization indices */
|
||||
int16_t* mem, /* (i) Buffer for codevector construction */
|
||||
size_t lMem, /* (i) Length of buffer */
|
||||
size_t veclen /* (i) Length of vector */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergy.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Function WebRtcIlbcfix_CbMemEnergy computes the energy of all
|
||||
* the vectors in the codebook memory that will be used in the
|
||||
* following search for the best match.
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CbMemEnergy(
|
||||
size_t range,
|
||||
int16_t *CB, /* (i) The CB memory (1:st section) */
|
||||
int16_t *filteredCB, /* (i) The filtered CB memory (2:nd section) */
|
||||
size_t lMem, /* (i) Length of the CB memory */
|
||||
size_t lTarget, /* (i) Length of the target vector */
|
||||
int16_t *energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t *energyShifts, /* (o) Shift value of the energy */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size /* (i) Index to where energy values should be stored */
|
||||
) {
|
||||
int16_t *ppi, *ppo, *pp;
|
||||
int32_t energy, tmp32;
|
||||
|
||||
/* Compute the energy and store it in a vector. Also the
|
||||
* corresponding shift values are stored. The energy values
|
||||
* are reused in all three stages. */
|
||||
|
||||
/* Calculate the energy in the first block of 'lTarget' sampels. */
|
||||
ppi = CB+lMem-lTarget-1;
|
||||
ppo = CB+lMem-1;
|
||||
|
||||
pp=CB+lMem-lTarget;
|
||||
energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
|
||||
|
||||
/* Normalize the energy and store the number of shifts */
|
||||
energyShifts[0] = (int16_t)WebRtcSpl_NormW32(energy);
|
||||
tmp32 = energy << energyShifts[0];
|
||||
energyW16[0] = (int16_t)(tmp32 >> 16);
|
||||
|
||||
/* Compute the energy of the rest of the cb memory
|
||||
* by step wise adding and subtracting the next
|
||||
* sample and the last sample respectively. */
|
||||
WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, 0);
|
||||
|
||||
/* Next, precompute the energy values for the filtered cb section */
|
||||
energy=0;
|
||||
pp=filteredCB+lMem-lTarget;
|
||||
|
||||
energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
|
||||
|
||||
/* Normalize the energy and store the number of shifts */
|
||||
energyShifts[base_size] = (int16_t)WebRtcSpl_NormW32(energy);
|
||||
tmp32 = energy << energyShifts[base_size];
|
||||
energyW16[base_size] = (int16_t)(tmp32 >> 16);
|
||||
|
||||
ppi = filteredCB + lMem - 1 - lTarget;
|
||||
ppo = filteredCB + lMem - 1;
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, base_size);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergy.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void WebRtcIlbcfix_CbMemEnergy(
|
||||
size_t range,
|
||||
int16_t* CB, /* (i) The CB memory (1:st section) */
|
||||
int16_t* filteredCB, /* (i) The filtered CB memory (2:nd section) */
|
||||
size_t lMem, /* (i) Length of the CB memory */
|
||||
size_t lTarget, /* (i) Length of the target vector */
|
||||
int16_t* energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t* energyShifts, /* (o) Shift value of the energy */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size /* (i) Index to where energy values should be stored */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergyAugmentation.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_CbMemEnergyAugmentation(
|
||||
int16_t *interpSamples, /* (i) The interpolated samples */
|
||||
int16_t *CBmem, /* (i) The CB memory */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size, /* (i) Index to where energy values should be stored */
|
||||
int16_t *energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t *energyShifts /* (o) Shift value of the energy */
|
||||
){
|
||||
int32_t energy, tmp32;
|
||||
int16_t *ppe, *pp, *interpSamplesPtr;
|
||||
int16_t *CBmemPtr;
|
||||
size_t lagcount;
|
||||
int16_t *enPtr=&energyW16[base_size-20];
|
||||
int16_t *enShPtr=&energyShifts[base_size-20];
|
||||
int32_t nrjRecursive;
|
||||
|
||||
CBmemPtr = CBmem+147;
|
||||
interpSamplesPtr = interpSamples;
|
||||
|
||||
/* Compute the energy for the first (low-5) noninterpolated samples */
|
||||
nrjRecursive = WebRtcSpl_DotProductWithScale( CBmemPtr-19, CBmemPtr-19, 15, scale);
|
||||
ppe = CBmemPtr - 20;
|
||||
|
||||
for (lagcount=20; lagcount<=39; lagcount++) {
|
||||
|
||||
/* Update the energy recursively to save complexity */
|
||||
nrjRecursive += (*ppe * *ppe) >> scale;
|
||||
ppe--;
|
||||
energy = nrjRecursive;
|
||||
|
||||
/* interpolation */
|
||||
energy += WebRtcSpl_DotProductWithScale(interpSamplesPtr, interpSamplesPtr, 4, scale);
|
||||
interpSamplesPtr += 4;
|
||||
|
||||
/* Compute energy for the remaining samples */
|
||||
pp = CBmemPtr - lagcount;
|
||||
energy += WebRtcSpl_DotProductWithScale(pp, pp, SUBL-lagcount, scale);
|
||||
|
||||
/* Normalize the energy and store the number of shifts */
|
||||
(*enShPtr) = (int16_t)WebRtcSpl_NormW32(energy);
|
||||
tmp32 = energy << *enShPtr;
|
||||
*enPtr = (int16_t)(tmp32 >> 16);
|
||||
enShPtr++;
|
||||
enPtr++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergyAugmentation.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void WebRtcIlbcfix_CbMemEnergyAugmentation(
|
||||
int16_t* interpSamples, /* (i) The interpolated samples */
|
||||
int16_t* CBmem, /* (i) The CB memory */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size, /* (i) Index to where energy values should be stored */
|
||||
int16_t* energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t* energyShifts /* (o) Shift value of the energy */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergyCalc.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/* Compute the energy of the rest of the cb memory
|
||||
* by step wise adding and subtracting the next
|
||||
* sample and the last sample respectively */
|
||||
void WebRtcIlbcfix_CbMemEnergyCalc(
|
||||
int32_t energy, /* (i) input start energy */
|
||||
size_t range, /* (i) number of iterations */
|
||||
int16_t *ppi, /* (i) input pointer 1 */
|
||||
int16_t *ppo, /* (i) input pointer 2 */
|
||||
int16_t *energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t *energyShifts, /* (o) Shift value of the energy */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size /* (i) Index to where energy values should be stored */
|
||||
)
|
||||
{
|
||||
size_t j;
|
||||
int16_t shft;
|
||||
int32_t tmp;
|
||||
int16_t *eSh_ptr;
|
||||
int16_t *eW16_ptr;
|
||||
|
||||
|
||||
eSh_ptr = &energyShifts[1+base_size];
|
||||
eW16_ptr = &energyW16[1+base_size];
|
||||
|
||||
for (j = 0; j + 1 < range; j++) {
|
||||
|
||||
/* Calculate next energy by a +/-
|
||||
operation on the edge samples */
|
||||
tmp = (*ppi) * (*ppi) - (*ppo) * (*ppo);
|
||||
energy += tmp >> scale;
|
||||
energy = WEBRTC_SPL_MAX(energy, 0);
|
||||
|
||||
ppi--;
|
||||
ppo--;
|
||||
|
||||
/* Normalize the energy into a int16_t and store
|
||||
the number of shifts */
|
||||
|
||||
shft = (int16_t)WebRtcSpl_NormW32(energy);
|
||||
*eSh_ptr++ = shft;
|
||||
|
||||
tmp = energy << shft;
|
||||
*eW16_ptr++ = (int16_t)(tmp >> 16);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbMemEnergyCalc.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void WebRtcIlbcfix_CbMemEnergyCalc(
|
||||
int32_t energy, /* (i) input start energy */
|
||||
size_t range, /* (i) number of iterations */
|
||||
int16_t* ppi, /* (i) input pointer 1 */
|
||||
int16_t* ppo, /* (i) input pointer 2 */
|
||||
int16_t* energyW16, /* (o) Energy in the CB vectors */
|
||||
int16_t* energyShifts, /* (o) Shift value of the energy */
|
||||
int scale, /* (i) The scaling of all energy values */
|
||||
size_t base_size /* (i) Index to where energy values should be stored */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbSearch.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_search.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Search routine for codebook encoding and gain quantization.
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CbSearch(
|
||||
IlbcEncoder *iLBCenc_inst,
|
||||
/* (i) the encoder state structure */
|
||||
int16_t *index, /* (o) Codebook indices */
|
||||
int16_t *gain_index, /* (o) Gain quantization indices */
|
||||
int16_t *intarget, /* (i) Target vector for encoding */
|
||||
int16_t *decResidual,/* (i) Decoded residual for codebook construction */
|
||||
size_t lMem, /* (i) Length of buffer */
|
||||
size_t lTarget, /* (i) Length of vector */
|
||||
int16_t *weightDenum,/* (i) weighting filter coefficients in Q12 */
|
||||
size_t block /* (i) the subblock number */
|
||||
) {
|
||||
size_t i, range;
|
||||
int16_t ii, j, stage;
|
||||
int16_t *pp;
|
||||
int16_t tmp;
|
||||
int scale;
|
||||
int16_t bits, temp1, temp2;
|
||||
size_t base_size;
|
||||
int32_t codedEner, targetEner;
|
||||
int16_t gains[CB_NSTAGES+1];
|
||||
int16_t *cb_vecPtr;
|
||||
size_t indexOffset, sInd, eInd;
|
||||
int32_t CritMax=0;
|
||||
int16_t shTotMax=WEBRTC_SPL_WORD16_MIN;
|
||||
size_t bestIndex=0;
|
||||
int16_t bestGain=0;
|
||||
size_t indexNew;
|
||||
int16_t CritNewSh;
|
||||
int32_t CritNew;
|
||||
int32_t *cDotPtr;
|
||||
size_t noOfZeros;
|
||||
int16_t *gainPtr;
|
||||
int32_t t32, tmpW32;
|
||||
int16_t *WebRtcIlbcfix_kGainSq5_ptr;
|
||||
/* Stack based */
|
||||
int16_t CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN];
|
||||
int32_t cDot[128];
|
||||
int32_t Crit[128];
|
||||
int16_t targetVec[SUBL+LPC_FILTERORDER];
|
||||
int16_t cbvectors[CB_MEML + 1]; /* Adding one extra position for
|
||||
Coverity warnings. */
|
||||
int16_t codedVec[SUBL];
|
||||
int16_t interpSamples[20*4];
|
||||
int16_t interpSamplesFilt[20*4];
|
||||
int16_t energyW16[CB_EXPAND*128];
|
||||
int16_t energyShifts[CB_EXPAND*128];
|
||||
int16_t *inverseEnergy=energyW16; /* Reuse memory */
|
||||
int16_t *inverseEnergyShifts=energyShifts; /* Reuse memory */
|
||||
int16_t *buf = &CBbuf[LPC_FILTERORDER];
|
||||
int16_t *target = &targetVec[LPC_FILTERORDER];
|
||||
int16_t *aug_vec = (int16_t*)cDot; /* length [SUBL], reuse memory */
|
||||
|
||||
/* Determine size of codebook sections */
|
||||
|
||||
base_size=lMem-lTarget+1;
|
||||
if (lTarget==SUBL) {
|
||||
base_size=lMem-19;
|
||||
}
|
||||
|
||||
/* weighting of the CB memory */
|
||||
noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block];
|
||||
WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER);
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
decResidual+noOfZeros, buf+noOfZeros,
|
||||
weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]);
|
||||
|
||||
/* weighting of the target vector */
|
||||
WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER);
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
intarget, target,
|
||||
weightDenum, LPC_FILTERORDER+1, lTarget);
|
||||
|
||||
/* Store target, towards the end codedVec is calculated as
|
||||
the initial target minus the remaining target */
|
||||
WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget);
|
||||
|
||||
/* Find the highest absolute value to calculate proper
|
||||
vector scale factor (so that it uses 12 bits) */
|
||||
temp1 = WebRtcSpl_MaxAbsValueW16(buf, lMem);
|
||||
temp2 = WebRtcSpl_MaxAbsValueW16(target, lTarget);
|
||||
|
||||
if ((temp1>0)&&(temp2>0)) {
|
||||
temp1 = WEBRTC_SPL_MAX(temp1, temp2);
|
||||
scale = WebRtcSpl_GetSizeInBits((uint32_t)(temp1 * temp1));
|
||||
} else {
|
||||
/* temp1 or temp2 is negative (maximum was -32768) */
|
||||
scale = 30;
|
||||
}
|
||||
|
||||
/* Scale to so that a mul-add 40 times does not overflow */
|
||||
scale = scale - 25;
|
||||
scale = WEBRTC_SPL_MAX(0, scale);
|
||||
|
||||
/* Compute energy of the original target */
|
||||
targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale);
|
||||
|
||||
/* Prepare search over one more codebook section. This section
|
||||
is created by filtering the original buffer with a filter. */
|
||||
WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]);
|
||||
|
||||
range = WebRtcIlbcfix_kSearchRange[block][0];
|
||||
|
||||
if(lTarget == SUBL) {
|
||||
/* Create the interpolated samples and store them for use in all stages */
|
||||
|
||||
/* First section, non-filtered half of the cb */
|
||||
WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem);
|
||||
|
||||
/* Second section, filtered half of the cb */
|
||||
WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem);
|
||||
|
||||
/* Compute the CB vectors' energies for the first cb section (non-filtered) */
|
||||
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf,
|
||||
scale, 20, energyW16, energyShifts);
|
||||
|
||||
/* Compute the CB vectors' energies for the second cb section (filtered cb) */
|
||||
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors, scale,
|
||||
base_size + 20, energyW16,
|
||||
energyShifts);
|
||||
|
||||
/* Compute the CB vectors' energies and store them in the vector
|
||||
* energyW16. Also the corresponding shift values are stored. The
|
||||
* energy values are used in all three stages. */
|
||||
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
|
||||
lTarget, energyW16+20, energyShifts+20, scale, base_size);
|
||||
|
||||
} else {
|
||||
/* Compute the CB vectors' energies and store them in the vector
|
||||
* energyW16. Also the corresponding shift values are stored. The
|
||||
* energy values are used in all three stages. */
|
||||
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
|
||||
lTarget, energyW16, energyShifts, scale, base_size);
|
||||
|
||||
/* Set the energy positions 58-63 and 122-127 to zero
|
||||
(otherwise they are uninitialized) */
|
||||
WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range));
|
||||
WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range));
|
||||
}
|
||||
|
||||
/* Calculate Inverse Energy (energyW16 is already normalized
|
||||
and will contain the inverse energy in Q29 after this call */
|
||||
WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND);
|
||||
|
||||
/* The gain value computed in the previous stage is used
|
||||
* as an upper limit to what the next stage gain value
|
||||
* is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as
|
||||
* the upper limit. */
|
||||
gains[0] = 16384;
|
||||
|
||||
for (stage=0; stage<CB_NSTAGES; stage++) {
|
||||
|
||||
/* Set up memories */
|
||||
range = WebRtcIlbcfix_kSearchRange[block][stage];
|
||||
|
||||
/* initialize search measures */
|
||||
CritMax=0;
|
||||
shTotMax=-100;
|
||||
bestIndex=0;
|
||||
bestGain=0;
|
||||
|
||||
/* loop over lags 40+ in the first codebook section, full search */
|
||||
cb_vecPtr = buf+lMem-lTarget;
|
||||
|
||||
/* Calculate all the cross correlations (augmented part of CB) */
|
||||
if (lTarget==SUBL) {
|
||||
WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem,
|
||||
interpSamples, cDot,
|
||||
20, 39, scale);
|
||||
cDotPtr=&cDot[20];
|
||||
} else {
|
||||
cDotPtr=cDot;
|
||||
}
|
||||
/* Calculate all the cross correlations (main part of CB) */
|
||||
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1);
|
||||
|
||||
/* Adjust the search range for the augmented vectors */
|
||||
if (lTarget==SUBL) {
|
||||
range=WebRtcIlbcfix_kSearchRange[block][stage]+20;
|
||||
} else {
|
||||
range=WebRtcIlbcfix_kSearchRange[block][stage];
|
||||
}
|
||||
|
||||
indexOffset=0;
|
||||
|
||||
/* Search for best index in this part of the vector */
|
||||
WebRtcIlbcfix_CbSearchCore(
|
||||
cDot, range, stage, inverseEnergy,
|
||||
inverseEnergyShifts, Crit,
|
||||
&indexNew, &CritNew, &CritNewSh);
|
||||
|
||||
/* Update the global best index and the corresponding gain */
|
||||
WebRtcIlbcfix_CbUpdateBestIndex(
|
||||
CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew+indexOffset],
|
||||
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
|
||||
&CritMax, &shTotMax, &bestIndex, &bestGain);
|
||||
|
||||
sInd = ((CB_RESRANGE >> 1) > bestIndex) ?
|
||||
0 : (bestIndex - (CB_RESRANGE >> 1));
|
||||
eInd=sInd+CB_RESRANGE;
|
||||
if (eInd>=range) {
|
||||
eInd=range-1;
|
||||
sInd=eInd-CB_RESRANGE;
|
||||
}
|
||||
|
||||
range = WebRtcIlbcfix_kSearchRange[block][stage];
|
||||
|
||||
if (lTarget==SUBL) {
|
||||
i=sInd;
|
||||
if (sInd<20) {
|
||||
WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors + lMem,
|
||||
interpSamplesFilt, cDot, sInd + 20,
|
||||
WEBRTC_SPL_MIN(39, (eInd + 20)), scale);
|
||||
i=20;
|
||||
cDotPtr = &cDot[20 - sInd];
|
||||
} else {
|
||||
cDotPtr = cDot;
|
||||
}
|
||||
|
||||
cb_vecPtr = cbvectors+lMem-20-i;
|
||||
|
||||
/* Calculate the cross correlations (main part of the filtered CB) */
|
||||
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget,
|
||||
eInd - i + 1, scale, -1);
|
||||
|
||||
} else {
|
||||
cDotPtr = cDot;
|
||||
cb_vecPtr = cbvectors+lMem-lTarget-sInd;
|
||||
|
||||
/* Calculate the cross correlations (main part of the filtered CB) */
|
||||
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget,
|
||||
eInd - sInd + 1, scale, -1);
|
||||
|
||||
}
|
||||
|
||||
/* Adjust the search range for the augmented vectors */
|
||||
indexOffset=base_size+sInd;
|
||||
|
||||
/* Search for best index in this part of the vector */
|
||||
WebRtcIlbcfix_CbSearchCore(
|
||||
cDot, eInd-sInd+1, stage, inverseEnergy+indexOffset,
|
||||
inverseEnergyShifts+indexOffset, Crit,
|
||||
&indexNew, &CritNew, &CritNewSh);
|
||||
|
||||
/* Update the global best index and the corresponding gain */
|
||||
WebRtcIlbcfix_CbUpdateBestIndex(
|
||||
CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew],
|
||||
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
|
||||
&CritMax, &shTotMax, &bestIndex, &bestGain);
|
||||
|
||||
index[stage] = (int16_t)bestIndex;
|
||||
|
||||
|
||||
bestGain = WebRtcIlbcfix_GainQuant(bestGain,
|
||||
(int16_t)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]);
|
||||
|
||||
/* Extract the best (according to measure) codebook vector
|
||||
Also adjust the index, so that the augmented vectors are last.
|
||||
Above these vectors were first...
|
||||
*/
|
||||
|
||||
if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
|
||||
|
||||
if((size_t)index[stage]<base_size) {
|
||||
pp=buf+lMem-lTarget-index[stage];
|
||||
} else {
|
||||
pp=cbvectors+lMem-lTarget-
|
||||
index[stage]+base_size;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ((size_t)index[stage]<base_size) {
|
||||
if (index[stage]>=20) {
|
||||
/* Adjust index and extract vector */
|
||||
index[stage]-=20;
|
||||
pp=buf+lMem-lTarget-index[stage];
|
||||
} else {
|
||||
/* Adjust index and extract vector */
|
||||
index[stage]+=(int16_t)(base_size-20);
|
||||
|
||||
WebRtcIlbcfix_CreateAugmentedVec(index[stage]-base_size+40,
|
||||
buf+lMem, aug_vec);
|
||||
pp = aug_vec;
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((index[stage] - base_size) >= 20) {
|
||||
/* Adjust index and extract vector */
|
||||
index[stage]-=20;
|
||||
pp=cbvectors+lMem-lTarget-
|
||||
index[stage]+base_size;
|
||||
} else {
|
||||
/* Adjust index and extract vector */
|
||||
index[stage]+=(int16_t)(base_size-20);
|
||||
WebRtcIlbcfix_CreateAugmentedVec(index[stage]-2*base_size+40,
|
||||
cbvectors+lMem, aug_vec);
|
||||
pp = aug_vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subtract the best codebook vector, according
|
||||
to measure, from the target vector */
|
||||
|
||||
WebRtcSpl_AddAffineVectorToVector(target, pp, (int16_t)(-bestGain),
|
||||
(int32_t)8192, (int16_t)14, lTarget);
|
||||
|
||||
/* record quantized gain */
|
||||
gains[stage+1] = bestGain;
|
||||
|
||||
} /* end of Main Loop. for (stage=0;... */
|
||||
|
||||
/* Calculte the coded vector (original target - what's left) */
|
||||
for (i=0;i<lTarget;i++) {
|
||||
codedVec[i]-=target[i];
|
||||
}
|
||||
|
||||
/* Gain adjustment for energy matching */
|
||||
codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale);
|
||||
|
||||
j=gain_index[0];
|
||||
|
||||
temp1 = (int16_t)WebRtcSpl_NormW32(codedEner);
|
||||
temp2 = (int16_t)WebRtcSpl_NormW32(targetEner);
|
||||
|
||||
if(temp1 < temp2) {
|
||||
bits = 16 - temp1;
|
||||
} else {
|
||||
bits = 16 - temp2;
|
||||
}
|
||||
|
||||
tmp = (int16_t)((gains[1] * gains[1]) >> 14);
|
||||
|
||||
targetEner = (int16_t)WEBRTC_SPL_SHIFT_W32(targetEner, -bits) * tmp;
|
||||
|
||||
tmpW32 = ((int32_t)(gains[1]-1))<<1;
|
||||
|
||||
/* Pointer to the table that contains
|
||||
gain_sq5TblFIX * gain_sq5TblFIX in Q14 */
|
||||
gainPtr=(int16_t*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0];
|
||||
temp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(codedEner, -bits);
|
||||
|
||||
WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[j];
|
||||
|
||||
/* targetEner and codedEner are in Q(-2*scale) */
|
||||
for (ii=gain_index[0];ii<32;ii++) {
|
||||
|
||||
/* Change the index if
|
||||
(codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND
|
||||
gainTbl[i] < 2*gain[0]
|
||||
*/
|
||||
|
||||
t32 = temp1 * *gainPtr;
|
||||
t32 = t32 - targetEner;
|
||||
if (t32 < 0) {
|
||||
if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) {
|
||||
j=ii;
|
||||
WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[ii];
|
||||
}
|
||||
}
|
||||
gainPtr++;
|
||||
}
|
||||
gain_index[0]=j;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbSearch.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_CbSearch(
|
||||
IlbcEncoder* iLBCenc_inst,
|
||||
/* (i) the encoder state structure */
|
||||
int16_t* index, /* (o) Codebook indices */
|
||||
int16_t* gain_index, /* (o) Gain quantization indices */
|
||||
int16_t* intarget, /* (i) Target vector for encoding */
|
||||
int16_t* decResidual, /* (i) Decoded residual for codebook construction */
|
||||
size_t lMem, /* (i) Length of buffer */
|
||||
size_t lTarget, /* (i) Length of vector */
|
||||
int16_t* weightDenum, /* (i) weighting filter coefficients in Q12 */
|
||||
size_t block /* (i) the subblock number */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbSearchCore.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_CbSearchCore(
|
||||
int32_t *cDot, /* (i) Cross Correlation */
|
||||
size_t range, /* (i) Search range */
|
||||
int16_t stage, /* (i) Stage of this search */
|
||||
int16_t *inverseEnergy, /* (i) Inversed energy */
|
||||
int16_t *inverseEnergyShift, /* (i) Shifts of inversed energy
|
||||
with the offset 2*16-29 */
|
||||
int32_t *Crit, /* (o) The criteria */
|
||||
size_t *bestIndex, /* (o) Index that corresponds to
|
||||
maximum criteria (in this
|
||||
vector) */
|
||||
int32_t *bestCrit, /* (o) Value of critera for the
|
||||
chosen index */
|
||||
int16_t *bestCritSh) /* (o) The domain of the chosen
|
||||
criteria */
|
||||
{
|
||||
int32_t maxW32, tmp32;
|
||||
int16_t max, sh, tmp16;
|
||||
size_t i;
|
||||
int32_t *cDotPtr;
|
||||
int16_t cDotSqW16;
|
||||
int16_t *inverseEnergyPtr;
|
||||
int32_t *critPtr;
|
||||
int16_t *inverseEnergyShiftPtr;
|
||||
|
||||
/* Don't allow negative values for stage 0 */
|
||||
if (stage==0) {
|
||||
cDotPtr=cDot;
|
||||
for (i=0;i<range;i++) {
|
||||
*cDotPtr=WEBRTC_SPL_MAX(0, (*cDotPtr));
|
||||
cDotPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Normalize cDot to int16_t, calculate the square of cDot and store the upper int16_t */
|
||||
maxW32 = WebRtcSpl_MaxAbsValueW32(cDot, range);
|
||||
|
||||
sh = (int16_t)WebRtcSpl_NormW32(maxW32);
|
||||
cDotPtr = cDot;
|
||||
inverseEnergyPtr = inverseEnergy;
|
||||
critPtr = Crit;
|
||||
inverseEnergyShiftPtr=inverseEnergyShift;
|
||||
max=WEBRTC_SPL_WORD16_MIN;
|
||||
|
||||
for (i=0;i<range;i++) {
|
||||
/* Calculate cDot*cDot and put the result in a int16_t */
|
||||
tmp32 = *cDotPtr << sh;
|
||||
tmp16 = (int16_t)(tmp32 >> 16);
|
||||
cDotSqW16 = (int16_t)(((int32_t)(tmp16)*(tmp16))>>16);
|
||||
|
||||
/* Calculate the criteria (cDot*cDot/energy) */
|
||||
*critPtr = cDotSqW16 * *inverseEnergyPtr;
|
||||
|
||||
/* Extract the maximum shift value under the constraint
|
||||
that the criteria is not zero */
|
||||
if ((*critPtr)!=0) {
|
||||
max = WEBRTC_SPL_MAX((*inverseEnergyShiftPtr), max);
|
||||
}
|
||||
|
||||
inverseEnergyPtr++;
|
||||
inverseEnergyShiftPtr++;
|
||||
critPtr++;
|
||||
cDotPtr++;
|
||||
}
|
||||
|
||||
/* If no max shifts still at initialization value, set shift to zero */
|
||||
if (max==WEBRTC_SPL_WORD16_MIN) {
|
||||
max = 0;
|
||||
}
|
||||
|
||||
/* Modify the criterias, so that all of them use the same Q domain */
|
||||
critPtr=Crit;
|
||||
inverseEnergyShiftPtr=inverseEnergyShift;
|
||||
for (i=0;i<range;i++) {
|
||||
/* Guarantee that the shift value is less than 16
|
||||
in order to simplify for DSP's (and guard against >31) */
|
||||
tmp16 = WEBRTC_SPL_MIN(16, max-(*inverseEnergyShiftPtr));
|
||||
|
||||
(*critPtr)=WEBRTC_SPL_SHIFT_W32((*critPtr),-tmp16);
|
||||
critPtr++;
|
||||
inverseEnergyShiftPtr++;
|
||||
}
|
||||
|
||||
/* Find the index of the best value */
|
||||
*bestIndex = WebRtcSpl_MaxIndexW32(Crit, range);
|
||||
*bestCrit = Crit[*bestIndex];
|
||||
|
||||
/* Calculate total shifts of this criteria */
|
||||
*bestCritSh = 32 - 2*sh + max;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbSearchCore.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void WebRtcIlbcfix_CbSearchCore(
|
||||
int32_t* cDot, /* (i) Cross Correlation */
|
||||
size_t range, /* (i) Search range */
|
||||
int16_t stage, /* (i) Stage of this search */
|
||||
int16_t* inverseEnergy, /* (i) Inversed energy */
|
||||
int16_t* inverseEnergyShift, /* (i) Shifts of inversed energy
|
||||
with the offset 2*16-29 */
|
||||
int32_t* Crit, /* (o) The criteria */
|
||||
size_t* bestIndex, /* (o) Index that corresponds to
|
||||
maximum criteria (in this
|
||||
vector) */
|
||||
int32_t* bestCrit, /* (o) Value of critera for the
|
||||
chosen index */
|
||||
int16_t* bestCritSh); /* (o) The domain of the chosen
|
||||
criteria */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbUpdateBestIndex.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_CbUpdateBestIndex(
|
||||
int32_t CritNew, /* (i) New Potentially best Criteria */
|
||||
int16_t CritNewSh, /* (i) Shift value of above Criteria */
|
||||
size_t IndexNew, /* (i) Index of new Criteria */
|
||||
int32_t cDotNew, /* (i) Cross dot of new index */
|
||||
int16_t invEnergyNew, /* (i) Inversed energy new index */
|
||||
int16_t energyShiftNew, /* (i) Energy shifts of new index */
|
||||
int32_t *CritMax, /* (i/o) Maximum Criteria (so far) */
|
||||
int16_t *shTotMax, /* (i/o) Shifts of maximum criteria */
|
||||
size_t *bestIndex, /* (i/o) Index that corresponds to
|
||||
maximum criteria */
|
||||
int16_t *bestGain) /* (i/o) Gain in Q14 that corresponds
|
||||
to maximum criteria */
|
||||
{
|
||||
int16_t shOld, shNew, tmp16;
|
||||
int16_t scaleTmp;
|
||||
int32_t gainW32;
|
||||
|
||||
/* Normalize the new and old Criteria to the same domain */
|
||||
if (CritNewSh>(*shTotMax)) {
|
||||
shOld=WEBRTC_SPL_MIN(31,CritNewSh-(*shTotMax));
|
||||
shNew=0;
|
||||
} else {
|
||||
shOld=0;
|
||||
shNew=WEBRTC_SPL_MIN(31,(*shTotMax)-CritNewSh);
|
||||
}
|
||||
|
||||
/* Compare the two criterias. If the new one is better,
|
||||
calculate the gain and store this index as the new best one
|
||||
*/
|
||||
|
||||
if ((CritNew >> shNew) > (*CritMax >> shOld)) {
|
||||
|
||||
tmp16 = (int16_t)WebRtcSpl_NormW32(cDotNew);
|
||||
tmp16 = 16 - tmp16;
|
||||
|
||||
/* Calculate the gain in Q14
|
||||
Compensate for inverseEnergyshift in Q29 and that the energy
|
||||
value was stored in a int16_t (shifted down 16 steps)
|
||||
=> 29-14+16 = 31 */
|
||||
|
||||
scaleTmp = -energyShiftNew-tmp16+31;
|
||||
scaleTmp = WEBRTC_SPL_MIN(31, scaleTmp);
|
||||
|
||||
gainW32 = ((int16_t)WEBRTC_SPL_SHIFT_W32(cDotNew, -tmp16) * invEnergyNew) >>
|
||||
scaleTmp;
|
||||
|
||||
/* Check if criteria satisfies Gain criteria (max 1.3)
|
||||
if it is larger set the gain to 1.3
|
||||
(slightly different from FLP version)
|
||||
*/
|
||||
if (gainW32>21299) {
|
||||
*bestGain=21299;
|
||||
} else if (gainW32<-21299) {
|
||||
*bestGain=-21299;
|
||||
} else {
|
||||
*bestGain=(int16_t)gainW32;
|
||||
}
|
||||
|
||||
*CritMax=CritNew;
|
||||
*shTotMax=CritNewSh;
|
||||
*bestIndex = IndexNew;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CbUpdateBestIndex.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void WebRtcIlbcfix_CbUpdateBestIndex(
|
||||
int32_t CritNew, /* (i) New Potentially best Criteria */
|
||||
int16_t CritNewSh, /* (i) Shift value of above Criteria */
|
||||
size_t IndexNew, /* (i) Index of new Criteria */
|
||||
int32_t cDotNew, /* (i) Cross dot of new index */
|
||||
int16_t invEnergyNew, /* (i) Inversed energy new index */
|
||||
int16_t energyShiftNew, /* (i) Energy shifts of new index */
|
||||
int32_t* CritMax, /* (i/o) Maximum Criteria (so far) */
|
||||
int16_t* shTotMax, /* (i/o) Shifts of maximum criteria */
|
||||
size_t* bestIndex, /* (i/o) Index that corresponds to
|
||||
maximum criteria */
|
||||
int16_t* bestGain); /* (i/o) Gain in Q14 that corresponds
|
||||
to maximum criteria */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Chebyshev.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/chebyshev.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* Calculate the Chevyshev polynomial series
|
||||
* F(w) = 2*exp(-j5w)*C(x)
|
||||
* C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
|
||||
* T_i(x) is the i:th order Chebyshev polynomial
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
int16_t WebRtcIlbcfix_Chebyshev(
|
||||
/* (o) Result of C(x) */
|
||||
int16_t x, /* (i) Value to the Chevyshev polynomial */
|
||||
int16_t *f /* (i) The coefficients in the polynomial */
|
||||
) {
|
||||
int16_t b1_high, b1_low; /* Use the high, low format to increase the accuracy */
|
||||
int32_t b2;
|
||||
int32_t tmp1W32;
|
||||
int32_t tmp2W32;
|
||||
int i;
|
||||
|
||||
b2 = (int32_t)0x1000000; /* b2 = 1.0 (Q23) */
|
||||
/* Calculate b1 = 2*x + f[1] */
|
||||
tmp1W32 = (x << 10) + (f[1] << 14);
|
||||
|
||||
for (i = 2; i < 5; i++) {
|
||||
tmp2W32 = tmp1W32;
|
||||
|
||||
/* Split b1 (in tmp1W32) into a high and low part */
|
||||
b1_high = (int16_t)(tmp1W32 >> 16);
|
||||
b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
|
||||
|
||||
/* Calculate 2*x*b1-b2+f[i] */
|
||||
tmp1W32 = ((b1_high * x + ((b1_low * x) >> 15)) << 2) - b2 + (f[i] << 14);
|
||||
|
||||
/* Update b2 for next round */
|
||||
b2 = tmp2W32;
|
||||
}
|
||||
|
||||
/* Split b1 (in tmp1W32) into a high and low part */
|
||||
b1_high = (int16_t)(tmp1W32 >> 16);
|
||||
b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
|
||||
|
||||
/* tmp1W32 = x*b1 - b2 + f[i]/2 */
|
||||
tmp1W32 = ((b1_high * x) << 1) + (((b1_low * x) >> 15) << 1) -
|
||||
b2 + (f[i] << 13);
|
||||
|
||||
/* Handle overflows and set to maximum or minimum int16_t instead */
|
||||
if (tmp1W32>((int32_t)33553408)) {
|
||||
return(WEBRTC_SPL_WORD16_MAX);
|
||||
} else if (tmp1W32<((int32_t)-33554432)) {
|
||||
return(WEBRTC_SPL_WORD16_MIN);
|
||||
} else {
|
||||
return (int16_t)(tmp1W32 >> 10);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Chebyshev.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* Calculate the Chevyshev polynomial series
|
||||
* F(w) = 2*exp(-j5w)*C(x)
|
||||
* C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
|
||||
* T_i(x) is the i:th order Chebyshev polynomial
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
int16_t WebRtcIlbcfix_Chebyshev(
|
||||
/* (o) Result of C(x) */
|
||||
int16_t x, /* (i) Value to the Chevyshev polynomial */
|
||||
int16_t* f /* (i) The coefficients in the polynomial */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CompCorr.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Compute cross correlation and pitch gain for pitch prediction
|
||||
* of last subframe at given lag.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CompCorr(
|
||||
int32_t *corr, /* (o) cross correlation */
|
||||
int32_t *ener, /* (o) energy */
|
||||
int16_t *buffer, /* (i) signal buffer */
|
||||
size_t lag, /* (i) pitch lag */
|
||||
size_t bLen, /* (i) length of buffer */
|
||||
size_t sRange, /* (i) correlation search length */
|
||||
int16_t scale /* (i) number of rightshifts to use */
|
||||
){
|
||||
int16_t *w16ptr;
|
||||
|
||||
w16ptr=&buffer[bLen-sRange-lag];
|
||||
|
||||
/* Calculate correlation and energy */
|
||||
(*corr)=WebRtcSpl_DotProductWithScale(&buffer[bLen-sRange], w16ptr, sRange, scale);
|
||||
(*ener)=WebRtcSpl_DotProductWithScale(w16ptr, w16ptr, sRange, scale);
|
||||
|
||||
/* For zero energy set the energy to 0 in order to avoid potential
|
||||
problems for coming divisions */
|
||||
if (*ener == 0) {
|
||||
*corr = 0;
|
||||
*ener = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CompCorr.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Compute cross correlation and pitch gain for pitch prediction
|
||||
* of last subframe at given lag.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CompCorr(int32_t* corr, /* (o) cross correlation */
|
||||
int32_t* ener, /* (o) energy */
|
||||
int16_t* buffer, /* (i) signal buffer */
|
||||
size_t lag, /* (i) pitch lag */
|
||||
size_t bLen, /* (i) length of buffer */
|
||||
size_t sRange, /* (i) correlation search length */
|
||||
int16_t scale /* (i) number of rightshifts to use */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
% % Copyright(c) 2011 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.%
|
||||
|
||||
clear;
|
||||
pack;
|
||||
%
|
||||
% Enter the path to YOUR executable and remember to define the perprocessor
|
||||
% variable PRINT_MIPS te get the instructions printed to the screen.
|
||||
%
|
||||
command = '!iLBCtest.exe 30 speechAndBGnoise.pcm out1.bit out1.pcm tlm10_30ms.dat';
|
||||
cout=' > st.txt'; %saves to matlab variable 'st'
|
||||
eval(strcat(command,cout));
|
||||
if(length(cout)>3)
|
||||
load st.txt
|
||||
else
|
||||
disp('No cout file to load')
|
||||
end
|
||||
|
||||
% initialize vector to zero
|
||||
index = find(st(1:end,1)==-1);
|
||||
indexnonzero = find(st(1:end,1)>0);
|
||||
frames = length(index)-indexnonzero(1)+1;
|
||||
start = indexnonzero(1) - 1;
|
||||
functionOrder=max(st(:,2));
|
||||
new=zeros(frames,functionOrder);
|
||||
|
||||
for i = 1:frames,
|
||||
for j = index(start-1+i)+1:(index(start+i)-1),
|
||||
new(i,st(j,2)) = new(i,st(j,2)) + st(j,1);
|
||||
end
|
||||
end
|
||||
|
||||
result=zeros(functionOrder,3);
|
||||
for i=1:functionOrder
|
||||
nonzeroelements = find(new(1:end,i)>0);
|
||||
result(i,1)=i;
|
||||
|
||||
% Compute each function's mean complexity
|
||||
% result(i,2)=(sum(new(nonzeroelements,i))/(length(nonzeroelements)*0.03))/1000000;
|
||||
|
||||
% Compute each function's maximum complexity in encoding
|
||||
% and decoding respectively and then add it together:
|
||||
% result(i,3)=(max(new(1:end,i))/0.03)/1000000;
|
||||
result(i,3)=(max(new(1:size(new,1)/2,i))/0.03)/1000000 + (max(new(size(new,1)/2+1:end,i))/0.03)/1000000;
|
||||
end
|
||||
|
||||
result
|
||||
|
||||
% Compute maximum complexity for a single frame (enc/dec separately and together)
|
||||
maxEncComplexityInAFrame = (max(sum(new(1:size(new,1)/2,:),2))/0.03)/1000000
|
||||
maxDecComplexityInAFrame = (max(sum(new(size(new,1)/2+1:end,:),2))/0.03)/1000000
|
||||
totalComplexity = maxEncComplexityInAFrame + maxDecComplexityInAFrame
|
||||
|
|
@ -0,0 +1,667 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
constants.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/* HP Filters {b[0] b[1] b[2] -a[1] -a[2]} */
|
||||
|
||||
const int16_t WebRtcIlbcfix_kHpInCoefs[5] = {3798, -7596, 3798, 7807, -3733};
|
||||
const int16_t WebRtcIlbcfix_kHpOutCoefs[5] = {3849, -7699, 3849, 7918, -3833};
|
||||
|
||||
/* Window in Q11 to window the energies of the 5 choises (3 for 20ms) in the choise for
|
||||
the 80 sample start state
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kStartSequenceEnrgWin[NSUB_MAX-1]= {
|
||||
1638, 1843, 2048, 1843, 1638
|
||||
};
|
||||
|
||||
/* LP Filter coeffs used for downsampling */
|
||||
const int16_t WebRtcIlbcfix_kLpFiltCoefs[FILTERORDER_DS_PLUS1]= {
|
||||
-273, 512, 1297, 1696, 1297, 512, -273
|
||||
};
|
||||
|
||||
/* Constants used in the LPC calculations */
|
||||
|
||||
/* Hanning LPC window (in Q15) */
|
||||
const int16_t WebRtcIlbcfix_kLpcWin[BLOCKL_MAX] = {
|
||||
6, 22, 50, 89, 139, 200, 272, 355, 449, 554, 669, 795,
|
||||
932, 1079, 1237, 1405, 1583, 1771, 1969, 2177, 2395, 2622, 2858, 3104,
|
||||
3359, 3622, 3894, 4175, 4464, 4761, 5066, 5379, 5699, 6026, 6361, 6702,
|
||||
7050, 7404, 7764, 8130, 8502, 8879, 9262, 9649, 10040, 10436, 10836, 11240,
|
||||
11647, 12058, 12471, 12887, 13306, 13726, 14148, 14572, 14997, 15423, 15850, 16277,
|
||||
16704, 17131, 17558, 17983, 18408, 18831, 19252, 19672, 20089, 20504, 20916, 21325,
|
||||
21730, 22132, 22530, 22924, 23314, 23698, 24078, 24452, 24821, 25185, 25542, 25893,
|
||||
26238, 26575, 26906, 27230, 27547, 27855, 28156, 28450, 28734, 29011, 29279, 29538,
|
||||
29788, 30029, 30261, 30483, 30696, 30899, 31092, 31275, 31448, 31611, 31764, 31906,
|
||||
32037, 32158, 32268, 32367, 32456, 32533, 32600, 32655, 32700, 32733, 32755, 32767,
|
||||
32767, 32755, 32733, 32700, 32655, 32600, 32533, 32456, 32367, 32268, 32158, 32037,
|
||||
31906, 31764, 31611, 31448, 31275, 31092, 30899, 30696, 30483, 30261, 30029, 29788,
|
||||
29538, 29279, 29011, 28734, 28450, 28156, 27855, 27547, 27230, 26906, 26575, 26238,
|
||||
25893, 25542, 25185, 24821, 24452, 24078, 23698, 23314, 22924, 22530, 22132, 21730,
|
||||
21325, 20916, 20504, 20089, 19672, 19252, 18831, 18408, 17983, 17558, 17131, 16704,
|
||||
16277, 15850, 15423, 14997, 14572, 14148, 13726, 13306, 12887, 12471, 12058, 11647,
|
||||
11240, 10836, 10436, 10040, 9649, 9262, 8879, 8502, 8130, 7764, 7404, 7050,
|
||||
6702, 6361, 6026, 5699, 5379, 5066, 4761, 4464, 4175, 3894, 3622, 3359,
|
||||
3104, 2858, 2622, 2395, 2177, 1969, 1771, 1583, 1405, 1237, 1079, 932,
|
||||
795, 669, 554, 449, 355, 272, 200, 139, 89, 50, 22, 6
|
||||
};
|
||||
|
||||
/* Asymmetric LPC window (in Q15)*/
|
||||
const int16_t WebRtcIlbcfix_kLpcAsymWin[BLOCKL_MAX] = {
|
||||
2, 7, 15, 27, 42, 60, 81, 106, 135, 166, 201, 239,
|
||||
280, 325, 373, 424, 478, 536, 597, 661, 728, 798, 872, 949,
|
||||
1028, 1111, 1197, 1287, 1379, 1474, 1572, 1674, 1778, 1885, 1995, 2108,
|
||||
2224, 2343, 2465, 2589, 2717, 2847, 2980, 3115, 3254, 3395, 3538, 3684,
|
||||
3833, 3984, 4138, 4295, 4453, 4615, 4778, 4944, 5112, 5283, 5456, 5631,
|
||||
5808, 5987, 6169, 6352, 6538, 6725, 6915, 7106, 7300, 7495, 7692, 7891,
|
||||
8091, 8293, 8497, 8702, 8909, 9118, 9328, 9539, 9752, 9966, 10182, 10398,
|
||||
10616, 10835, 11055, 11277, 11499, 11722, 11947, 12172, 12398, 12625, 12852, 13080,
|
||||
13309, 13539, 13769, 14000, 14231, 14463, 14695, 14927, 15160, 15393, 15626, 15859,
|
||||
16092, 16326, 16559, 16792, 17026, 17259, 17492, 17725, 17957, 18189, 18421, 18653,
|
||||
18884, 19114, 19344, 19573, 19802, 20030, 20257, 20483, 20709, 20934, 21157, 21380,
|
||||
21602, 21823, 22042, 22261, 22478, 22694, 22909, 23123, 23335, 23545, 23755, 23962,
|
||||
24168, 24373, 24576, 24777, 24977, 25175, 25371, 25565, 25758, 25948, 26137, 26323,
|
||||
26508, 26690, 26871, 27049, 27225, 27399, 27571, 27740, 27907, 28072, 28234, 28394,
|
||||
28552, 28707, 28860, 29010, 29157, 29302, 29444, 29584, 29721, 29855, 29987, 30115,
|
||||
30241, 30364, 30485, 30602, 30717, 30828, 30937, 31043, 31145, 31245, 31342, 31436,
|
||||
31526, 31614, 31699, 31780, 31858, 31933, 32005, 32074, 32140, 32202, 32261, 32317,
|
||||
32370, 32420, 32466, 32509, 32549, 32585, 32618, 32648, 32675, 32698, 32718, 32734,
|
||||
32748, 32758, 32764, 32767, 32767, 32667, 32365, 31863, 31164, 30274, 29197, 27939,
|
||||
26510, 24917, 23170, 21281, 19261, 17121, 14876, 12540, 10126, 7650, 5126, 2571
|
||||
};
|
||||
|
||||
/* Lag window for LPC (Q31) */
|
||||
const int32_t WebRtcIlbcfix_kLpcLagWin[LPC_FILTERORDER + 1]={
|
||||
2147483647, 2144885453, 2137754373, 2125918626, 2109459810,
|
||||
2088483140, 2063130336, 2033564590, 1999977009, 1962580174,
|
||||
1921610283};
|
||||
|
||||
/* WebRtcIlbcfix_kLpcChirpSyntDenum vector in Q15 corresponding
|
||||
* floating point vector {1 0.9025 0.9025^2 0.9025^3 ...}
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kLpcChirpSyntDenum[LPC_FILTERORDER + 1] = {
|
||||
32767, 29573, 26690, 24087,
|
||||
21739, 19619, 17707, 15980,
|
||||
14422, 13016, 11747};
|
||||
|
||||
/* WebRtcIlbcfix_kLpcChirpWeightDenum in Q15 corresponding to
|
||||
* floating point vector {1 0.4222 0.4222^2... }
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kLpcChirpWeightDenum[LPC_FILTERORDER + 1] = {
|
||||
32767, 13835, 5841, 2466, 1041, 440,
|
||||
186, 78, 33, 14, 6};
|
||||
|
||||
/* LSF quantization Q13 domain */
|
||||
const int16_t WebRtcIlbcfix_kLsfCb[64 * 3 + 128 * 3 + 128 * 4] = {
|
||||
1273, 2238, 3696,
|
||||
3199, 5309, 8209,
|
||||
3606, 5671, 7829,
|
||||
2815, 5262, 8778,
|
||||
2608, 4027, 5493,
|
||||
1582, 3076, 5945,
|
||||
2983, 4181, 5396,
|
||||
2437, 4322, 6902,
|
||||
1861, 2998, 4613,
|
||||
2007, 3250, 5214,
|
||||
1388, 2459, 4262,
|
||||
2563, 3805, 5269,
|
||||
2036, 3522, 5129,
|
||||
1935, 4025, 6694,
|
||||
2744, 5121, 7338,
|
||||
2810, 4248, 5723,
|
||||
3054, 5405, 7745,
|
||||
1449, 2593, 4763,
|
||||
3411, 5128, 6596,
|
||||
2484, 4659, 7496,
|
||||
1668, 2879, 4818,
|
||||
1812, 3072, 5036,
|
||||
1638, 2649, 3900,
|
||||
2464, 3550, 4644,
|
||||
1853, 2900, 4158,
|
||||
2458, 4163, 5830,
|
||||
2556, 4036, 6254,
|
||||
2703, 4432, 6519,
|
||||
3062, 4953, 7609,
|
||||
1725, 3703, 6187,
|
||||
2221, 3877, 5427,
|
||||
2339, 3579, 5197,
|
||||
2021, 4633, 7037,
|
||||
2216, 3328, 4535,
|
||||
2961, 4739, 6667,
|
||||
2807, 3955, 5099,
|
||||
2788, 4501, 6088,
|
||||
1642, 2755, 4431,
|
||||
3341, 5282, 7333,
|
||||
2414, 3726, 5727,
|
||||
1582, 2822, 5269,
|
||||
2259, 3447, 4905,
|
||||
3117, 4986, 7054,
|
||||
1825, 3491, 5542,
|
||||
3338, 5736, 8627,
|
||||
1789, 3090, 5488,
|
||||
2566, 3720, 4923,
|
||||
2846, 4682, 7161,
|
||||
1950, 3321, 5976,
|
||||
1834, 3383, 6734,
|
||||
3238, 4769, 6094,
|
||||
2031, 3978, 5903,
|
||||
1877, 4068, 7436,
|
||||
2131, 4644, 8296,
|
||||
2764, 5010, 8013,
|
||||
2194, 3667, 6302,
|
||||
2053, 3127, 4342,
|
||||
3523, 6595, 10010,
|
||||
3134, 4457, 5748,
|
||||
3142, 5819, 9414,
|
||||
2223, 4334, 6353,
|
||||
2022, 3224, 4822,
|
||||
2186, 3458, 5544,
|
||||
2552, 4757, 6870,
|
||||
10905, 12917, 14578,
|
||||
9503, 11485, 14485,
|
||||
9518, 12494, 14052,
|
||||
6222, 7487, 9174,
|
||||
7759, 9186, 10506,
|
||||
8315, 12755, 14786,
|
||||
9609, 11486, 13866,
|
||||
8909, 12077, 13643,
|
||||
7369, 9054, 11520,
|
||||
9408, 12163, 14715,
|
||||
6436, 9911, 12843,
|
||||
7109, 9556, 11884,
|
||||
7557, 10075, 11640,
|
||||
6482, 9202, 11547,
|
||||
6463, 7914, 10980,
|
||||
8611, 10427, 12752,
|
||||
7101, 9676, 12606,
|
||||
7428, 11252, 13172,
|
||||
10197, 12955, 15842,
|
||||
7487, 10955, 12613,
|
||||
5575, 7858, 13621,
|
||||
7268, 11719, 14752,
|
||||
7476, 11744, 13795,
|
||||
7049, 8686, 11922,
|
||||
8234, 11314, 13983,
|
||||
6560, 11173, 14984,
|
||||
6405, 9211, 12337,
|
||||
8222, 12054, 13801,
|
||||
8039, 10728, 13255,
|
||||
10066, 12733, 14389,
|
||||
6016, 7338, 10040,
|
||||
6896, 8648, 10234,
|
||||
7538, 9170, 12175,
|
||||
7327, 12608, 14983,
|
||||
10516, 12643, 15223,
|
||||
5538, 7644, 12213,
|
||||
6728, 12221, 14253,
|
||||
7563, 9377, 12948,
|
||||
8661, 11023, 13401,
|
||||
7280, 8806, 11085,
|
||||
7723, 9793, 12333,
|
||||
12225, 14648, 16709,
|
||||
8768, 13389, 15245,
|
||||
10267, 12197, 13812,
|
||||
5301, 7078, 11484,
|
||||
7100, 10280, 11906,
|
||||
8716, 12555, 14183,
|
||||
9567, 12464, 15434,
|
||||
7832, 12305, 14300,
|
||||
7608, 10556, 12121,
|
||||
8913, 11311, 12868,
|
||||
7414, 9722, 11239,
|
||||
8666, 11641, 13250,
|
||||
9079, 10752, 12300,
|
||||
8024, 11608, 13306,
|
||||
10453, 13607, 16449,
|
||||
8135, 9573, 10909,
|
||||
6375, 7741, 10125,
|
||||
10025, 12217, 14874,
|
||||
6985, 11063, 14109,
|
||||
9296, 13051, 14642,
|
||||
8613, 10975, 12542,
|
||||
6583, 10414, 13534,
|
||||
6191, 9368, 13430,
|
||||
5742, 6859, 9260,
|
||||
7723, 9813, 13679,
|
||||
8137, 11291, 12833,
|
||||
6562, 8973, 10641,
|
||||
6062, 8462, 11335,
|
||||
6928, 8784, 12647,
|
||||
7501, 8784, 10031,
|
||||
8372, 10045, 12135,
|
||||
8191, 9864, 12746,
|
||||
5917, 7487, 10979,
|
||||
5516, 6848, 10318,
|
||||
6819, 9899, 11421,
|
||||
7882, 12912, 15670,
|
||||
9558, 11230, 12753,
|
||||
7752, 9327, 11472,
|
||||
8479, 9980, 11358,
|
||||
11418, 14072, 16386,
|
||||
7968, 10330, 14423,
|
||||
8423, 10555, 12162,
|
||||
6337, 10306, 14391,
|
||||
8850, 10879, 14276,
|
||||
6750, 11885, 15710,
|
||||
7037, 8328, 9764,
|
||||
6914, 9266, 13476,
|
||||
9746, 13949, 15519,
|
||||
11032, 14444, 16925,
|
||||
8032, 10271, 11810,
|
||||
10962, 13451, 15833,
|
||||
10021, 11667, 13324,
|
||||
6273, 8226, 12936,
|
||||
8543, 10397, 13496,
|
||||
7936, 10302, 12745,
|
||||
6769, 8138, 10446,
|
||||
6081, 7786, 11719,
|
||||
8637, 11795, 14975,
|
||||
8790, 10336, 11812,
|
||||
7040, 8490, 10771,
|
||||
7338, 10381, 13153,
|
||||
6598, 7888, 9358,
|
||||
6518, 8237, 12030,
|
||||
9055, 10763, 12983,
|
||||
6490, 10009, 12007,
|
||||
9589, 12023, 13632,
|
||||
6867, 9447, 10995,
|
||||
7930, 9816, 11397,
|
||||
10241, 13300, 14939,
|
||||
5830, 8670, 12387,
|
||||
9870, 11915, 14247,
|
||||
9318, 11647, 13272,
|
||||
6721, 10836, 12929,
|
||||
6543, 8233, 9944,
|
||||
8034, 10854, 12394,
|
||||
9112, 11787, 14218,
|
||||
9302, 11114, 13400,
|
||||
9022, 11366, 13816,
|
||||
6962, 10461, 12480,
|
||||
11288, 13333, 15222,
|
||||
7249, 8974, 10547,
|
||||
10566, 12336, 14390,
|
||||
6697, 11339, 13521,
|
||||
11851, 13944, 15826,
|
||||
6847, 8381, 11349,
|
||||
7509, 9331, 10939,
|
||||
8029, 9618, 11909,
|
||||
13973, 17644, 19647, 22474,
|
||||
14722, 16522, 20035, 22134,
|
||||
16305, 18179, 21106, 23048,
|
||||
15150, 17948, 21394, 23225,
|
||||
13582, 15191, 17687, 22333,
|
||||
11778, 15546, 18458, 21753,
|
||||
16619, 18410, 20827, 23559,
|
||||
14229, 15746, 17907, 22474,
|
||||
12465, 15327, 20700, 22831,
|
||||
15085, 16799, 20182, 23410,
|
||||
13026, 16935, 19890, 22892,
|
||||
14310, 16854, 19007, 22944,
|
||||
14210, 15897, 18891, 23154,
|
||||
14633, 18059, 20132, 22899,
|
||||
15246, 17781, 19780, 22640,
|
||||
16396, 18904, 20912, 23035,
|
||||
14618, 17401, 19510, 21672,
|
||||
15473, 17497, 19813, 23439,
|
||||
18851, 20736, 22323, 23864,
|
||||
15055, 16804, 18530, 20916,
|
||||
16490, 18196, 19990, 21939,
|
||||
11711, 15223, 21154, 23312,
|
||||
13294, 15546, 19393, 21472,
|
||||
12956, 16060, 20610, 22417,
|
||||
11628, 15843, 19617, 22501,
|
||||
14106, 16872, 19839, 22689,
|
||||
15655, 18192, 20161, 22452,
|
||||
12953, 15244, 20619, 23549,
|
||||
15322, 17193, 19926, 21762,
|
||||
16873, 18676, 20444, 22359,
|
||||
14874, 17871, 20083, 21959,
|
||||
11534, 14486, 19194, 21857,
|
||||
17766, 19617, 21338, 23178,
|
||||
13404, 15284, 19080, 23136,
|
||||
15392, 17527, 19470, 21953,
|
||||
14462, 16153, 17985, 21192,
|
||||
17734, 19750, 21903, 23783,
|
||||
16973, 19096, 21675, 23815,
|
||||
16597, 18936, 21257, 23461,
|
||||
15966, 17865, 20602, 22920,
|
||||
15416, 17456, 20301, 22972,
|
||||
18335, 20093, 21732, 23497,
|
||||
15548, 17217, 20679, 23594,
|
||||
15208, 16995, 20816, 22870,
|
||||
13890, 18015, 20531, 22468,
|
||||
13211, 15377, 19951, 22388,
|
||||
12852, 14635, 17978, 22680,
|
||||
16002, 17732, 20373, 23544,
|
||||
11373, 14134, 19534, 22707,
|
||||
17329, 19151, 21241, 23462,
|
||||
15612, 17296, 19362, 22850,
|
||||
15422, 19104, 21285, 23164,
|
||||
13792, 17111, 19349, 21370,
|
||||
15352, 17876, 20776, 22667,
|
||||
15253, 16961, 18921, 22123,
|
||||
14108, 17264, 20294, 23246,
|
||||
15785, 17897, 20010, 21822,
|
||||
17399, 19147, 20915, 22753,
|
||||
13010, 15659, 18127, 20840,
|
||||
16826, 19422, 22218, 24084,
|
||||
18108, 20641, 22695, 24237,
|
||||
18018, 20273, 22268, 23920,
|
||||
16057, 17821, 21365, 23665,
|
||||
16005, 17901, 19892, 23016,
|
||||
13232, 16683, 21107, 23221,
|
||||
13280, 16615, 19915, 21829,
|
||||
14950, 18575, 20599, 22511,
|
||||
16337, 18261, 20277, 23216,
|
||||
14306, 16477, 21203, 23158,
|
||||
12803, 17498, 20248, 22014,
|
||||
14327, 17068, 20160, 22006,
|
||||
14402, 17461, 21599, 23688,
|
||||
16968, 18834, 20896, 23055,
|
||||
15070, 17157, 20451, 22315,
|
||||
15419, 17107, 21601, 23946,
|
||||
16039, 17639, 19533, 21424,
|
||||
16326, 19261, 21745, 23673,
|
||||
16489, 18534, 21658, 23782,
|
||||
16594, 18471, 20549, 22807,
|
||||
18973, 21212, 22890, 24278,
|
||||
14264, 18674, 21123, 23071,
|
||||
15117, 16841, 19239, 23118,
|
||||
13762, 15782, 20478, 23230,
|
||||
14111, 15949, 20058, 22354,
|
||||
14990, 16738, 21139, 23492,
|
||||
13735, 16971, 19026, 22158,
|
||||
14676, 17314, 20232, 22807,
|
||||
16196, 18146, 20459, 22339,
|
||||
14747, 17258, 19315, 22437,
|
||||
14973, 17778, 20692, 23367,
|
||||
15715, 17472, 20385, 22349,
|
||||
15702, 18228, 20829, 23410,
|
||||
14428, 16188, 20541, 23630,
|
||||
16824, 19394, 21365, 23246,
|
||||
13069, 16392, 18900, 21121,
|
||||
12047, 16640, 19463, 21689,
|
||||
14757, 17433, 19659, 23125,
|
||||
15185, 16930, 19900, 22540,
|
||||
16026, 17725, 19618, 22399,
|
||||
16086, 18643, 21179, 23472,
|
||||
15462, 17248, 19102, 21196,
|
||||
17368, 20016, 22396, 24096,
|
||||
12340, 14475, 19665, 23362,
|
||||
13636, 16229, 19462, 22728,
|
||||
14096, 16211, 19591, 21635,
|
||||
12152, 14867, 19943, 22301,
|
||||
14492, 17503, 21002, 22728,
|
||||
14834, 16788, 19447, 21411,
|
||||
14650, 16433, 19326, 22308,
|
||||
14624, 16328, 19659, 23204,
|
||||
13888, 16572, 20665, 22488,
|
||||
12977, 16102, 18841, 22246,
|
||||
15523, 18431, 21757, 23738,
|
||||
14095, 16349, 18837, 20947,
|
||||
13266, 17809, 21088, 22839,
|
||||
15427, 18190, 20270, 23143,
|
||||
11859, 16753, 20935, 22486,
|
||||
12310, 17667, 21736, 23319,
|
||||
14021, 15926, 18702, 22002,
|
||||
12286, 15299, 19178, 21126,
|
||||
15703, 17491, 21039, 23151,
|
||||
12272, 14018, 18213, 22570,
|
||||
14817, 16364, 18485, 22598,
|
||||
17109, 19683, 21851, 23677,
|
||||
12657, 14903, 19039, 22061,
|
||||
14713, 16487, 20527, 22814,
|
||||
14635, 16726, 18763, 21715,
|
||||
15878, 18550, 20718, 22906
|
||||
};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kLsfDimCb[LSF_NSPLIT] = {3, 3, 4};
|
||||
const int16_t WebRtcIlbcfix_kLsfSizeCb[LSF_NSPLIT] = {64,128,128};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kLsfMean[LPC_FILTERORDER] = {
|
||||
2308, 3652, 5434, 7885,
|
||||
10255, 12559, 15160, 17513,
|
||||
20328, 22752};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kLspMean[LPC_FILTERORDER] = {
|
||||
31476, 29565, 25819, 18725, 10276,
|
||||
1236, -9049, -17600, -25884, -30618
|
||||
};
|
||||
|
||||
/* Q14 */
|
||||
const int16_t WebRtcIlbcfix_kLsfWeight20ms[4] = {12288, 8192, 4096, 0};
|
||||
const int16_t WebRtcIlbcfix_kLsfWeight30ms[6] = {8192, 16384, 10923, 5461, 0, 0};
|
||||
|
||||
/*
|
||||
cos(x) in Q15
|
||||
WebRtcIlbcfix_kCos[i] = cos(pi*i/64.0)
|
||||
used in WebRtcIlbcfix_Lsp2Lsf()
|
||||
*/
|
||||
|
||||
const int16_t WebRtcIlbcfix_kCos[64] = {
|
||||
32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
|
||||
30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
|
||||
23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
|
||||
12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
|
||||
0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
|
||||
-12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
|
||||
-23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
|
||||
-30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729
|
||||
};
|
||||
|
||||
/*
|
||||
Derivative in Q19, used to interpolate between the
|
||||
WebRtcIlbcfix_kCos[] values to get a more exact y = cos(x)
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kCosDerivative[64] = {
|
||||
-632, -1893, -3150, -4399, -5638, -6863, -8072, -9261,
|
||||
-10428, -11570, -12684, -13767, -14817, -15832, -16808, -17744,
|
||||
-18637, -19486, -20287, -21039, -21741, -22390, -22986, -23526,
|
||||
-24009, -24435, -24801, -25108, -25354, -25540, -25664, -25726,
|
||||
-25726, -25664, -25540, -25354, -25108, -24801, -24435, -24009,
|
||||
-23526, -22986, -22390, -21741, -21039, -20287, -19486, -18637,
|
||||
-17744, -16808, -15832, -14817, -13767, -12684, -11570, -10428,
|
||||
-9261, -8072, -6863, -5638, -4399, -3150, -1893, -632};
|
||||
|
||||
/*
|
||||
Table in Q15, used for a2lsf conversion
|
||||
WebRtcIlbcfix_kCosGrid[i] = cos((2*pi*i)/(float)(2*COS_GRID_POINTS));
|
||||
*/
|
||||
|
||||
const int16_t WebRtcIlbcfix_kCosGrid[COS_GRID_POINTS + 1] = {
|
||||
32760, 32723, 32588, 32364, 32051, 31651, 31164, 30591,
|
||||
29935, 29196, 28377, 27481, 26509, 25465, 24351, 23170,
|
||||
21926, 20621, 19260, 17846, 16384, 14876, 13327, 11743,
|
||||
10125, 8480, 6812, 5126, 3425, 1714, 0, -1714, -3425,
|
||||
-5126, -6812, -8480, -10125, -11743, -13327, -14876,
|
||||
-16384, -17846, -19260, -20621, -21926, -23170, -24351,
|
||||
-25465, -26509, -27481, -28377, -29196, -29935, -30591,
|
||||
-31164, -31651, -32051, -32364, -32588, -32723, -32760
|
||||
};
|
||||
|
||||
/*
|
||||
Derivative of y = acos(x) in Q12
|
||||
used in WebRtcIlbcfix_Lsp2Lsf()
|
||||
*/
|
||||
|
||||
const int16_t WebRtcIlbcfix_kAcosDerivative[64] = {
|
||||
-26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811,
|
||||
-1608, -1450, -1322, -1219, -1132, -1059, -998, -946,
|
||||
-901, -861, -827, -797, -772, -750, -730, -713,
|
||||
-699, -687, -677, -668, -662, -657, -654, -652,
|
||||
-652, -654, -657, -662, -668, -677, -687, -699,
|
||||
-713, -730, -750, -772, -797, -827, -861, -901,
|
||||
-946, -998, -1059, -1132, -1219, -1322, -1450, -1608,
|
||||
-1811, -2081, -2444, -2979, -3813, -5323, -8812, -26887
|
||||
};
|
||||
|
||||
|
||||
/* Tables for quantization of start state */
|
||||
|
||||
/* State quantization tables */
|
||||
const int16_t WebRtcIlbcfix_kStateSq3[8] = { /* Values in Q13 */
|
||||
-30473, -17838, -9257, -2537,
|
||||
3639, 10893, 19958, 32636
|
||||
};
|
||||
|
||||
/* This table defines the limits for the selection of the freqg
|
||||
less or equal than value 0 => index = 0
|
||||
less or equal than value k => index = k
|
||||
*/
|
||||
const int32_t WebRtcIlbcfix_kChooseFrgQuant[64] = {
|
||||
118, 163, 222, 305, 425, 604,
|
||||
851, 1174, 1617, 2222, 3080, 4191,
|
||||
5525, 7215, 9193, 11540, 14397, 17604,
|
||||
21204, 25209, 29863, 35720, 42531, 50375,
|
||||
59162, 68845, 80108, 93754, 110326, 129488,
|
||||
150654, 174328, 201962, 233195, 267843, 308239,
|
||||
354503, 405988, 464251, 531550, 608652, 697516,
|
||||
802526, 928793, 1080145, 1258120, 1481106, 1760881,
|
||||
2111111, 2546619, 3078825, 3748642, 4563142, 5573115,
|
||||
6887601, 8582108, 10797296, 14014513, 18625760, 25529599,
|
||||
37302935, 58819185, 109782723, WEBRTC_SPL_WORD32_MAX
|
||||
};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kScale[64] = {
|
||||
/* Values in Q16 */
|
||||
29485, 25003, 21345, 18316, 15578, 13128, 10973, 9310, 7955,
|
||||
6762, 5789, 4877, 4255, 3699, 3258, 2904, 2595, 2328,
|
||||
2123, 1932, 1785, 1631, 1493, 1370, 1260, 1167, 1083,
|
||||
/* Values in Q21 */
|
||||
32081, 29611, 27262, 25229, 23432, 21803, 20226, 18883, 17609,
|
||||
16408, 15311, 14327, 13390, 12513, 11693, 10919, 10163, 9435,
|
||||
8739, 8100, 7424, 6813, 6192, 5648, 5122, 4639, 4207, 3798,
|
||||
3404, 3048, 2706, 2348, 2036, 1713, 1393, 1087, 747
|
||||
};
|
||||
|
||||
/*frgq in fixpoint, but already computed like this:
|
||||
for(i=0; i<64; i++){
|
||||
a = (pow(10,frgq[i])/4.5);
|
||||
WebRtcIlbcfix_kFrgQuantMod[i] = round(a);
|
||||
}
|
||||
|
||||
Value 0 :36 in Q8
|
||||
37:58 in Q5
|
||||
59:63 in Q3
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kFrgQuantMod[64] = {
|
||||
/* First 37 values in Q8 */
|
||||
569, 671, 786, 916, 1077, 1278,
|
||||
1529, 1802, 2109, 2481, 2898, 3440,
|
||||
3943, 4535, 5149, 5778, 6464, 7208,
|
||||
7904, 8682, 9397, 10285, 11240, 12246,
|
||||
13313, 14382, 15492, 16735, 18131, 19693,
|
||||
21280, 22912, 24624, 26544, 28432, 30488,
|
||||
32720,
|
||||
/* 22 values in Q5 */
|
||||
4383, 4684, 5012, 5363, 5739, 6146,
|
||||
6603, 7113, 7679, 8285, 9040, 9850,
|
||||
10838, 11882, 13103, 14467, 15950, 17669,
|
||||
19712, 22016, 24800, 28576,
|
||||
/* 5 values in Q3 */
|
||||
8240, 9792, 12040, 15440, 22472
|
||||
};
|
||||
|
||||
/* Constants for codebook search and creation */
|
||||
|
||||
/* Expansion filter to get additional cb section.
|
||||
* Q12 and reversed compared to flp
|
||||
*/
|
||||
const int16_t WebRtcIlbcfix_kCbFiltersRev[CB_FILTERLEN]={
|
||||
-140, 446, -755, 3302, 2922, -590, 343, -138};
|
||||
|
||||
/* Weighting coefficients for short lags.
|
||||
* [0.2 0.4 0.6 0.8] in Q15 */
|
||||
const int16_t WebRtcIlbcfix_kAlpha[4]={
|
||||
6554, 13107, 19661, 26214};
|
||||
|
||||
/* Ranges for search and filters at different subframes */
|
||||
|
||||
const size_t WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES]={
|
||||
{58,58,58}, {108,44,44}, {108,108,108}, {108,108,108}, {108,108,108}};
|
||||
|
||||
const size_t WebRtcIlbcfix_kFilterRange[5]={63, 85, 125, 147, 147};
|
||||
|
||||
/* Gain Quantization for the codebook gains of the 3 stages */
|
||||
|
||||
/* Q14 (one extra value (max int16_t) to simplify for the search) */
|
||||
const int16_t WebRtcIlbcfix_kGainSq3[9]={
|
||||
-16384, -10813, -5407, 0, 4096, 8192,
|
||||
12288, 16384, 32767};
|
||||
|
||||
/* Q14 (one extra value (max int16_t) to simplify for the search) */
|
||||
const int16_t WebRtcIlbcfix_kGainSq4[17]={
|
||||
-17203, -14746, -12288, -9830, -7373, -4915,
|
||||
-2458, 0, 2458, 4915, 7373, 9830,
|
||||
12288, 14746, 17203, 19661, 32767};
|
||||
|
||||
/* Q14 (one extra value (max int16_t) to simplify for the search) */
|
||||
const int16_t WebRtcIlbcfix_kGainSq5[33]={
|
||||
614, 1229, 1843, 2458, 3072, 3686,
|
||||
4301, 4915, 5530, 6144, 6758, 7373,
|
||||
7987, 8602, 9216, 9830, 10445, 11059,
|
||||
11674, 12288, 12902, 13517, 14131, 14746,
|
||||
15360, 15974, 16589, 17203, 17818, 18432,
|
||||
19046, 19661, 32767};
|
||||
|
||||
/* Q14 gain_sq5Tbl squared in Q14 */
|
||||
const int16_t WebRtcIlbcfix_kGainSq5Sq[32] = {
|
||||
23, 92, 207, 368, 576, 829,
|
||||
1129, 1474, 1866, 2304, 2787, 3317,
|
||||
3893, 4516, 5184, 5897, 6658, 7464,
|
||||
8318, 9216, 10160, 11151, 12187, 13271,
|
||||
14400, 15574, 16796, 18062, 19377, 20736,
|
||||
22140, 23593
|
||||
};
|
||||
|
||||
const int16_t* const WebRtcIlbcfix_kGain[3] =
|
||||
{WebRtcIlbcfix_kGainSq5, WebRtcIlbcfix_kGainSq4, WebRtcIlbcfix_kGainSq3};
|
||||
|
||||
|
||||
/* Tables for the Enhancer, using upsamling factor 4 (ENH_UPS0 = 4) */
|
||||
|
||||
const int16_t WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0][ENH_FLO_MULT2_PLUS1]={
|
||||
{0, 0, 0, 4096, 0, 0, 0},
|
||||
{64, -315, 1181, 3531, -436, 77, -64},
|
||||
{97, -509, 2464, 2464, -509, 97, -97},
|
||||
{77, -436, 3531, 1181, -315, 64, -77}
|
||||
};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kEnhWt[3] = {
|
||||
4800, 16384, 27968 /* Q16 */
|
||||
};
|
||||
|
||||
const size_t WebRtcIlbcfix_kEnhPlocs[ENH_NBLOCKS_TOT] = {
|
||||
160, 480, 800, 1120, 1440, 1760, 2080, 2400 /* Q(-2) */
|
||||
};
|
||||
|
||||
/* PLC table */
|
||||
|
||||
const int16_t WebRtcIlbcfix_kPlcPerSqr[6] = { /* Grid points for square of periodiciy in Q15 */
|
||||
839, 1343, 2048, 2998, 4247, 5849
|
||||
};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kPlcPitchFact[6] = { /* Value of y=(x^4-0.4)/(0.7-0.4) in grid points in Q15 */
|
||||
0, 5462, 10922, 16384, 21846, 27306
|
||||
};
|
||||
|
||||
const int16_t WebRtcIlbcfix_kPlcPfSlope[6] = { /* Slope of y=(x^4-0.4)/(0.7-0.4) in Q11 */
|
||||
26667, 18729, 13653, 10258, 7901, 6214
|
||||
};
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
constants.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/* high pass filters */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kHpInCoefs[];
|
||||
extern const int16_t WebRtcIlbcfix_kHpOutCoefs[];
|
||||
|
||||
/* Window for start state decision */
|
||||
extern const int16_t WebRtcIlbcfix_kStartSequenceEnrgWin[];
|
||||
|
||||
/* low pass filter used for downsampling */
|
||||
extern const int16_t WebRtcIlbcfix_kLpFiltCoefs[];
|
||||
|
||||
/* LPC analysis and quantization */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kLpcWin[];
|
||||
extern const int16_t WebRtcIlbcfix_kLpcAsymWin[];
|
||||
extern const int32_t WebRtcIlbcfix_kLpcLagWin[];
|
||||
extern const int16_t WebRtcIlbcfix_kLpcChirpSyntDenum[];
|
||||
extern const int16_t WebRtcIlbcfix_kLpcChirpWeightDenum[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfDimCb[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfSizeCb[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfCb[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfWeight20ms[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfWeight30ms[];
|
||||
extern const int16_t WebRtcIlbcfix_kLsfMean[];
|
||||
extern const int16_t WebRtcIlbcfix_kLspMean[];
|
||||
extern const int16_t WebRtcIlbcfix_kCos[];
|
||||
extern const int16_t WebRtcIlbcfix_kCosDerivative[];
|
||||
extern const int16_t WebRtcIlbcfix_kCosGrid[];
|
||||
extern const int16_t WebRtcIlbcfix_kAcosDerivative[];
|
||||
|
||||
/* state quantization tables */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kStateSq3[];
|
||||
extern const int32_t WebRtcIlbcfix_kChooseFrgQuant[];
|
||||
extern const int16_t WebRtcIlbcfix_kScale[];
|
||||
extern const int16_t WebRtcIlbcfix_kFrgQuantMod[];
|
||||
|
||||
/* Ranges for search and filters at different subframes */
|
||||
|
||||
extern const size_t WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES];
|
||||
extern const size_t WebRtcIlbcfix_kFilterRange[];
|
||||
|
||||
/* gain quantization tables */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kGainSq3[];
|
||||
extern const int16_t WebRtcIlbcfix_kGainSq4[];
|
||||
extern const int16_t WebRtcIlbcfix_kGainSq5[];
|
||||
extern const int16_t WebRtcIlbcfix_kGainSq5Sq[];
|
||||
extern const int16_t* const WebRtcIlbcfix_kGain[];
|
||||
|
||||
/* adaptive codebook definitions */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kCbFiltersRev[];
|
||||
extern const int16_t WebRtcIlbcfix_kAlpha[];
|
||||
|
||||
/* enhancer definitions */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0]
|
||||
[ENH_FLO_MULT2_PLUS1];
|
||||
extern const int16_t WebRtcIlbcfix_kEnhWt[];
|
||||
extern const size_t WebRtcIlbcfix_kEnhPlocs[];
|
||||
|
||||
/* PLC tables */
|
||||
|
||||
extern const int16_t WebRtcIlbcfix_kPlcPerSqr[];
|
||||
extern const int16_t WebRtcIlbcfix_kPlcPitchFact[];
|
||||
extern const int16_t WebRtcIlbcfix_kPlcPfSlope[];
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CreateAugmentedVec.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
|
||||
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Recreate a specific codebook vector from the augmented part.
|
||||
*
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CreateAugmentedVec(
|
||||
size_t index, /* (i) Index for the augmented vector to be
|
||||
created */
|
||||
const int16_t* buffer, /* (i) Pointer to the end of the codebook memory
|
||||
that is used for creation of the augmented
|
||||
codebook */
|
||||
int16_t* cbVec) { /* (o) The constructed codebook vector */
|
||||
size_t ilow;
|
||||
const int16_t *ppo, *ppi;
|
||||
int16_t cbVecTmp[4];
|
||||
/* Interpolation starts 4 elements before cbVec+index, but must not start
|
||||
outside `cbVec`; clamping interp_len to stay within `cbVec`.
|
||||
*/
|
||||
size_t interp_len = WEBRTC_SPL_MIN(index, 4);
|
||||
|
||||
rtc_MsanCheckInitialized(buffer - index - interp_len, sizeof(buffer[0]),
|
||||
index + interp_len);
|
||||
|
||||
ilow = index - interp_len;
|
||||
|
||||
/* copy the first noninterpolated part */
|
||||
ppo = buffer-index;
|
||||
WEBRTC_SPL_MEMCPY_W16(cbVec, ppo, index);
|
||||
|
||||
/* interpolation */
|
||||
ppo = buffer - interp_len;
|
||||
ppi = buffer - index - interp_len;
|
||||
|
||||
/* perform cbVec[ilow+k] = ((ppi[k]*alphaTbl[k])>>15) +
|
||||
((ppo[k]*alphaTbl[interp_len-1-k])>>15);
|
||||
for k = 0..interp_len-1
|
||||
*/
|
||||
WebRtcSpl_ElementwiseVectorMult(&cbVec[ilow], ppi, WebRtcIlbcfix_kAlpha,
|
||||
interp_len, 15);
|
||||
WebRtcSpl_ReverseOrderMultArrayElements(
|
||||
cbVecTmp, ppo, &WebRtcIlbcfix_kAlpha[interp_len - 1], interp_len, 15);
|
||||
WebRtcSpl_AddVectorsAndShift(&cbVec[ilow], &cbVec[ilow], cbVecTmp, interp_len,
|
||||
0);
|
||||
|
||||
/* copy the second noninterpolated part */
|
||||
ppo = buffer - index;
|
||||
/* `tempbuff2` is declared in WebRtcIlbcfix_GetCbVec and is SUBL+5 elements
|
||||
long. `buffer` points one element past the end of that vector, i.e., at
|
||||
tempbuff2+SUBL+5. Since ppo=buffer-index, we cannot read any more than
|
||||
`index` elements from `ppo`.
|
||||
|
||||
`cbVec` is declared to be SUBL elements long in WebRtcIlbcfix_CbConstruct.
|
||||
Therefore, we can only write SUBL-index elements to cbVec+index.
|
||||
|
||||
These two conditions limit the number of elements to copy.
|
||||
*/
|
||||
WEBRTC_SPL_MEMCPY_W16(cbVec+index, ppo, WEBRTC_SPL_MIN(SUBL-index, index));
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_CreateAugmentedVec.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Recreate a specific codebook vector from the augmented part.
|
||||
*
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_CreateAugmentedVec(
|
||||
size_t index, /* (i) Index for the augmented vector to be
|
||||
created */
|
||||
const int16_t* buffer, /* (i) Pointer to the end of the codebook memory
|
||||
that is used for creation of the augmented
|
||||
codebook */
|
||||
int16_t* cbVec); /* (o) The construced codebook vector */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Decode.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/decode.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/do_plc.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/hp_output.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/init_decode.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
#ifndef WEBRTC_ARCH_BIG_ENDIAN
|
||||
#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* main decoder function
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int WebRtcIlbcfix_DecodeImpl(
|
||||
int16_t *decblock, /* (o) decoded signal block */
|
||||
const uint16_t *bytes, /* (i) encoded signal bits */
|
||||
IlbcDecoder *iLBCdec_inst, /* (i/o) the decoder state
|
||||
structure */
|
||||
int16_t mode /* (i) 0: bad packet, PLC,
|
||||
1: normal */
|
||||
) {
|
||||
const int old_mode = iLBCdec_inst->mode;
|
||||
const int old_use_enhancer = iLBCdec_inst->use_enhancer;
|
||||
|
||||
size_t i;
|
||||
int16_t order_plus_one;
|
||||
|
||||
int16_t last_bit;
|
||||
int16_t *data;
|
||||
/* Stack based */
|
||||
int16_t decresidual[BLOCKL_MAX];
|
||||
int16_t PLCresidual[BLOCKL_MAX + LPC_FILTERORDER];
|
||||
int16_t syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)];
|
||||
int16_t PLClpc[LPC_FILTERORDER + 1];
|
||||
#ifndef WEBRTC_ARCH_BIG_ENDIAN
|
||||
uint16_t swapped[NO_OF_WORDS_30MS];
|
||||
#endif
|
||||
iLBC_bits *iLBCbits_inst = (iLBC_bits*)PLCresidual;
|
||||
|
||||
/* Reuse some buffers that are non overlapping in order to save stack memory */
|
||||
data = &PLCresidual[LPC_FILTERORDER];
|
||||
|
||||
if (mode) { /* the data are good */
|
||||
|
||||
/* decode data */
|
||||
|
||||
/* Unpacketize bits into parameters */
|
||||
|
||||
#ifndef WEBRTC_ARCH_BIG_ENDIAN
|
||||
WebRtcIlbcfix_SwapBytes(bytes, iLBCdec_inst->no_of_words, swapped);
|
||||
last_bit = WebRtcIlbcfix_UnpackBits(swapped, iLBCbits_inst, iLBCdec_inst->mode);
|
||||
#else
|
||||
last_bit = WebRtcIlbcfix_UnpackBits(bytes, iLBCbits_inst, iLBCdec_inst->mode);
|
||||
#endif
|
||||
|
||||
/* Check for bit errors */
|
||||
if (iLBCbits_inst->startIdx<1)
|
||||
mode = 0;
|
||||
if ((iLBCdec_inst->mode==20) && (iLBCbits_inst->startIdx>3))
|
||||
mode = 0;
|
||||
if ((iLBCdec_inst->mode==30) && (iLBCbits_inst->startIdx>5))
|
||||
mode = 0;
|
||||
if (last_bit==1)
|
||||
mode = 0;
|
||||
|
||||
if (mode) { /* No bit errors was detected, continue decoding */
|
||||
/* Stack based */
|
||||
int16_t lsfdeq[LPC_FILTERORDER*LPC_N_MAX];
|
||||
int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
|
||||
|
||||
/* adjust index */
|
||||
WebRtcIlbcfix_IndexConvDec(iLBCbits_inst->cb_index);
|
||||
|
||||
/* decode the lsf */
|
||||
WebRtcIlbcfix_SimpleLsfDeQ(lsfdeq, (int16_t*)(iLBCbits_inst->lsf), iLBCdec_inst->lpc_n);
|
||||
WebRtcIlbcfix_LsfCheck(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n);
|
||||
WebRtcIlbcfix_DecoderInterpolateLsp(syntdenum, weightdenum,
|
||||
lsfdeq, LPC_FILTERORDER, iLBCdec_inst);
|
||||
|
||||
/* Decode the residual using the cb and gain indexes */
|
||||
if (!WebRtcIlbcfix_DecodeResidual(iLBCdec_inst, iLBCbits_inst,
|
||||
decresidual, syntdenum))
|
||||
goto error;
|
||||
|
||||
/* preparing the plc for a future loss! */
|
||||
WebRtcIlbcfix_DoThePlc(
|
||||
PLCresidual, PLClpc, 0, decresidual,
|
||||
syntdenum + (LPC_FILTERORDER + 1) * (iLBCdec_inst->nsub - 1),
|
||||
iLBCdec_inst->last_lag, iLBCdec_inst);
|
||||
|
||||
/* Use the output from doThePLC */
|
||||
WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
/* the data is bad (either a PLC call
|
||||
* was made or a bit error was detected)
|
||||
*/
|
||||
|
||||
/* packet loss conceal */
|
||||
|
||||
WebRtcIlbcfix_DoThePlc(PLCresidual, PLClpc, 1, decresidual, syntdenum,
|
||||
iLBCdec_inst->last_lag, iLBCdec_inst);
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
|
||||
|
||||
order_plus_one = LPC_FILTERORDER + 1;
|
||||
|
||||
for (i = 0; i < iLBCdec_inst->nsub; i++) {
|
||||
WEBRTC_SPL_MEMCPY_W16(syntdenum+(i*order_plus_one),
|
||||
PLClpc, order_plus_one);
|
||||
}
|
||||
}
|
||||
|
||||
if ((*iLBCdec_inst).use_enhancer == 1) { /* Enhancer activated */
|
||||
|
||||
/* Update the filter and filter coefficients if there was a packet loss */
|
||||
if (iLBCdec_inst->prev_enh_pl==2) {
|
||||
for (i=0;i<iLBCdec_inst->nsub;i++) {
|
||||
WEBRTC_SPL_MEMCPY_W16(&(iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]),
|
||||
syntdenum, (LPC_FILTERORDER+1));
|
||||
}
|
||||
}
|
||||
|
||||
/* post filtering */
|
||||
(*iLBCdec_inst).last_lag =
|
||||
WebRtcIlbcfix_EnhancerInterface(data, decresidual, iLBCdec_inst);
|
||||
|
||||
/* synthesis filtering */
|
||||
|
||||
/* Set up the filter state */
|
||||
WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
|
||||
|
||||
if (iLBCdec_inst->mode==20) {
|
||||
/* Enhancer has 40 samples delay */
|
||||
i=0;
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
data, data,
|
||||
iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1),
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
|
||||
for (i=1; i < iLBCdec_inst->nsub; i++) {
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
data+i*SUBL, data+i*SUBL,
|
||||
syntdenum+(i-1)*(LPC_FILTERORDER+1),
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
}
|
||||
|
||||
} else if (iLBCdec_inst->mode==30) {
|
||||
/* Enhancer has 80 samples delay */
|
||||
for (i=0; i < 2; i++) {
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
data+i*SUBL, data+i*SUBL,
|
||||
iLBCdec_inst->old_syntdenum + (i+4)*(LPC_FILTERORDER+1),
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
}
|
||||
for (i=2; i < iLBCdec_inst->nsub; i++) {
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
data+i*SUBL, data+i*SUBL,
|
||||
syntdenum+(i-2)*(LPC_FILTERORDER+1),
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the filter state */
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
|
||||
|
||||
} else { /* Enhancer not activated */
|
||||
size_t lag;
|
||||
|
||||
/* Find last lag (since the enhancer is not called to give this info) */
|
||||
lag = 20;
|
||||
if (iLBCdec_inst->mode==20) {
|
||||
lag = WebRtcIlbcfix_XcorrCoef(
|
||||
&decresidual[iLBCdec_inst->blockl-60],
|
||||
&decresidual[iLBCdec_inst->blockl-60-lag],
|
||||
60,
|
||||
80, lag, -1);
|
||||
} else {
|
||||
lag = WebRtcIlbcfix_XcorrCoef(
|
||||
&decresidual[iLBCdec_inst->blockl-ENH_BLOCKL],
|
||||
&decresidual[iLBCdec_inst->blockl-ENH_BLOCKL-lag],
|
||||
ENH_BLOCKL,
|
||||
100, lag, -1);
|
||||
}
|
||||
|
||||
/* Store lag (it is needed if next packet is lost) */
|
||||
(*iLBCdec_inst).last_lag = lag;
|
||||
|
||||
/* copy data and run synthesis filter */
|
||||
WEBRTC_SPL_MEMCPY_W16(data, decresidual, iLBCdec_inst->blockl);
|
||||
|
||||
/* Set up the filter state */
|
||||
WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
|
||||
|
||||
for (i=0; i < iLBCdec_inst->nsub; i++) {
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
data+i*SUBL, data+i*SUBL,
|
||||
syntdenum + i*(LPC_FILTERORDER+1),
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
}
|
||||
|
||||
/* Save the filter state */
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
|
||||
}
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(decblock,data,iLBCdec_inst->blockl);
|
||||
|
||||
/* High pass filter the signal (with upscaling a factor 2 and saturation) */
|
||||
WebRtcIlbcfix_HpOutput(decblock, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
|
||||
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
|
||||
iLBCdec_inst->blockl);
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->old_syntdenum,
|
||||
syntdenum, iLBCdec_inst->nsub*(LPC_FILTERORDER+1));
|
||||
|
||||
iLBCdec_inst->prev_enh_pl=0;
|
||||
|
||||
if (mode==0) { /* PLC was used */
|
||||
iLBCdec_inst->prev_enh_pl=1;
|
||||
}
|
||||
|
||||
return 0; // Success.
|
||||
|
||||
error:
|
||||
// The decoder got sick from eating that data. Reset it and return.
|
||||
WebRtcIlbcfix_InitDecode(iLBCdec_inst, old_mode, old_use_enhancer);
|
||||
return -1; // Error
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Decode.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* main decoder function
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
// Returns 0 on success, -1 on error.
|
||||
ABSL_MUST_USE_RESULT
|
||||
int WebRtcIlbcfix_DecodeImpl(
|
||||
int16_t* decblock, /* (o) decoded signal block */
|
||||
const uint16_t* bytes, /* (i) encoded signal bits */
|
||||
IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state
|
||||
structure */
|
||||
int16_t mode /* (i) 0: bad packet, PLC,
|
||||
1: normal */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DecodeResidual.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/do_plc.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/state_construct.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* frame residual decoder function (subrutine to iLBC_decode)
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
bool WebRtcIlbcfix_DecodeResidual(
|
||||
IlbcDecoder *iLBCdec_inst,
|
||||
/* (i/o) the decoder state structure */
|
||||
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used
|
||||
for the decoding */
|
||||
int16_t *decresidual, /* (o) decoded residual frame */
|
||||
int16_t *syntdenum /* (i) the decoded synthesis filter
|
||||
coefficients */
|
||||
) {
|
||||
size_t meml_gotten, diff, start_pos;
|
||||
size_t subcount, subframe;
|
||||
int16_t *reverseDecresidual = iLBCdec_inst->enh_buf; /* Reversed decoded data, used for decoding backwards in time (reuse memory in state) */
|
||||
int16_t *memVec = iLBCdec_inst->prevResidual; /* Memory for codebook and filter state (reuse memory in state) */
|
||||
int16_t *mem = &memVec[CB_HALFFILTERLEN]; /* Memory for codebook */
|
||||
|
||||
diff = STATE_LEN - iLBCdec_inst->state_short_len;
|
||||
|
||||
if (iLBC_encbits->state_first == 1) {
|
||||
start_pos = (iLBC_encbits->startIdx-1)*SUBL;
|
||||
} else {
|
||||
start_pos = (iLBC_encbits->startIdx-1)*SUBL + diff;
|
||||
}
|
||||
|
||||
/* decode scalar part of start state */
|
||||
|
||||
WebRtcIlbcfix_StateConstruct(iLBC_encbits->idxForMax,
|
||||
iLBC_encbits->idxVec, &syntdenum[(iLBC_encbits->startIdx-1)*(LPC_FILTERORDER+1)],
|
||||
&decresidual[start_pos], iLBCdec_inst->state_short_len
|
||||
);
|
||||
|
||||
if (iLBC_encbits->state_first) { /* put adaptive part in the end */
|
||||
|
||||
/* setup memory */
|
||||
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCdec_inst->state_short_len);
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCdec_inst->state_short_len, decresidual+start_pos,
|
||||
iLBCdec_inst->state_short_len);
|
||||
|
||||
/* construct decoded vector */
|
||||
|
||||
if (!WebRtcIlbcfix_CbConstruct(
|
||||
&decresidual[start_pos + iLBCdec_inst->state_short_len],
|
||||
iLBC_encbits->cb_index, iLBC_encbits->gain_index,
|
||||
mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL, diff))
|
||||
return false; // Error.
|
||||
|
||||
}
|
||||
else {/* put adaptive part in the beginning */
|
||||
|
||||
/* setup memory */
|
||||
|
||||
meml_gotten = iLBCdec_inst->state_short_len;
|
||||
WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
|
||||
decresidual+start_pos, meml_gotten);
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
|
||||
|
||||
/* construct decoded vector */
|
||||
|
||||
if (!WebRtcIlbcfix_CbConstruct(reverseDecresidual, iLBC_encbits->cb_index,
|
||||
iLBC_encbits->gain_index,
|
||||
mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL,
|
||||
diff))
|
||||
return false; // Error.
|
||||
|
||||
/* get decoded residual from reversed vector */
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1],
|
||||
reverseDecresidual, diff);
|
||||
}
|
||||
|
||||
/* counter for predicted subframes */
|
||||
|
||||
subcount=1;
|
||||
|
||||
/* forward prediction of subframes */
|
||||
|
||||
if (iLBCdec_inst->nsub > iLBC_encbits->startIdx + 1) {
|
||||
|
||||
/* setup memory */
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
|
||||
decresidual+(iLBC_encbits->startIdx-1)*SUBL, STATE_LEN);
|
||||
|
||||
/* loop over subframes to encode */
|
||||
|
||||
size_t Nfor = iLBCdec_inst->nsub - iLBC_encbits->startIdx - 1;
|
||||
for (subframe=0; subframe<Nfor; subframe++) {
|
||||
|
||||
/* construct decoded vector */
|
||||
if (!WebRtcIlbcfix_CbConstruct(
|
||||
&decresidual[(iLBC_encbits->startIdx + 1 + subframe) * SUBL],
|
||||
iLBC_encbits->cb_index + subcount * CB_NSTAGES,
|
||||
iLBC_encbits->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
|
||||
SUBL))
|
||||
return false; // Error;
|
||||
|
||||
/* update memory */
|
||||
memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
|
||||
&decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], SUBL);
|
||||
|
||||
subcount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* backward prediction of subframes */
|
||||
|
||||
if (iLBC_encbits->startIdx > 1) {
|
||||
|
||||
/* setup memory */
|
||||
|
||||
meml_gotten = SUBL*(iLBCdec_inst->nsub+1-iLBC_encbits->startIdx);
|
||||
if( meml_gotten > CB_MEML ) {
|
||||
meml_gotten=CB_MEML;
|
||||
}
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
|
||||
decresidual+(iLBC_encbits->startIdx-1)*SUBL, meml_gotten);
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
|
||||
|
||||
/* loop over subframes to decode */
|
||||
|
||||
size_t Nback = iLBC_encbits->startIdx - 1;
|
||||
for (subframe=0; subframe<Nback; subframe++) {
|
||||
|
||||
/* construct decoded vector */
|
||||
if (!WebRtcIlbcfix_CbConstruct(
|
||||
&reverseDecresidual[subframe * SUBL],
|
||||
iLBC_encbits->cb_index + subcount * CB_NSTAGES,
|
||||
iLBC_encbits->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
|
||||
SUBL))
|
||||
return false; // Error.
|
||||
|
||||
/* update memory */
|
||||
memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
|
||||
&reverseDecresidual[subframe*SUBL], SUBL);
|
||||
|
||||
subcount++;
|
||||
}
|
||||
|
||||
/* get decoded residual from reversed vector */
|
||||
WebRtcSpl_MemCpyReversedOrder(decresidual+SUBL*Nback-1,
|
||||
reverseDecresidual, SUBL*Nback);
|
||||
}
|
||||
|
||||
return true; // Success.
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DecodeResidual.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* frame residual decoder function (subrutine to iLBC_decode)
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
// Returns true on success, false on failure. In case of failure, the decoder
|
||||
// state may be corrupted and needs resetting.
|
||||
ABSL_MUST_USE_RESULT
|
||||
bool WebRtcIlbcfix_DecodeResidual(
|
||||
IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state structure */
|
||||
iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits, which are used
|
||||
for the decoding */
|
||||
int16_t* decresidual, /* (o) decoded residual frame */
|
||||
int16_t* syntdenum /* (i) the decoded synthesis filter
|
||||
coefficients */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DecoderInterpolateLsp.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* obtain synthesis and weighting filters form lsf coefficients
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_DecoderInterpolateLsp(
|
||||
int16_t *syntdenum, /* (o) synthesis filter coefficients */
|
||||
int16_t *weightdenum, /* (o) weighting denumerator
|
||||
coefficients */
|
||||
int16_t *lsfdeq, /* (i) dequantized lsf coefficients */
|
||||
int16_t length, /* (i) length of lsf coefficient vector */
|
||||
IlbcDecoder *iLBCdec_inst
|
||||
/* (i) the decoder state structure */
|
||||
){
|
||||
size_t i;
|
||||
int pos, lp_length;
|
||||
int16_t lp[LPC_FILTERORDER + 1], *lsfdeq2;
|
||||
|
||||
lsfdeq2 = lsfdeq + length;
|
||||
lp_length = length + 1;
|
||||
|
||||
if (iLBCdec_inst->mode==30) {
|
||||
/* subframe 1: Interpolation between old and first LSF */
|
||||
|
||||
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, (*iLBCdec_inst).lsfdeqold, lsfdeq,
|
||||
WebRtcIlbcfix_kLsfWeight30ms[0], length);
|
||||
WEBRTC_SPL_MEMCPY_W16(syntdenum,lp,lp_length);
|
||||
WebRtcIlbcfix_BwExpand(weightdenum, lp, (int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
|
||||
|
||||
/* subframes 2 to 6: interpolation between first and last LSF */
|
||||
|
||||
pos = lp_length;
|
||||
for (i = 1; i < 6; i++) {
|
||||
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, lsfdeq, lsfdeq2,
|
||||
WebRtcIlbcfix_kLsfWeight30ms[i], length);
|
||||
WEBRTC_SPL_MEMCPY_W16(syntdenum + pos,lp,lp_length);
|
||||
WebRtcIlbcfix_BwExpand(weightdenum + pos, lp,
|
||||
(int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
|
||||
pos += lp_length;
|
||||
}
|
||||
} else { /* iLBCdec_inst->mode=20 */
|
||||
/* subframes 1 to 4: interpolation between old and new LSF */
|
||||
pos = 0;
|
||||
for (i = 0; i < iLBCdec_inst->nsub; i++) {
|
||||
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, iLBCdec_inst->lsfdeqold, lsfdeq,
|
||||
WebRtcIlbcfix_kLsfWeight20ms[i], length);
|
||||
WEBRTC_SPL_MEMCPY_W16(syntdenum+pos,lp,lp_length);
|
||||
WebRtcIlbcfix_BwExpand(weightdenum+pos, lp,
|
||||
(int16_t*)WebRtcIlbcfix_kLpcChirpSyntDenum, (int16_t)lp_length);
|
||||
pos += lp_length;
|
||||
}
|
||||
}
|
||||
|
||||
/* update memory */
|
||||
|
||||
if (iLBCdec_inst->mode==30) {
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq2, length);
|
||||
} else {
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq, length);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DecoderInterpolateLsp.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* obtain synthesis and weighting filters form lsf coefficients
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_DecoderInterpolateLsp(
|
||||
int16_t* syntdenum, /* (o) synthesis filter coefficients */
|
||||
int16_t* weightdenum, /* (o) weighting denumerator
|
||||
coefficients */
|
||||
int16_t* lsfdeq, /* (i) dequantized lsf coefficients */
|
||||
int16_t length, /* (i) length of lsf coefficient vector */
|
||||
IlbcDecoder* iLBCdec_inst
|
||||
/* (i) the decoder state structure */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
define.h
|
||||
|
||||
******************************************************************/
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
/* general codec settings */
|
||||
|
||||
#define FS 8000
|
||||
#define BLOCKL_20MS 160
|
||||
#define BLOCKL_30MS 240
|
||||
#define BLOCKL_MAX 240
|
||||
#define NSUB_20MS 4
|
||||
#define NSUB_30MS 6
|
||||
#define NSUB_MAX 6
|
||||
#define NASUB_20MS 2
|
||||
#define NASUB_30MS 4
|
||||
#define NASUB_MAX 4
|
||||
#define SUBL 40
|
||||
#define STATE_LEN 80
|
||||
#define STATE_SHORT_LEN_30MS 58
|
||||
#define STATE_SHORT_LEN_20MS 57
|
||||
|
||||
/* LPC settings */
|
||||
|
||||
#define LPC_FILTERORDER 10
|
||||
#define LPC_LOOKBACK 60
|
||||
#define LPC_N_20MS 1
|
||||
#define LPC_N_30MS 2
|
||||
#define LPC_N_MAX 2
|
||||
#define LPC_ASYMDIFF 20
|
||||
#define LSF_NSPLIT 3
|
||||
#define LSF_NUMBER_OF_STEPS 4
|
||||
#define LPC_HALFORDER 5
|
||||
#define COS_GRID_POINTS 60
|
||||
|
||||
/* cb settings */
|
||||
|
||||
#define CB_NSTAGES 3
|
||||
#define CB_EXPAND 2
|
||||
#define CB_MEML 147
|
||||
#define CB_FILTERLEN (2 * 4)
|
||||
#define CB_HALFFILTERLEN 4
|
||||
#define CB_RESRANGE 34
|
||||
#define CB_MAXGAIN_FIXQ6 83 /* error = -0.24% */
|
||||
#define CB_MAXGAIN_FIXQ14 21299
|
||||
|
||||
/* enhancer */
|
||||
|
||||
#define ENH_BLOCKL 80 /* block length */
|
||||
#define ENH_BLOCKL_HALF (ENH_BLOCKL / 2)
|
||||
#define ENH_HL \
|
||||
3 /* 2*ENH_HL+1 is number blocks \
|
||||
in said second \
|
||||
sequence */
|
||||
#define ENH_SLOP \
|
||||
2 /* max difference estimated and \
|
||||
correct pitch period */
|
||||
#define ENH_PLOCSL \
|
||||
8 /* pitch-estimates and \
|
||||
pitch-locations buffer \
|
||||
length */
|
||||
#define ENH_OVERHANG 2
|
||||
#define ENH_UPS0 4 /* upsampling rate */
|
||||
#define ENH_FL0 3 /* 2*FLO+1 is the length of each filter */
|
||||
#define ENH_FLO_MULT2_PLUS1 7
|
||||
#define ENH_VECTL (ENH_BLOCKL + 2 * ENH_FL0)
|
||||
#define ENH_CORRDIM (2 * ENH_SLOP + 1)
|
||||
#define ENH_NBLOCKS (BLOCKL / ENH_BLOCKL)
|
||||
#define ENH_NBLOCKS_EXTRA 5
|
||||
#define ENH_NBLOCKS_TOT 8 /* ENH_NBLOCKS+ENH_NBLOCKS_EXTRA */
|
||||
#define ENH_BUFL (ENH_NBLOCKS_TOT) * ENH_BLOCKL
|
||||
#define ENH_BUFL_FILTEROVERHEAD 3
|
||||
#define ENH_A0 819 /* Q14 */
|
||||
#define ENH_A0_MINUS_A0A0DIV4 848256041 /* Q34 */
|
||||
#define ENH_A0DIV2 26843546 /* Q30 */
|
||||
|
||||
/* PLC */
|
||||
|
||||
/* Down sampling */
|
||||
|
||||
#define FILTERORDER_DS_PLUS1 7
|
||||
#define DELAY_DS 3
|
||||
#define FACTOR_DS 2
|
||||
|
||||
/* bit stream defs */
|
||||
|
||||
#define NO_OF_BYTES_20MS 38
|
||||
#define NO_OF_BYTES_30MS 50
|
||||
#define NO_OF_WORDS_20MS 19
|
||||
#define NO_OF_WORDS_30MS 25
|
||||
#define STATE_BITS 3
|
||||
#define BYTE_LEN 8
|
||||
#define ULP_CLASSES 3
|
||||
|
||||
/* help parameters */
|
||||
|
||||
#define TWO_PI_FIX 25736 /* Q12 */
|
||||
|
||||
/* Constants for codebook search and creation */
|
||||
|
||||
#define ST_MEM_L_TBL 85
|
||||
#define MEM_LF_TBL 147
|
||||
|
||||
/* Struct for the bits */
|
||||
typedef struct iLBC_bits_t_ {
|
||||
int16_t lsf[LSF_NSPLIT * LPC_N_MAX];
|
||||
int16_t cb_index[CB_NSTAGES * (NASUB_MAX + 1)]; /* First CB_NSTAGES values
|
||||
contains extra CB index */
|
||||
int16_t gain_index[CB_NSTAGES * (NASUB_MAX + 1)]; /* First CB_NSTAGES values
|
||||
contains extra CB gain */
|
||||
size_t idxForMax;
|
||||
int16_t state_first;
|
||||
int16_t idxVec[STATE_SHORT_LEN_30MS];
|
||||
int16_t firstbits;
|
||||
size_t startIdx;
|
||||
} iLBC_bits;
|
||||
|
||||
/* type definition encoder instance */
|
||||
typedef struct IlbcEncoder_ {
|
||||
/* flag for frame size mode */
|
||||
int16_t mode;
|
||||
|
||||
/* basic parameters for different frame sizes */
|
||||
size_t blockl;
|
||||
size_t nsub;
|
||||
int16_t nasub;
|
||||
size_t no_of_bytes, no_of_words;
|
||||
int16_t lpc_n;
|
||||
size_t state_short_len;
|
||||
|
||||
/* analysis filter state */
|
||||
int16_t anaMem[LPC_FILTERORDER];
|
||||
|
||||
/* Fix-point old lsf parameters for interpolation */
|
||||
int16_t lsfold[LPC_FILTERORDER];
|
||||
int16_t lsfdeqold[LPC_FILTERORDER];
|
||||
|
||||
/* signal buffer for LP analysis */
|
||||
int16_t lpc_buffer[LPC_LOOKBACK + BLOCKL_MAX];
|
||||
|
||||
/* state of input HP filter */
|
||||
int16_t hpimemx[2];
|
||||
int16_t hpimemy[4];
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
int16_t weightdenumbuf[66];
|
||||
int16_t past_samples[160];
|
||||
uint16_t bytes[25];
|
||||
int16_t section;
|
||||
int16_t Nfor_flag;
|
||||
int16_t Nback_flag;
|
||||
int16_t start_pos;
|
||||
size_t diff;
|
||||
#endif
|
||||
|
||||
} IlbcEncoder;
|
||||
|
||||
/* type definition decoder instance */
|
||||
typedef struct IlbcDecoder_ {
|
||||
/* flag for frame size mode */
|
||||
int16_t mode;
|
||||
|
||||
/* basic parameters for different frame sizes */
|
||||
size_t blockl;
|
||||
size_t nsub;
|
||||
int16_t nasub;
|
||||
size_t no_of_bytes, no_of_words;
|
||||
int16_t lpc_n;
|
||||
size_t state_short_len;
|
||||
|
||||
/* synthesis filter state */
|
||||
int16_t syntMem[LPC_FILTERORDER];
|
||||
|
||||
/* old LSF for interpolation */
|
||||
int16_t lsfdeqold[LPC_FILTERORDER];
|
||||
|
||||
/* pitch lag estimated in enhancer and used in PLC */
|
||||
size_t last_lag;
|
||||
|
||||
/* PLC state information */
|
||||
int consPLICount, prev_enh_pl;
|
||||
int16_t perSquare;
|
||||
|
||||
int16_t prevScale, prevPLI;
|
||||
size_t prevLag;
|
||||
int16_t prevLpc[LPC_FILTERORDER + 1];
|
||||
int16_t prevResidual[NSUB_MAX * SUBL];
|
||||
int16_t seed;
|
||||
|
||||
/* previous synthesis filter parameters */
|
||||
|
||||
int16_t old_syntdenum[(LPC_FILTERORDER + 1) * NSUB_MAX];
|
||||
|
||||
/* state of output HP filter */
|
||||
int16_t hpimemx[2];
|
||||
int16_t hpimemy[4];
|
||||
|
||||
/* enhancer state information */
|
||||
int use_enhancer;
|
||||
int16_t enh_buf[ENH_BUFL + ENH_BUFL_FILTEROVERHEAD];
|
||||
size_t enh_period[ENH_NBLOCKS_TOT];
|
||||
|
||||
} IlbcDecoder;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DoThePlc.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/do_plc.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Packet loss concealment routine. Conceals a residual signal
|
||||
* and LP parameters. If no packet loss, update state.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_DoThePlc(
|
||||
int16_t *PLCresidual, /* (o) concealed residual */
|
||||
int16_t *PLClpc, /* (o) concealed LP parameters */
|
||||
int16_t PLI, /* (i) packet loss indicator
|
||||
0 - no PL, 1 = PL */
|
||||
int16_t *decresidual, /* (i) decoded residual */
|
||||
int16_t *lpc, /* (i) decoded LPC (only used for no PL) */
|
||||
size_t inlag, /* (i) pitch lag */
|
||||
IlbcDecoder *iLBCdec_inst
|
||||
/* (i/o) decoder instance */
|
||||
){
|
||||
size_t i;
|
||||
int32_t cross, ener, cross_comp, ener_comp = 0;
|
||||
int32_t measure, maxMeasure, energy;
|
||||
int32_t noise_energy_threshold_30dB;
|
||||
int16_t max, crossSquareMax, crossSquare;
|
||||
size_t j, lag, randlag;
|
||||
int16_t tmp1, tmp2;
|
||||
int16_t shift1, shift2, shift3, shiftMax;
|
||||
int16_t scale3;
|
||||
size_t corrLen;
|
||||
int32_t tmpW32, tmp2W32;
|
||||
int16_t use_gain;
|
||||
int16_t tot_gain;
|
||||
int16_t max_perSquare;
|
||||
int16_t scale1, scale2;
|
||||
int16_t totscale;
|
||||
int32_t nom;
|
||||
int16_t denom;
|
||||
int16_t pitchfact;
|
||||
size_t use_lag;
|
||||
int ind;
|
||||
int16_t randvec[BLOCKL_MAX];
|
||||
|
||||
/* Packet Loss */
|
||||
if (PLI == 1) {
|
||||
|
||||
(*iLBCdec_inst).consPLICount += 1;
|
||||
|
||||
/* if previous frame not lost,
|
||||
determine pitch pred. gain */
|
||||
|
||||
if (iLBCdec_inst->prevPLI != 1) {
|
||||
|
||||
/* Maximum 60 samples are correlated, preserve as high accuracy
|
||||
as possible without getting overflow */
|
||||
max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual,
|
||||
iLBCdec_inst->blockl);
|
||||
scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25;
|
||||
if (scale3 < 0) {
|
||||
scale3 = 0;
|
||||
}
|
||||
|
||||
/* Store scale for use when interpolating between the
|
||||
* concealment and the received packet */
|
||||
iLBCdec_inst->prevScale = scale3;
|
||||
|
||||
/* Search around the previous lag +/-3 to find the
|
||||
best pitch period */
|
||||
lag = inlag - 3;
|
||||
|
||||
/* Guard against getting outside the frame */
|
||||
corrLen = (size_t)WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3));
|
||||
|
||||
WebRtcIlbcfix_CompCorr( &cross, &ener,
|
||||
iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3);
|
||||
|
||||
/* Normalize and store cross^2 and the number of shifts */
|
||||
shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15;
|
||||
crossSquareMax = (int16_t)((
|
||||
(int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax) *
|
||||
(int16_t)WEBRTC_SPL_SHIFT_W32(cross, -shiftMax)) >> 15);
|
||||
|
||||
for (j=inlag-2;j<=inlag+3;j++) {
|
||||
WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp,
|
||||
iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3);
|
||||
|
||||
/* Use the criteria (corr*corr)/energy to compare if
|
||||
this lag is better or not. To avoid the division,
|
||||
do a cross multiplication */
|
||||
shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15;
|
||||
crossSquare = (int16_t)((
|
||||
(int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1) *
|
||||
(int16_t)WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1)) >> 15);
|
||||
|
||||
shift2 = WebRtcSpl_GetSizeInBits(ener)-15;
|
||||
measure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, -shift2) * crossSquare;
|
||||
|
||||
shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15;
|
||||
maxMeasure = (int16_t)WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3) *
|
||||
crossSquareMax;
|
||||
|
||||
/* Calculate shift value, so that the two measures can
|
||||
be put in the same Q domain */
|
||||
if(2 * shiftMax + shift3 > 2 * shift1 + shift2) {
|
||||
tmp1 =
|
||||
WEBRTC_SPL_MIN(31, 2 * shiftMax + shift3 - 2 * shift1 - shift2);
|
||||
tmp2 = 0;
|
||||
} else {
|
||||
tmp1 = 0;
|
||||
tmp2 =
|
||||
WEBRTC_SPL_MIN(31, 2 * shift1 + shift2 - 2 * shiftMax - shift3);
|
||||
}
|
||||
|
||||
if ((measure>>tmp1) > (maxMeasure>>tmp2)) {
|
||||
/* New lag is better => record lag, measure and domain */
|
||||
lag = j;
|
||||
crossSquareMax = crossSquare;
|
||||
cross = cross_comp;
|
||||
shiftMax = shift1;
|
||||
ener = ener_comp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the periodicity for the lag with the maximum correlation.
|
||||
|
||||
Definition of the periodicity:
|
||||
abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2)))
|
||||
|
||||
Work in the Square domain to simplify the calculations
|
||||
max_perSquare is less than 1 (in Q15)
|
||||
*/
|
||||
tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
|
||||
&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
|
||||
corrLen, scale3);
|
||||
|
||||
if ((tmp2W32>0)&&(ener_comp>0)) {
|
||||
/* norm energies to int16_t, compute the product of the energies and
|
||||
use the upper int16_t as the denominator */
|
||||
|
||||
scale1=(int16_t)WebRtcSpl_NormW32(tmp2W32)-16;
|
||||
tmp1=(int16_t)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1);
|
||||
|
||||
scale2=(int16_t)WebRtcSpl_NormW32(ener)-16;
|
||||
tmp2=(int16_t)WEBRTC_SPL_SHIFT_W32(ener, scale2);
|
||||
denom = (int16_t)((tmp1 * tmp2) >> 16); /* in Q(scale1+scale2-16) */
|
||||
|
||||
/* Square the cross correlation and norm it such that max_perSquare
|
||||
will be in Q15 after the division */
|
||||
|
||||
totscale = scale1+scale2-1;
|
||||
tmp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1));
|
||||
tmp2 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1));
|
||||
|
||||
nom = tmp1 * tmp2;
|
||||
max_perSquare = (int16_t)WebRtcSpl_DivW32W16(nom, denom);
|
||||
|
||||
} else {
|
||||
max_perSquare = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* previous frame lost, use recorded lag and gain */
|
||||
|
||||
else {
|
||||
lag = iLBCdec_inst->prevLag;
|
||||
max_perSquare = iLBCdec_inst->perSquare;
|
||||
}
|
||||
|
||||
/* Attenuate signal and scale down pitch pred gain if
|
||||
several frames lost consecutively */
|
||||
|
||||
use_gain = 32767; /* 1.0 in Q15 */
|
||||
|
||||
if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) {
|
||||
use_gain = 29491; /* 0.9 in Q15 */
|
||||
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) {
|
||||
use_gain = 22938; /* 0.7 in Q15 */
|
||||
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) {
|
||||
use_gain = 16384; /* 0.5 in Q15 */
|
||||
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) {
|
||||
use_gain = 0; /* 0.0 in Q15 */
|
||||
}
|
||||
|
||||
/* Compute mixing factor of picth repeatition and noise:
|
||||
for max_per>0.7 set periodicity to 1.0
|
||||
0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4)
|
||||
max_per<0.4 set periodicity to 0.0
|
||||
*/
|
||||
|
||||
if (max_perSquare>7868) { /* periodicity > 0.7 (0.7^4=0.2401 in Q15) */
|
||||
pitchfact = 32767;
|
||||
} else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */
|
||||
/* find best index and interpolate from that */
|
||||
ind = 5;
|
||||
while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) {
|
||||
ind--;
|
||||
}
|
||||
/* pitch fact is approximated by first order */
|
||||
tmpW32 = (int32_t)WebRtcIlbcfix_kPlcPitchFact[ind] +
|
||||
((WebRtcIlbcfix_kPlcPfSlope[ind] *
|
||||
(max_perSquare - WebRtcIlbcfix_kPlcPerSqr[ind])) >> 11);
|
||||
|
||||
pitchfact = (int16_t)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */
|
||||
|
||||
} else { /* periodicity < 0.4 */
|
||||
pitchfact = 0;
|
||||
}
|
||||
|
||||
/* avoid repetition of same pitch cycle (buzzyness) */
|
||||
use_lag = lag;
|
||||
if (lag<80) {
|
||||
use_lag = 2*lag;
|
||||
}
|
||||
|
||||
/* compute concealed residual */
|
||||
noise_energy_threshold_30dB = (int32_t)iLBCdec_inst->blockl * 900;
|
||||
energy = 0;
|
||||
for (i=0; i<iLBCdec_inst->blockl; i++) {
|
||||
|
||||
/* noise component - 52 < randlagFIX < 117 */
|
||||
iLBCdec_inst->seed = (int16_t)(iLBCdec_inst->seed * 31821 + 13849);
|
||||
randlag = 53 + (iLBCdec_inst->seed & 63);
|
||||
if (randlag > i) {
|
||||
randvec[i] =
|
||||
iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - randlag];
|
||||
} else {
|
||||
randvec[i] = iLBCdec_inst->prevResidual[i - randlag];
|
||||
}
|
||||
|
||||
/* pitch repeatition component */
|
||||
if (use_lag > i) {
|
||||
PLCresidual[i] =
|
||||
iLBCdec_inst->prevResidual[iLBCdec_inst->blockl + i - use_lag];
|
||||
} else {
|
||||
PLCresidual[i] = PLCresidual[i - use_lag];
|
||||
}
|
||||
|
||||
/* Attinuate total gain for each 10 ms */
|
||||
if (i<80) {
|
||||
tot_gain=use_gain;
|
||||
} else if (i<160) {
|
||||
tot_gain = (int16_t)((31130 * use_gain) >> 15); /* 0.95*use_gain */
|
||||
} else {
|
||||
tot_gain = (int16_t)((29491 * use_gain) >> 15); /* 0.9*use_gain */
|
||||
}
|
||||
|
||||
|
||||
/* mix noise and pitch repeatition */
|
||||
PLCresidual[i] = (int16_t)((tot_gain *
|
||||
((pitchfact * PLCresidual[i] + (32767 - pitchfact) * randvec[i] +
|
||||
16384) >> 15)) >> 15);
|
||||
|
||||
/* Compute energy until threshold for noise energy is reached */
|
||||
if (energy < noise_energy_threshold_30dB) {
|
||||
energy += PLCresidual[i] * PLCresidual[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* less than 30 dB, use only noise */
|
||||
if (energy < noise_energy_threshold_30dB) {
|
||||
for (i=0; i<iLBCdec_inst->blockl; i++) {
|
||||
PLCresidual[i] = randvec[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* use the old LPC */
|
||||
WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1);
|
||||
|
||||
/* Update state in case there are multiple frame losses */
|
||||
iLBCdec_inst->prevLag = lag;
|
||||
iLBCdec_inst->perSquare = max_perSquare;
|
||||
}
|
||||
|
||||
/* no packet loss, copy input */
|
||||
|
||||
else {
|
||||
WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl);
|
||||
WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1));
|
||||
iLBCdec_inst->consPLICount = 0;
|
||||
}
|
||||
|
||||
/* update state */
|
||||
iLBCdec_inst->prevPLI = PLI;
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1));
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_DoThePlc.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Packet loss concealment routine. Conceals a residual signal
|
||||
* and LP parameters. If no packet loss, update state.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_DoThePlc(
|
||||
int16_t* PLCresidual, /* (o) concealed residual */
|
||||
int16_t* PLClpc, /* (o) concealed LP parameters */
|
||||
int16_t PLI, /* (i) packet loss indicator
|
||||
0 - no PL, 1 = PL */
|
||||
int16_t* decresidual, /* (i) decoded residual */
|
||||
int16_t* lpc, /* (i) decoded LPC (only used for no PL) */
|
||||
size_t inlag, /* (i) pitch lag */
|
||||
IlbcDecoder* iLBCdec_inst
|
||||
/* (i/o) decoder instance */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Encode.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/encode.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_construct.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/cb_search.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/hp_input.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/state_construct.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/state_search.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
|
||||
#endif
|
||||
|
||||
#ifndef WEBRTC_ARCH_BIG_ENDIAN
|
||||
#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* main encoder function
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_EncodeImpl(
|
||||
uint16_t *bytes, /* (o) encoded data bits iLBC */
|
||||
const int16_t *block, /* (i) speech vector to encode */
|
||||
IlbcEncoder *iLBCenc_inst /* (i/o) the general encoder
|
||||
state */
|
||||
){
|
||||
size_t n, meml_gotten, Nfor;
|
||||
size_t diff, start_pos;
|
||||
size_t index;
|
||||
size_t subcount, subframe;
|
||||
size_t start_count, end_count;
|
||||
int16_t *residual;
|
||||
int32_t en1, en2;
|
||||
int16_t scale, max;
|
||||
int16_t *syntdenum;
|
||||
int16_t *decresidual;
|
||||
int16_t *reverseResidual;
|
||||
int16_t *reverseDecresidual;
|
||||
/* Stack based */
|
||||
int16_t weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
|
||||
int16_t dataVec[BLOCKL_MAX + LPC_FILTERORDER];
|
||||
int16_t memVec[CB_MEML+CB_FILTERLEN];
|
||||
int16_t bitsMemory[sizeof(iLBC_bits)/sizeof(int16_t)];
|
||||
iLBC_bits *iLBCbits_inst = (iLBC_bits*)bitsMemory;
|
||||
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
int16_t *weightdenumbuf = iLBCenc_inst->weightdenumbuf;
|
||||
int16_t last_bit;
|
||||
#endif
|
||||
|
||||
int16_t *data = &dataVec[LPC_FILTERORDER];
|
||||
int16_t *mem = &memVec[CB_HALFFILTERLEN];
|
||||
|
||||
/* Reuse som buffers to save stack memory */
|
||||
residual = &iLBCenc_inst->lpc_buffer[LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl];
|
||||
syntdenum = mem; /* syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX] and mem are used non overlapping in the code */
|
||||
decresidual = residual; /* Already encoded residual is overwritten by the decoded version */
|
||||
reverseResidual = data; /* data and reverseResidual are used non overlapping in the code */
|
||||
reverseDecresidual = reverseResidual; /* Already encoded residual is overwritten by the decoded version */
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
|
||||
WebRtcSpl_MemSetW16 ( (int16_t *) iLBCbits_inst, 0,
|
||||
sizeof(iLBC_bits) / sizeof(int16_t) );
|
||||
|
||||
start_pos = iLBCenc_inst->start_pos;
|
||||
diff = iLBCenc_inst->diff;
|
||||
|
||||
if (iLBCenc_inst->section != 0){
|
||||
WEBRTC_SPL_MEMCPY_W16 (weightdenum, weightdenumbuf,
|
||||
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
|
||||
/* Un-Packetize the frame into parameters */
|
||||
last_bit = WebRtcIlbcfix_UnpackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
if (last_bit)
|
||||
return;
|
||||
/* adjust index */
|
||||
WebRtcIlbcfix_IndexConvDec (iLBCbits_inst->cb_index);
|
||||
|
||||
if (iLBCenc_inst->section == 1){
|
||||
/* Save first 80 samples of a 160/240 sample frame for 20/30msec */
|
||||
WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples, block, 80);
|
||||
}
|
||||
else{ // iLBCenc_inst->section == 2 AND mode = 30ms
|
||||
/* Save second 80 samples of a 240 sample frame for 30msec */
|
||||
WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples + 80, block, 80);
|
||||
}
|
||||
}
|
||||
else{ // iLBCenc_inst->section == 0
|
||||
/* form a complete frame of 160/240 for 20msec/30msec mode */
|
||||
WEBRTC_SPL_MEMCPY_W16 (data + (iLBCenc_inst->mode * 8) - 80, block, 80);
|
||||
WEBRTC_SPL_MEMCPY_W16 (data, iLBCenc_inst->past_samples,
|
||||
(iLBCenc_inst->mode * 8) - 80);
|
||||
iLBCenc_inst->Nfor_flag = 0;
|
||||
iLBCenc_inst->Nback_flag = 0;
|
||||
#else
|
||||
/* copy input block to data*/
|
||||
WEBRTC_SPL_MEMCPY_W16(data,block,iLBCenc_inst->blockl);
|
||||
#endif
|
||||
|
||||
/* high pass filtering of input signal and scale down the residual (*0.5) */
|
||||
WebRtcIlbcfix_HpInput(data, (int16_t*)WebRtcIlbcfix_kHpInCoefs,
|
||||
iLBCenc_inst->hpimemy, iLBCenc_inst->hpimemx,
|
||||
iLBCenc_inst->blockl);
|
||||
|
||||
/* LPC of hp filtered input data */
|
||||
WebRtcIlbcfix_LpcEncode(syntdenum, weightdenum, iLBCbits_inst->lsf, data,
|
||||
iLBCenc_inst);
|
||||
|
||||
/* Set up state */
|
||||
WEBRTC_SPL_MEMCPY_W16(dataVec, iLBCenc_inst->anaMem, LPC_FILTERORDER);
|
||||
|
||||
/* inverse filter to get residual */
|
||||
for (n=0; n<iLBCenc_inst->nsub; n++ ) {
|
||||
WebRtcSpl_FilterMAFastQ12(
|
||||
&data[n*SUBL], &residual[n*SUBL],
|
||||
&syntdenum[n*(LPC_FILTERORDER+1)],
|
||||
LPC_FILTERORDER+1, SUBL);
|
||||
}
|
||||
|
||||
/* Copy the state for next frame */
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->anaMem, &data[iLBCenc_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
|
||||
|
||||
/* find state location */
|
||||
|
||||
iLBCbits_inst->startIdx = WebRtcIlbcfix_FrameClassify(iLBCenc_inst,residual);
|
||||
|
||||
/* check if state should be in first or last part of the
|
||||
two subframes */
|
||||
|
||||
index = (iLBCbits_inst->startIdx-1)*SUBL;
|
||||
max=WebRtcSpl_MaxAbsValueW16(&residual[index], 2*SUBL);
|
||||
scale = WebRtcSpl_GetSizeInBits((uint32_t)(max * max));
|
||||
|
||||
/* Scale to maximum 25 bits so that the MAC won't cause overflow */
|
||||
scale = scale - 25;
|
||||
if(scale < 0) {
|
||||
scale = 0;
|
||||
}
|
||||
|
||||
diff = STATE_LEN - iLBCenc_inst->state_short_len;
|
||||
en1=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
|
||||
iLBCenc_inst->state_short_len, scale);
|
||||
index += diff;
|
||||
en2=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
|
||||
iLBCenc_inst->state_short_len, scale);
|
||||
if (en1 > en2) {
|
||||
iLBCbits_inst->state_first = 1;
|
||||
start_pos = (iLBCbits_inst->startIdx-1)*SUBL;
|
||||
} else {
|
||||
iLBCbits_inst->state_first = 0;
|
||||
start_pos = (iLBCbits_inst->startIdx-1)*SUBL + diff;
|
||||
}
|
||||
|
||||
/* scalar quantization of state */
|
||||
|
||||
WebRtcIlbcfix_StateSearch(iLBCenc_inst, iLBCbits_inst, &residual[start_pos],
|
||||
&syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
|
||||
&weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)]);
|
||||
|
||||
WebRtcIlbcfix_StateConstruct(iLBCbits_inst->idxForMax, iLBCbits_inst->idxVec,
|
||||
&syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
|
||||
&decresidual[start_pos], iLBCenc_inst->state_short_len
|
||||
);
|
||||
|
||||
/* predictive quantization in state */
|
||||
|
||||
if (iLBCbits_inst->state_first) { /* put adaptive part in the end */
|
||||
|
||||
/* setup memory */
|
||||
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCenc_inst->state_short_len,
|
||||
decresidual+start_pos, iLBCenc_inst->state_short_len);
|
||||
|
||||
/* encode subframes */
|
||||
|
||||
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
|
||||
&residual[start_pos+iLBCenc_inst->state_short_len],
|
||||
mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
|
||||
&weightdenum[iLBCbits_inst->startIdx*(LPC_FILTERORDER+1)], 0);
|
||||
|
||||
/* construct decoded vector */
|
||||
|
||||
RTC_CHECK(WebRtcIlbcfix_CbConstruct(
|
||||
&decresidual[start_pos + iLBCenc_inst->state_short_len],
|
||||
iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
|
||||
mem + CB_MEML - ST_MEM_L_TBL, ST_MEM_L_TBL, diff));
|
||||
|
||||
}
|
||||
else { /* put adaptive part in the beginning */
|
||||
|
||||
/* create reversed vectors for prediction */
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(&reverseResidual[diff-1],
|
||||
&residual[(iLBCbits_inst->startIdx+1)*SUBL-STATE_LEN], diff);
|
||||
|
||||
/* setup memory */
|
||||
|
||||
meml_gotten = iLBCenc_inst->state_short_len;
|
||||
WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[start_pos], meml_gotten);
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - iLBCenc_inst->state_short_len);
|
||||
|
||||
/* encode subframes */
|
||||
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
|
||||
reverseResidual, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
|
||||
&weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
|
||||
0);
|
||||
|
||||
/* construct decoded vector */
|
||||
RTC_CHECK(WebRtcIlbcfix_CbConstruct(
|
||||
reverseDecresidual, iLBCbits_inst->cb_index,
|
||||
iLBCbits_inst->gain_index, mem + CB_MEML - ST_MEM_L_TBL,
|
||||
ST_MEM_L_TBL, diff));
|
||||
|
||||
/* get decoded residual from reversed vector */
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff);
|
||||
}
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
iLBCenc_inst->start_pos = start_pos;
|
||||
iLBCenc_inst->diff = diff;
|
||||
iLBCenc_inst->section++;
|
||||
/* adjust index */
|
||||
WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
|
||||
/* Packetize the parameters into the frame */
|
||||
WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
|
||||
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* forward prediction of subframes */
|
||||
|
||||
Nfor = iLBCenc_inst->nsub-iLBCbits_inst->startIdx-1;
|
||||
|
||||
/* counter for predicted subframes */
|
||||
#ifdef SPLIT_10MS
|
||||
if (iLBCenc_inst->mode == 20)
|
||||
{
|
||||
subcount = 1;
|
||||
}
|
||||
if (iLBCenc_inst->mode == 30)
|
||||
{
|
||||
if (iLBCenc_inst->section == 1)
|
||||
{
|
||||
subcount = 1;
|
||||
}
|
||||
if (iLBCenc_inst->section == 2)
|
||||
{
|
||||
subcount = 3;
|
||||
}
|
||||
}
|
||||
#else
|
||||
subcount=1;
|
||||
#endif
|
||||
|
||||
if( Nfor > 0 ){
|
||||
|
||||
/* setup memory */
|
||||
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
|
||||
decresidual+(iLBCbits_inst->startIdx-1)*SUBL, STATE_LEN);
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
if (iLBCenc_inst->Nfor_flag > 0)
|
||||
{
|
||||
for (subframe = 0; subframe < WEBRTC_SPL_MIN (Nfor, 2); subframe++)
|
||||
{
|
||||
/* update memory */
|
||||
WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
|
||||
WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
|
||||
&decresidual[(iLBCbits_inst->startIdx + 1 +
|
||||
subframe) * SUBL], SUBL);
|
||||
}
|
||||
}
|
||||
|
||||
iLBCenc_inst->Nfor_flag++;
|
||||
|
||||
if (iLBCenc_inst->mode == 20)
|
||||
{
|
||||
start_count = 0;
|
||||
end_count = Nfor;
|
||||
}
|
||||
if (iLBCenc_inst->mode == 30)
|
||||
{
|
||||
if (iLBCenc_inst->section == 1)
|
||||
{
|
||||
start_count = 0;
|
||||
end_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
|
||||
}
|
||||
if (iLBCenc_inst->section == 2)
|
||||
{
|
||||
start_count = WEBRTC_SPL_MIN (Nfor, (size_t)2);
|
||||
end_count = Nfor;
|
||||
}
|
||||
}
|
||||
#else
|
||||
start_count = 0;
|
||||
end_count = Nfor;
|
||||
#endif
|
||||
|
||||
/* loop over subframes to encode */
|
||||
|
||||
for (subframe = start_count; subframe < end_count; subframe++){
|
||||
|
||||
/* encode subframe */
|
||||
|
||||
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
|
||||
iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
|
||||
&residual[(iLBCbits_inst->startIdx+1+subframe)*SUBL],
|
||||
mem, MEM_LF_TBL, SUBL,
|
||||
&weightdenum[(iLBCbits_inst->startIdx+1+subframe)*(LPC_FILTERORDER+1)],
|
||||
subcount);
|
||||
|
||||
/* construct decoded vector */
|
||||
RTC_CHECK(WebRtcIlbcfix_CbConstruct(
|
||||
&decresidual[(iLBCbits_inst->startIdx + 1 + subframe) * SUBL],
|
||||
iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
|
||||
iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
|
||||
SUBL));
|
||||
|
||||
/* update memory */
|
||||
|
||||
memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
|
||||
&decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], SUBL);
|
||||
|
||||
subcount++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
if ((iLBCenc_inst->section == 1) &&
|
||||
(iLBCenc_inst->mode == 30) && (Nfor > 0) && (end_count == 2))
|
||||
{
|
||||
iLBCenc_inst->section++;
|
||||
/* adjust index */
|
||||
WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
|
||||
/* Packetize the parameters into the frame */
|
||||
WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
|
||||
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* backward prediction of subframes */
|
||||
|
||||
if (iLBCbits_inst->startIdx > 1) {
|
||||
|
||||
/* create reverse order vectors
|
||||
(The decresidual does not need to be copied since it is
|
||||
contained in the same vector as the residual)
|
||||
*/
|
||||
|
||||
size_t Nback = iLBCbits_inst->startIdx - 1;
|
||||
WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL);
|
||||
|
||||
/* setup memory */
|
||||
|
||||
meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx);
|
||||
if( meml_gotten > CB_MEML ) {
|
||||
meml_gotten=CB_MEML;
|
||||
}
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten);
|
||||
WebRtcSpl_MemSetW16(mem, 0, CB_MEML - meml_gotten);
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
if (iLBCenc_inst->Nback_flag > 0)
|
||||
{
|
||||
for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++)
|
||||
{
|
||||
/* update memory */
|
||||
WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
|
||||
WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
|
||||
&reverseDecresidual[subframe * SUBL], SUBL);
|
||||
}
|
||||
}
|
||||
|
||||
iLBCenc_inst->Nback_flag++;
|
||||
|
||||
|
||||
if (iLBCenc_inst->mode == 20)
|
||||
{
|
||||
start_count = 0;
|
||||
end_count = Nback;
|
||||
}
|
||||
if (iLBCenc_inst->mode == 30)
|
||||
{
|
||||
if (iLBCenc_inst->section == 1)
|
||||
{
|
||||
start_count = 0;
|
||||
end_count = (Nfor >= 2) ? 0 : (2 - NFor);
|
||||
}
|
||||
if (iLBCenc_inst->section == 2)
|
||||
{
|
||||
start_count = (Nfor >= 2) ? 0 : (2 - NFor);
|
||||
end_count = Nback;
|
||||
}
|
||||
}
|
||||
#else
|
||||
start_count = 0;
|
||||
end_count = Nback;
|
||||
#endif
|
||||
|
||||
/* loop over subframes to encode */
|
||||
|
||||
for (subframe = start_count; subframe < end_count; subframe++){
|
||||
|
||||
/* encode subframe */
|
||||
|
||||
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
|
||||
iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL],
|
||||
mem, MEM_LF_TBL, SUBL,
|
||||
&weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)],
|
||||
subcount);
|
||||
|
||||
/* construct decoded vector */
|
||||
RTC_CHECK(WebRtcIlbcfix_CbConstruct(
|
||||
&reverseDecresidual[subframe * SUBL],
|
||||
iLBCbits_inst->cb_index + subcount * CB_NSTAGES,
|
||||
iLBCbits_inst->gain_index + subcount * CB_NSTAGES, mem, MEM_LF_TBL,
|
||||
SUBL));
|
||||
|
||||
/* update memory */
|
||||
memmove(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(*mem));
|
||||
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
|
||||
&reverseDecresidual[subframe*SUBL], SUBL);
|
||||
|
||||
subcount++;
|
||||
|
||||
}
|
||||
|
||||
/* get decoded residual from reversed vector */
|
||||
|
||||
WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback);
|
||||
}
|
||||
/* end encoding part */
|
||||
|
||||
/* adjust index */
|
||||
|
||||
WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index);
|
||||
|
||||
/* Packetize the parameters into the frame */
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){
|
||||
WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
}
|
||||
else{
|
||||
WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
}
|
||||
#else
|
||||
WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
|
||||
#endif
|
||||
|
||||
#ifndef WEBRTC_ARCH_BIG_ENDIAN
|
||||
/* Swap bytes for LITTLE ENDIAN since the packbits()
|
||||
function assumes BIG_ENDIAN machine */
|
||||
#ifdef SPLIT_10MS
|
||||
if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) ||
|
||||
( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){
|
||||
WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
|
||||
}
|
||||
#else
|
||||
WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words, bytes);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SPLIT_10MS
|
||||
if (subcount == (iLBCenc_inst->nsub - 1))
|
||||
{
|
||||
iLBCenc_inst->section = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iLBCenc_inst->section++;
|
||||
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
|
||||
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Encode.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* main encoder function
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_EncodeImpl(
|
||||
uint16_t* bytes, /* (o) encoded data bits iLBC */
|
||||
const int16_t* block, /* (i) speech vector to encode */
|
||||
IlbcEncoder* iLBCenc_inst /* (i/o) the general encoder
|
||||
state */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnergyInverse.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
/* Inverses the in vector in into Q29 domain */
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
|
||||
|
||||
void WebRtcIlbcfix_EnergyInverse(
|
||||
int16_t *energy, /* (i/o) Energy and inverse
|
||||
energy (in Q29) */
|
||||
size_t noOfEnergies) /* (i) The length of the energy
|
||||
vector */
|
||||
{
|
||||
int32_t Nom=(int32_t)0x1FFFFFFF;
|
||||
int16_t *energyPtr;
|
||||
size_t i;
|
||||
|
||||
/* Set the minimum energy value to 16384 to avoid overflow */
|
||||
energyPtr=energy;
|
||||
for (i=0; i<noOfEnergies; i++) {
|
||||
(*energyPtr)=WEBRTC_SPL_MAX((*energyPtr),16384);
|
||||
energyPtr++;
|
||||
}
|
||||
|
||||
/* Calculate inverse energy in Q29 */
|
||||
energyPtr=energy;
|
||||
for (i=0; i<noOfEnergies; i++) {
|
||||
(*energyPtr) = (int16_t)WebRtcSpl_DivW32W16(Nom, (*energyPtr));
|
||||
energyPtr++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnergyInverse.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/* Inverses the in vector in into Q29 domain */
|
||||
|
||||
void WebRtcIlbcfix_EnergyInverse(
|
||||
int16_t*
|
||||
energy, /* (i/o) Energy and inverse
|
||||
energy (in Q29) */
|
||||
size_t noOfEnergies); /* (i) The length of the energy
|
||||
vector */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnhUpsample.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/enh_upsample.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* upsample finite array assuming zeros outside bounds
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_EnhUpsample(
|
||||
int32_t *useq1, /* (o) upsampled output sequence */
|
||||
int16_t *seq1 /* (i) unupsampled sequence */
|
||||
){
|
||||
int j;
|
||||
int32_t *pu1, *pu11;
|
||||
int16_t *ps, *w16tmp;
|
||||
const int16_t *pp;
|
||||
|
||||
/* filtering: filter overhangs left side of sequence */
|
||||
pu1=useq1;
|
||||
for (j=0;j<ENH_UPS0; j++) {
|
||||
pu11=pu1;
|
||||
/* i = 2 */
|
||||
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
|
||||
ps=seq1+2;
|
||||
*pu11 = (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
pu11+=ENH_UPS0;
|
||||
/* i = 3 */
|
||||
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
|
||||
ps=seq1+3;
|
||||
*pu11 = (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
pu11+=ENH_UPS0;
|
||||
/* i = 4 */
|
||||
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
|
||||
ps=seq1+4;
|
||||
*pu11 = (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
pu1++;
|
||||
}
|
||||
|
||||
/* filtering: simple convolution=inner products
|
||||
(not needed since the sequence is so short)
|
||||
*/
|
||||
|
||||
/* filtering: filter overhangs right side of sequence */
|
||||
|
||||
/* Code with loops, which is equivivalent to the expanded version below
|
||||
|
||||
filterlength = 5;
|
||||
hf1 = 2;
|
||||
for(j=0;j<ENH_UPS0; j++){
|
||||
pu = useq1 + (filterlength-hfl)*ENH_UPS0 + j;
|
||||
for(i=1; i<=hfl; i++){
|
||||
*pu=0;
|
||||
pp = polyp[j]+i;
|
||||
ps = seq1+dim1-1;
|
||||
for(k=0;k<filterlength-i;k++) {
|
||||
*pu += (*ps--) * *pp++;
|
||||
}
|
||||
pu+=ENH_UPS0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
pu1 = useq1 + 12;
|
||||
w16tmp = seq1+4;
|
||||
for (j=0;j<ENH_UPS0; j++) {
|
||||
pu11 = pu1;
|
||||
/* i = 1 */
|
||||
pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+2;
|
||||
ps = w16tmp;
|
||||
*pu11 = (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
pu11+=ENH_UPS0;
|
||||
/* i = 2 */
|
||||
pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+3;
|
||||
ps = w16tmp;
|
||||
*pu11 = (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
*pu11 += (*ps--) * *pp++;
|
||||
pu11+=ENH_UPS0;
|
||||
|
||||
pu1++;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnhUpsample.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* upsample finite array assuming zeros outside bounds
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_EnhUpsample(
|
||||
int32_t* useq1, /* (o) upsampled output sequence */
|
||||
int16_t* seq1 /* (i) unupsampled sequence */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Enhancer.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/enhancer.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/smooth.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* perform enhancement on idata+centerStartPos through
|
||||
* idata+centerStartPos+ENH_BLOCKL-1
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_Enhancer(
|
||||
int16_t *odata, /* (o) smoothed block, dimension blockl */
|
||||
int16_t *idata, /* (i) data buffer used for enhancing */
|
||||
size_t idatal, /* (i) dimension idata */
|
||||
size_t centerStartPos, /* (i) first sample current block within idata */
|
||||
size_t *period, /* (i) pitch period array (pitch bward-in time) */
|
||||
const size_t *plocs, /* (i) locations where period array values valid */
|
||||
size_t periodl /* (i) dimension of period and plocs */
|
||||
){
|
||||
/* Stack based */
|
||||
int16_t surround[ENH_BLOCKL];
|
||||
|
||||
WebRtcSpl_MemSetW16(surround, 0, ENH_BLOCKL);
|
||||
|
||||
/* get said second sequence of segments */
|
||||
|
||||
WebRtcIlbcfix_GetSyncSeq(idata, idatal, centerStartPos, period, plocs,
|
||||
periodl, ENH_HL, surround);
|
||||
|
||||
/* compute the smoothed output from said second sequence */
|
||||
|
||||
WebRtcIlbcfix_Smooth(odata, idata + centerStartPos, surround);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_Enhancer.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* perform enhancement on idata+centerStartPos through
|
||||
* idata+centerStartPos+ENH_BLOCKL-1
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_Enhancer(
|
||||
int16_t* odata, /* (o) smoothed block, dimension blockl */
|
||||
int16_t* idata, /* (i) data buffer used for enhancing */
|
||||
size_t idatal, /* (i) dimension idata */
|
||||
size_t centerStartPos, /* (i) first sample current block within idata */
|
||||
size_t* period, /* (i) pitch period array (pitch bward-in time) */
|
||||
const size_t* plocs, /* (i) locations where period array values valid */
|
||||
size_t periodl /* (i) dimension of period and plocs */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnhancerInterface.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/enhancer.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/hp_output.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* interface for enhancer
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
size_t // (o) Estimated lag in end of in[]
|
||||
WebRtcIlbcfix_EnhancerInterface(
|
||||
int16_t* out, // (o) enhanced signal
|
||||
const int16_t* in, // (i) unenhanced signal
|
||||
IlbcDecoder* iLBCdec_inst) { // (i) buffers etc
|
||||
size_t iblock;
|
||||
size_t lag=20, tlag=20;
|
||||
size_t inLen=iLBCdec_inst->blockl+120;
|
||||
int16_t scale, scale1;
|
||||
size_t plc_blockl;
|
||||
int16_t *enh_buf;
|
||||
size_t *enh_period;
|
||||
int32_t tmp1, tmp2, max;
|
||||
size_t new_blocks;
|
||||
int16_t *enh_bufPtr1;
|
||||
size_t i;
|
||||
size_t k;
|
||||
int16_t EnChange;
|
||||
int16_t SqrtEnChange;
|
||||
int16_t inc;
|
||||
int16_t win;
|
||||
int16_t *tmpW16ptr;
|
||||
size_t startPos;
|
||||
int16_t *plc_pred;
|
||||
const int16_t *target, *regressor;
|
||||
int16_t max16;
|
||||
int shifts;
|
||||
int32_t ener;
|
||||
int16_t enerSh;
|
||||
int16_t corrSh;
|
||||
size_t ind;
|
||||
int16_t sh;
|
||||
size_t start, stop;
|
||||
/* Stack based */
|
||||
int16_t totsh[3];
|
||||
int16_t downsampled[(BLOCKL_MAX+120)>>1]; /* length 180 */
|
||||
int32_t corr32[50];
|
||||
int32_t corrmax[3];
|
||||
int16_t corr16[3];
|
||||
int16_t en16[3];
|
||||
size_t lagmax[3];
|
||||
|
||||
plc_pred = downsampled; /* Reuse memory since plc_pred[ENH_BLOCKL] and
|
||||
downsampled are non overlapping */
|
||||
enh_buf=iLBCdec_inst->enh_buf;
|
||||
enh_period=iLBCdec_inst->enh_period;
|
||||
|
||||
/* Copy in the new data into the enhancer buffer */
|
||||
memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl],
|
||||
(ENH_BUFL - iLBCdec_inst->blockl) * sizeof(*enh_buf));
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in,
|
||||
iLBCdec_inst->blockl);
|
||||
|
||||
/* Set variables that are dependent on frame size */
|
||||
if (iLBCdec_inst->mode==30) {
|
||||
plc_blockl=ENH_BLOCKL;
|
||||
new_blocks=3;
|
||||
startPos=320; /* Start position for enhancement
|
||||
(640-new_blocks*ENH_BLOCKL-80) */
|
||||
} else {
|
||||
plc_blockl=40;
|
||||
new_blocks=2;
|
||||
startPos=440; /* Start position for enhancement
|
||||
(640-new_blocks*ENH_BLOCKL-40) */
|
||||
}
|
||||
|
||||
/* Update the pitch prediction for each enhancer block, move the old ones */
|
||||
memmove(enh_period, &enh_period[new_blocks],
|
||||
(ENH_NBLOCKS_TOT - new_blocks) * sizeof(*enh_period));
|
||||
|
||||
WebRtcSpl_DownsampleFast(
|
||||
enh_buf+ENH_BUFL-inLen, /* Input samples */
|
||||
inLen + ENH_BUFL_FILTEROVERHEAD,
|
||||
downsampled,
|
||||
inLen / 2,
|
||||
(int16_t*)WebRtcIlbcfix_kLpFiltCoefs, /* Coefficients in Q12 */
|
||||
FILTERORDER_DS_PLUS1, /* Length of filter (order-1) */
|
||||
FACTOR_DS,
|
||||
DELAY_DS);
|
||||
|
||||
/* Estimate the pitch in the down sampled domain. */
|
||||
for(iblock = 0; iblock<new_blocks; iblock++){
|
||||
|
||||
/* references */
|
||||
target = downsampled + 60 + iblock * ENH_BLOCKL_HALF;
|
||||
regressor = target - 10;
|
||||
|
||||
/* scaling */
|
||||
max16 = WebRtcSpl_MaxAbsValueW16(®ressor[-50], ENH_BLOCKL_HALF + 50 - 1);
|
||||
shifts = WebRtcSpl_GetSizeInBits((uint32_t)(max16 * max16)) - 25;
|
||||
shifts = WEBRTC_SPL_MAX(0, shifts);
|
||||
|
||||
/* compute cross correlation */
|
||||
WebRtcSpl_CrossCorrelation(corr32, target, regressor, ENH_BLOCKL_HALF, 50,
|
||||
shifts, -1);
|
||||
|
||||
/* Find 3 highest correlations that should be compared for the
|
||||
highest (corr*corr)/ener */
|
||||
|
||||
for (i=0;i<2;i++) {
|
||||
lagmax[i] = WebRtcSpl_MaxIndexW32(corr32, 50);
|
||||
corrmax[i] = corr32[lagmax[i]];
|
||||
start = WEBRTC_SPL_MAX(2, lagmax[i]) - 2;
|
||||
stop = WEBRTC_SPL_MIN(47, lagmax[i]) + 2;
|
||||
for (k = start; k <= stop; k++) {
|
||||
corr32[k] = 0;
|
||||
}
|
||||
}
|
||||
lagmax[2] = WebRtcSpl_MaxIndexW32(corr32, 50);
|
||||
corrmax[2] = corr32[lagmax[2]];
|
||||
|
||||
/* Calculate normalized corr^2 and ener */
|
||||
for (i=0;i<3;i++) {
|
||||
corrSh = 15-WebRtcSpl_GetSizeInBits(corrmax[i]);
|
||||
ener = WebRtcSpl_DotProductWithScale(regressor - lagmax[i],
|
||||
regressor - lagmax[i],
|
||||
ENH_BLOCKL_HALF, shifts);
|
||||
enerSh = 15-WebRtcSpl_GetSizeInBits(ener);
|
||||
corr16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(corrmax[i], corrSh);
|
||||
corr16[i] = (int16_t)((corr16[i] * corr16[i]) >> 16);
|
||||
en16[i] = (int16_t)WEBRTC_SPL_SHIFT_W32(ener, enerSh);
|
||||
totsh[i] = enerSh - 2 * corrSh;
|
||||
}
|
||||
|
||||
/* Compare lagmax[0..3] for the (corr^2)/ener criteria */
|
||||
ind = 0;
|
||||
for (i=1; i<3; i++) {
|
||||
if (totsh[ind] > totsh[i]) {
|
||||
sh = WEBRTC_SPL_MIN(31, totsh[ind]-totsh[i]);
|
||||
if (corr16[ind] * en16[i] < (corr16[i] * en16[ind]) >> sh) {
|
||||
ind = i;
|
||||
}
|
||||
} else {
|
||||
sh = WEBRTC_SPL_MIN(31, totsh[i]-totsh[ind]);
|
||||
if ((corr16[ind] * en16[i]) >> sh < corr16[i] * en16[ind]) {
|
||||
ind = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lag = lagmax[ind] + 10;
|
||||
|
||||
/* Store the estimated lag in the non-downsampled domain */
|
||||
enh_period[ENH_NBLOCKS_TOT - new_blocks + iblock] = lag * 8;
|
||||
|
||||
/* Store the estimated lag for backward PLC */
|
||||
if (iLBCdec_inst->prev_enh_pl==1) {
|
||||
if (!iblock) {
|
||||
tlag = lag * 2;
|
||||
}
|
||||
} else {
|
||||
if (iblock==1) {
|
||||
tlag = lag * 2;
|
||||
}
|
||||
}
|
||||
|
||||
lag *= 2;
|
||||
}
|
||||
|
||||
if ((iLBCdec_inst->prev_enh_pl==1)||(iLBCdec_inst->prev_enh_pl==2)) {
|
||||
|
||||
/* Calculate the best lag of the new frame
|
||||
This is used to interpolate backwards and mix with the PLC'd data
|
||||
*/
|
||||
|
||||
/* references */
|
||||
target=in;
|
||||
regressor=in+tlag-1;
|
||||
|
||||
/* scaling */
|
||||
// Note that this is not abs-max, so we will take the absolute value below.
|
||||
max16 = WebRtcSpl_MaxAbsElementW16(regressor, plc_blockl + 3 - 1);
|
||||
const int16_t max_target =
|
||||
WebRtcSpl_MaxAbsElementW16(target, plc_blockl + 3 - 1);
|
||||
const int64_t max_val = plc_blockl * abs(max16 * max_target);
|
||||
const int32_t factor = max_val >> 31;
|
||||
shifts = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor);
|
||||
|
||||
/* compute cross correlation */
|
||||
WebRtcSpl_CrossCorrelation(corr32, target, regressor, plc_blockl, 3, shifts,
|
||||
1);
|
||||
|
||||
/* find lag */
|
||||
lag=WebRtcSpl_MaxIndexW32(corr32, 3);
|
||||
lag+=tlag-1;
|
||||
|
||||
/* Copy the backward PLC to plc_pred */
|
||||
|
||||
if (iLBCdec_inst->prev_enh_pl==1) {
|
||||
if (lag>plc_blockl) {
|
||||
WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-plc_blockl], plc_blockl);
|
||||
} else {
|
||||
WEBRTC_SPL_MEMCPY_W16(&plc_pred[plc_blockl-lag], in, lag);
|
||||
WEBRTC_SPL_MEMCPY_W16(
|
||||
plc_pred, &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl+lag],
|
||||
(plc_blockl-lag));
|
||||
}
|
||||
} else {
|
||||
size_t pos;
|
||||
|
||||
pos = plc_blockl;
|
||||
|
||||
while (lag<pos) {
|
||||
WEBRTC_SPL_MEMCPY_W16(&plc_pred[pos-lag], in, lag);
|
||||
pos = pos - lag;
|
||||
}
|
||||
WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-pos], pos);
|
||||
|
||||
}
|
||||
|
||||
if (iLBCdec_inst->prev_enh_pl==1) {
|
||||
/* limit energy change
|
||||
if energy in backward PLC is more than 4 times higher than the forward
|
||||
PLC, then reduce the energy in the backward PLC vector:
|
||||
sample 1...len-16 set energy of the to 4 times forward PLC
|
||||
sample len-15..len interpolate between 4 times fw PLC and bw PLC energy
|
||||
|
||||
Note: Compared to floating point code there is a slight change,
|
||||
the window is 16 samples long instead of 10 samples to simplify the
|
||||
calculations
|
||||
*/
|
||||
|
||||
max=WebRtcSpl_MaxAbsValueW16(
|
||||
&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl);
|
||||
max16=WebRtcSpl_MaxAbsValueW16(plc_pred, plc_blockl);
|
||||
max = WEBRTC_SPL_MAX(max, max16);
|
||||
scale=22-(int16_t)WebRtcSpl_NormW32(max);
|
||||
scale=WEBRTC_SPL_MAX(scale,0);
|
||||
|
||||
tmp2 = WebRtcSpl_DotProductWithScale(
|
||||
&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl],
|
||||
&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl],
|
||||
plc_blockl, scale);
|
||||
tmp1 = WebRtcSpl_DotProductWithScale(plc_pred, plc_pred,
|
||||
plc_blockl, scale);
|
||||
|
||||
/* Check the energy difference */
|
||||
if ((tmp1>0)&&((tmp1>>2)>tmp2)) {
|
||||
/* EnChange is now guaranteed to be <0.5
|
||||
Calculate EnChange=tmp2/tmp1 in Q16
|
||||
*/
|
||||
|
||||
scale1=(int16_t)WebRtcSpl_NormW32(tmp1);
|
||||
tmp1=WEBRTC_SPL_SHIFT_W32(tmp1, (scale1-16)); /* using 15 bits */
|
||||
|
||||
tmp2=WEBRTC_SPL_SHIFT_W32(tmp2, (scale1));
|
||||
EnChange = (int16_t)WebRtcSpl_DivW32W16(tmp2,
|
||||
(int16_t)tmp1);
|
||||
|
||||
/* Calculate the Sqrt of the energy in Q15 ((14+16)/2) */
|
||||
SqrtEnChange = (int16_t)WebRtcSpl_SqrtFloor(EnChange << 14);
|
||||
|
||||
|
||||
/* Multiply first part of vector with 2*SqrtEnChange */
|
||||
WebRtcSpl_ScaleVector(plc_pred, plc_pred, SqrtEnChange, plc_blockl-16,
|
||||
14);
|
||||
|
||||
/* Calculate increase parameter for window part (16 last samples) */
|
||||
/* (1-2*SqrtEnChange)/16 in Q15 */
|
||||
inc = 2048 - (SqrtEnChange >> 3);
|
||||
|
||||
win=0;
|
||||
tmpW16ptr=&plc_pred[plc_blockl-16];
|
||||
|
||||
for (i=16;i>0;i--) {
|
||||
*tmpW16ptr = (int16_t)(
|
||||
(*tmpW16ptr * (SqrtEnChange + (win >> 1))) >> 14);
|
||||
/* multiply by (2.0*SqrtEnChange+win) */
|
||||
|
||||
win += inc;
|
||||
tmpW16ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the linear interpolation between the forward PLC'd data
|
||||
and the backward PLC'd data (from the new frame)
|
||||
*/
|
||||
|
||||
if (plc_blockl==40) {
|
||||
inc=400; /* 1/41 in Q14 */
|
||||
} else { /* plc_blockl==80 */
|
||||
inc=202; /* 1/81 in Q14 */
|
||||
}
|
||||
win=0;
|
||||
enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl];
|
||||
for (i=0; i<plc_blockl; i++) {
|
||||
win+=inc;
|
||||
*enh_bufPtr1 = (int16_t)((*enh_bufPtr1 * win) >> 14);
|
||||
*enh_bufPtr1 += (int16_t)(
|
||||
((16384 - win) * plc_pred[plc_blockl - 1 - i]) >> 14);
|
||||
enh_bufPtr1--;
|
||||
}
|
||||
} else {
|
||||
int16_t *synt = &downsampled[LPC_FILTERORDER];
|
||||
|
||||
enh_bufPtr1=&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl];
|
||||
WEBRTC_SPL_MEMCPY_W16(enh_bufPtr1, plc_pred, plc_blockl);
|
||||
|
||||
/* Clear fileter memory */
|
||||
WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER);
|
||||
WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4);
|
||||
WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2);
|
||||
|
||||
/* Initialize filter memory by filtering through 2 lags */
|
||||
WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], iLBCdec_inst->syntMem,
|
||||
LPC_FILTERORDER);
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
enh_bufPtr1,
|
||||
synt,
|
||||
&iLBCdec_inst->old_syntdenum[
|
||||
(iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)],
|
||||
LPC_FILTERORDER+1, lag);
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], &synt[lag-LPC_FILTERORDER],
|
||||
LPC_FILTERORDER);
|
||||
WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
|
||||
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
|
||||
lag);
|
||||
WebRtcSpl_FilterARFastQ12(
|
||||
enh_bufPtr1, synt,
|
||||
&iLBCdec_inst->old_syntdenum[
|
||||
(iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)],
|
||||
LPC_FILTERORDER+1, lag);
|
||||
|
||||
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &synt[lag-LPC_FILTERORDER],
|
||||
LPC_FILTERORDER);
|
||||
WebRtcIlbcfix_HpOutput(synt, (int16_t*)WebRtcIlbcfix_kHpOutCoefs,
|
||||
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
|
||||
lag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Perform enhancement block by block */
|
||||
|
||||
for (iblock = 0; iblock<new_blocks; iblock++) {
|
||||
WebRtcIlbcfix_Enhancer(out + iblock * ENH_BLOCKL,
|
||||
enh_buf,
|
||||
ENH_BUFL,
|
||||
iblock * ENH_BLOCKL + startPos,
|
||||
enh_period,
|
||||
WebRtcIlbcfix_kEnhPlocs, ENH_NBLOCKS_TOT);
|
||||
}
|
||||
|
||||
return (lag);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_EnhancerInterface.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* interface for enhancer
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
size_t // (o) Estimated lag in end of in[]
|
||||
WebRtcIlbcfix_EnhancerInterface(int16_t* out, // (o) enhanced signal
|
||||
const int16_t* in, // (i) unenhanced signal
|
||||
IlbcDecoder* iLBCdec_inst); // (i) buffers etc
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_FilteredCbVecs.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct an additional codebook vector by filtering the
|
||||
* initial codebook buffer. This vector is then used to expand
|
||||
* the codebook with an additional section.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_FilteredCbVecs(
|
||||
int16_t *cbvectors, /* (o) Codebook vector for the higher section */
|
||||
int16_t *CBmem, /* (i) Codebook memory that is filtered to create a
|
||||
second CB section */
|
||||
size_t lMem, /* (i) Length of codebook memory */
|
||||
size_t samples /* (i) Number of samples to filter */
|
||||
) {
|
||||
|
||||
/* Set up the memory, start with zero state */
|
||||
WebRtcSpl_MemSetW16(CBmem+lMem, 0, CB_HALFFILTERLEN);
|
||||
WebRtcSpl_MemSetW16(CBmem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
|
||||
WebRtcSpl_MemSetW16(cbvectors, 0, lMem-samples);
|
||||
|
||||
/* Filter to obtain the filtered CB memory */
|
||||
|
||||
WebRtcSpl_FilterMAFastQ12(
|
||||
CBmem+CB_HALFFILTERLEN+lMem-samples, cbvectors+lMem-samples,
|
||||
(int16_t*)WebRtcIlbcfix_kCbFiltersRev, CB_FILTERLEN, samples);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_FilteredCbVecs.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct an additional codebook vector by filtering the
|
||||
* initial codebook buffer. This vector is then used to expand
|
||||
* the codebook with an additional section.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_FilteredCbVecs(
|
||||
int16_t* cbvectors, /* (o) Codebook vector for the higher section */
|
||||
int16_t* CBmem, /* (i) Codebook memory that is filtered to create a
|
||||
second CB section */
|
||||
size_t lMem, /* (i) Length of codebook memory */
|
||||
size_t samples /* (i) Number of samples to filter */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_FrameClassify.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Classification of subframes to localize start state
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
size_t WebRtcIlbcfix_FrameClassify(
|
||||
/* (o) Index to the max-energy sub frame */
|
||||
IlbcEncoder *iLBCenc_inst,
|
||||
/* (i/o) the encoder state structure */
|
||||
int16_t *residualFIX /* (i) lpc residual signal */
|
||||
){
|
||||
int16_t max, scale;
|
||||
int32_t ssqEn[NSUB_MAX-1];
|
||||
int16_t *ssqPtr;
|
||||
int32_t *seqEnPtr;
|
||||
int32_t maxW32;
|
||||
int16_t scale1;
|
||||
size_t pos;
|
||||
size_t n;
|
||||
|
||||
/*
|
||||
Calculate the energy of each of the 80 sample blocks
|
||||
in the draft the 4 first and last samples are windowed with 1/5...4/5
|
||||
and 4/5...1/5 respectively. To simplify for the fixpoint we have changed
|
||||
this to 0 0 1 1 and 1 1 0 0
|
||||
*/
|
||||
|
||||
max = WebRtcSpl_MaxAbsValueW16(residualFIX, iLBCenc_inst->blockl);
|
||||
scale = WebRtcSpl_GetSizeInBits((uint32_t)(max * max));
|
||||
|
||||
/* Scale to maximum 24 bits so that it won't overflow for 76 samples */
|
||||
scale = scale-24;
|
||||
scale1 = WEBRTC_SPL_MAX(0, scale);
|
||||
|
||||
/* Calculate energies */
|
||||
ssqPtr=residualFIX + 2;
|
||||
seqEnPtr=ssqEn;
|
||||
for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
|
||||
(*seqEnPtr) = WebRtcSpl_DotProductWithScale(ssqPtr, ssqPtr, 76, scale1);
|
||||
ssqPtr += 40;
|
||||
seqEnPtr++;
|
||||
}
|
||||
|
||||
/* Scale to maximum 20 bits in order to allow for the 11 bit window */
|
||||
maxW32 = WebRtcSpl_MaxValueW32(ssqEn, iLBCenc_inst->nsub - 1);
|
||||
scale = WebRtcSpl_GetSizeInBits(maxW32) - 20;
|
||||
scale1 = WEBRTC_SPL_MAX(0, scale);
|
||||
|
||||
/* Window each 80 block with the ssqEn_winTbl window to give higher probability for
|
||||
the blocks in the middle
|
||||
*/
|
||||
seqEnPtr=ssqEn;
|
||||
if (iLBCenc_inst->mode==20) {
|
||||
ssqPtr=(int16_t*)WebRtcIlbcfix_kStartSequenceEnrgWin+1;
|
||||
} else {
|
||||
ssqPtr=(int16_t*)WebRtcIlbcfix_kStartSequenceEnrgWin;
|
||||
}
|
||||
for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
|
||||
(*seqEnPtr)=WEBRTC_SPL_MUL(((*seqEnPtr)>>scale1), (*ssqPtr));
|
||||
seqEnPtr++;
|
||||
ssqPtr++;
|
||||
}
|
||||
|
||||
/* Extract the best choise of start state */
|
||||
pos = WebRtcSpl_MaxIndexW32(ssqEn, iLBCenc_inst->nsub - 1) + 1;
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_FrameClassify.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
size_t WebRtcIlbcfix_FrameClassify(
|
||||
/* (o) Index to the max-energy sub frame */
|
||||
IlbcEncoder* iLBCenc_inst,
|
||||
/* (i/o) the encoder state structure */
|
||||
int16_t* residualFIX /* (i) lpc residual signal */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GainDequant.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/gain_dequant.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* decoder for quantized gains in the gain-shape coding of
|
||||
* residual
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int16_t WebRtcIlbcfix_GainDequant(
|
||||
/* (o) quantized gain value (Q14) */
|
||||
int16_t index, /* (i) quantization index */
|
||||
int16_t maxIn, /* (i) maximum of unquantized gain (Q14) */
|
||||
int16_t stage /* (i) The stage of the search */
|
||||
){
|
||||
int16_t scale;
|
||||
const int16_t *gain;
|
||||
|
||||
/* obtain correct scale factor */
|
||||
|
||||
scale=WEBRTC_SPL_ABS_W16(maxIn);
|
||||
scale = WEBRTC_SPL_MAX(1638, scale); /* if lower than 0.1, set it to 0.1 */
|
||||
|
||||
/* select the quantization table and return the decoded value */
|
||||
gain = WebRtcIlbcfix_kGain[stage];
|
||||
|
||||
return (int16_t)((scale * gain[index] + 8192) >> 14);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GainDequant.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* decoder for quantized gains in the gain-shape coding of
|
||||
* residual
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int16_t WebRtcIlbcfix_GainDequant(
|
||||
/* (o) quantized gain value (Q14) */
|
||||
int16_t index, /* (i) quantization index */
|
||||
int16_t maxIn, /* (i) maximum of unquantized gain (Q14) */
|
||||
int16_t stage /* (i) The stage of the search */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GainQuant.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* quantizer for the gain in the gain-shape coding of residual
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int16_t WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
|
||||
int16_t gain, /* (i) gain value Q14 */
|
||||
int16_t maxIn, /* (i) maximum of gain value Q14 */
|
||||
int16_t stage, /* (i) The stage of the search */
|
||||
int16_t *index /* (o) quantization index */
|
||||
) {
|
||||
|
||||
int16_t scale, cblen;
|
||||
int32_t gainW32, measure1, measure2;
|
||||
const int16_t *cbPtr, *cb;
|
||||
int loc, noMoves, noChecks, i;
|
||||
|
||||
/* ensure a lower bound (0.1) on the scaling factor */
|
||||
|
||||
scale = WEBRTC_SPL_MAX(1638, maxIn);
|
||||
|
||||
/* select the quantization table and calculate
|
||||
the length of the table and the number of
|
||||
steps in the binary search that are needed */
|
||||
cb = WebRtcIlbcfix_kGain[stage];
|
||||
cblen = 32>>stage;
|
||||
noChecks = 4-stage;
|
||||
|
||||
/* Multiply the gain with 2^14 to make the comparison
|
||||
easier and with higher precision */
|
||||
gainW32 = gain << 14;
|
||||
|
||||
/* Do a binary search, starting in the middle of the CB
|
||||
loc - defines the current position in the table
|
||||
noMoves - defines the number of steps to move in the CB in order
|
||||
to get next CB location
|
||||
*/
|
||||
|
||||
loc = cblen>>1;
|
||||
noMoves = loc;
|
||||
cbPtr = cb + loc; /* Centre of CB */
|
||||
|
||||
for (i=noChecks;i>0;i--) {
|
||||
noMoves>>=1;
|
||||
measure1 = scale * *cbPtr;
|
||||
|
||||
/* Move up if gain is larger, otherwise move down in table */
|
||||
measure1 = measure1 - gainW32;
|
||||
|
||||
if (0>measure1) {
|
||||
cbPtr+=noMoves;
|
||||
loc+=noMoves;
|
||||
} else {
|
||||
cbPtr-=noMoves;
|
||||
loc-=noMoves;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check which value is the closest one: loc-1, loc or loc+1 */
|
||||
|
||||
measure1 = scale * *cbPtr;
|
||||
if (gainW32>measure1) {
|
||||
/* Check against value above loc */
|
||||
measure2 = scale * cbPtr[1];
|
||||
if ((measure2-gainW32)<(gainW32-measure1)) {
|
||||
loc+=1;
|
||||
}
|
||||
} else {
|
||||
/* Check against value below loc */
|
||||
measure2 = scale * cbPtr[-1];
|
||||
if ((gainW32-measure2)<=(measure1-gainW32)) {
|
||||
loc-=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Guard against getting outside the table. The calculation above can give a location
|
||||
which is one above the maximum value (in very rare cases) */
|
||||
loc=WEBRTC_SPL_MIN(loc, (cblen-1));
|
||||
*index=loc;
|
||||
|
||||
/* Calculate and return the quantized gain value (in Q14) */
|
||||
return (int16_t)((scale * cb[loc] + 8192) >> 14);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GainQuant.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* quantizer for the gain in the gain-shape coding of residual
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int16_t
|
||||
WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
|
||||
int16_t gain, /* (i) gain value Q14 */
|
||||
int16_t maxIn, /* (i) maximum of gain value Q14 */
|
||||
int16_t stage, /* (i) The stage of the search */
|
||||
int16_t* index /* (o) quantization index */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetCbVec.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/get_cd_vec.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct codebook vector for given index.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
bool WebRtcIlbcfix_GetCbVec(
|
||||
int16_t *cbvec, /* (o) Constructed codebook vector */
|
||||
int16_t *mem, /* (i) Codebook buffer */
|
||||
size_t index, /* (i) Codebook index */
|
||||
size_t lMem, /* (i) Length of codebook buffer */
|
||||
size_t cbveclen /* (i) Codebook vector length */
|
||||
){
|
||||
size_t k, base_size;
|
||||
size_t lag;
|
||||
/* Stack based */
|
||||
int16_t tempbuff2[SUBL+5];
|
||||
|
||||
/* Determine size of codebook sections */
|
||||
|
||||
base_size=lMem-cbveclen+1;
|
||||
|
||||
if (cbveclen==SUBL) {
|
||||
base_size += cbveclen / 2;
|
||||
}
|
||||
|
||||
/* No filter -> First codebook section */
|
||||
|
||||
if (index<lMem-cbveclen+1) {
|
||||
|
||||
/* first non-interpolated vectors */
|
||||
|
||||
k=index+cbveclen;
|
||||
/* get vector */
|
||||
WEBRTC_SPL_MEMCPY_W16(cbvec, mem+lMem-k, cbveclen);
|
||||
|
||||
} else if (index < base_size) {
|
||||
|
||||
/* Calculate lag */
|
||||
|
||||
k = (2 * (index - (lMem - cbveclen + 1))) + cbveclen;
|
||||
|
||||
lag = k / 2;
|
||||
|
||||
WebRtcIlbcfix_CreateAugmentedVec(lag, mem+lMem, cbvec);
|
||||
|
||||
}
|
||||
|
||||
/* Higher codebbok section based on filtering */
|
||||
|
||||
else {
|
||||
|
||||
size_t memIndTest;
|
||||
|
||||
/* first non-interpolated vectors */
|
||||
|
||||
if (index-base_size<lMem-cbveclen+1) {
|
||||
|
||||
/* Set up filter memory, stuff zeros outside memory buffer */
|
||||
|
||||
memIndTest = lMem-(index-base_size+cbveclen);
|
||||
|
||||
WebRtcSpl_MemSetW16(mem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
|
||||
WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
|
||||
|
||||
/* do filtering to get the codebook vector */
|
||||
|
||||
WebRtcSpl_FilterMAFastQ12(
|
||||
&mem[memIndTest+4], cbvec, (int16_t*)WebRtcIlbcfix_kCbFiltersRev,
|
||||
CB_FILTERLEN, cbveclen);
|
||||
}
|
||||
|
||||
/* interpolated vectors */
|
||||
|
||||
else {
|
||||
if (cbveclen < SUBL) {
|
||||
// We're going to fill in cbveclen + 5 elements of tempbuff2 in
|
||||
// WebRtcSpl_FilterMAFastQ12, less than the SUBL + 5 elements we'll be
|
||||
// using in WebRtcIlbcfix_CreateAugmentedVec. This error is caused by
|
||||
// bad values in `index` (which come from the encoded stream). Tell the
|
||||
// caller that things went south, and that the decoder state is now
|
||||
// corrupt (because it's half-way through an update that we can't
|
||||
// complete).
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Stuff zeros outside memory buffer */
|
||||
memIndTest = lMem-cbveclen-CB_FILTERLEN;
|
||||
WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
|
||||
|
||||
/* do filtering */
|
||||
WebRtcSpl_FilterMAFastQ12(
|
||||
&mem[memIndTest+7], tempbuff2, (int16_t*)WebRtcIlbcfix_kCbFiltersRev,
|
||||
CB_FILTERLEN, cbveclen+5);
|
||||
|
||||
/* Calculate lag index */
|
||||
lag = (cbveclen<<1)-20+index-base_size-lMem-1;
|
||||
|
||||
WebRtcIlbcfix_CreateAugmentedVec(lag, tempbuff2+SUBL+5, cbvec);
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Success.
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetCbVec.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
// Returns true on success, false on failure. In case of failure, the decoder
|
||||
// state may be corrupted and needs resetting.
|
||||
ABSL_MUST_USE_RESULT
|
||||
bool WebRtcIlbcfix_GetCbVec(
|
||||
int16_t* cbvec, /* (o) Constructed codebook vector */
|
||||
int16_t* mem, /* (i) Codebook buffer */
|
||||
size_t index, /* (i) Codebook index */
|
||||
size_t lMem, /* (i) Length of codebook buffer */
|
||||
size_t cbveclen /* (i) Codebook vector length */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetLspPoly.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct the polynomials F1(z) and F2(z) from the LSP
|
||||
* (Computations are done in Q24)
|
||||
*
|
||||
* The expansion is performed using the following recursion:
|
||||
*
|
||||
* f[0] = 1;
|
||||
* tmp = -2.0 * lsp[0];
|
||||
* f[1] = tmp;
|
||||
* for (i=2; i<=5; i++) {
|
||||
* b = -2.0 * lsp[2*i-2];
|
||||
* f[i] = tmp*f[i-1] + 2.0*f[i-2];
|
||||
* for (j=i; j>=2; j--) {
|
||||
* f[j] = f[j] + tmp*f[j-1] + f[j-2];
|
||||
* }
|
||||
* f[i] = f[i] + tmp;
|
||||
* }
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_GetLspPoly(
|
||||
int16_t *lsp, /* (i) LSP in Q15 */
|
||||
int32_t *f) /* (o) polonymial in Q24 */
|
||||
{
|
||||
int32_t tmpW32;
|
||||
int i, j;
|
||||
int16_t high, low;
|
||||
int16_t *lspPtr;
|
||||
int32_t *fPtr;
|
||||
|
||||
lspPtr = lsp;
|
||||
fPtr = f;
|
||||
/* f[0] = 1.0 (Q24) */
|
||||
(*fPtr) = (int32_t)16777216;
|
||||
fPtr++;
|
||||
|
||||
(*fPtr) = WEBRTC_SPL_MUL((*lspPtr), -1024);
|
||||
fPtr++;
|
||||
lspPtr+=2;
|
||||
|
||||
for(i=2; i<=5; i++)
|
||||
{
|
||||
(*fPtr) = fPtr[-2];
|
||||
|
||||
for(j=i; j>1; j--)
|
||||
{
|
||||
/* Compute f[j] = f[j] + tmp*f[j-1] + f[j-2]; */
|
||||
high = (int16_t)(fPtr[-1] >> 16);
|
||||
low = (int16_t)((fPtr[-1] & 0xffff) >> 1);
|
||||
|
||||
tmpW32 = 4 * high * *lspPtr + 4 * ((low * *lspPtr) >> 15);
|
||||
|
||||
(*fPtr) += fPtr[-2];
|
||||
(*fPtr) -= tmpW32;
|
||||
fPtr--;
|
||||
}
|
||||
*fPtr -= *lspPtr * (1 << 10);
|
||||
|
||||
fPtr+=i;
|
||||
lspPtr+=2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetLspPoly.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Construct the polynomials F1(z) and F2(z) from the LSP
|
||||
* (Computations are done in Q24)
|
||||
*
|
||||
* The expansion is performed using the following recursion:
|
||||
*
|
||||
* f[0] = 1;
|
||||
* tmp = -2.0 * lsp[0];
|
||||
* f[1] = tmp;
|
||||
* for (i=2; i<=5; i++) {
|
||||
* b = -2.0 * lsp[2*i-2];
|
||||
* f[i] = tmp*f[i-1] + 2.0*f[i-2];
|
||||
* for (j=i; j>=2; j--) {
|
||||
* f[j] = f[j] + tmp*f[j-1] + f[j-2];
|
||||
* }
|
||||
* f[i] = f[i] + tmp;
|
||||
* }
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_GetLspPoly(int16_t* lsp, /* (i) LSP in Q15 */
|
||||
int32_t* f); /* (o) polonymial in Q24 */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetSyncSeq.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/constants.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/nearest_neighbor.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/refiner.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* get the pitch-synchronous sample sequence
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_GetSyncSeq(
|
||||
int16_t *idata, /* (i) original data */
|
||||
size_t idatal, /* (i) dimension of data */
|
||||
size_t centerStartPos, /* (i) where current block starts */
|
||||
size_t *period, /* (i) rough-pitch-period array (Q-2) */
|
||||
const size_t *plocs, /* (i) where periods of period array are taken (Q-2) */
|
||||
size_t periodl, /* (i) dimension period array */
|
||||
size_t hl, /* (i) 2*hl+1 is the number of sequences */
|
||||
int16_t *surround /* (i/o) The contribution from this sequence
|
||||
summed with earlier contributions */
|
||||
){
|
||||
size_t i, centerEndPos, q;
|
||||
/* Stack based */
|
||||
size_t lagBlock[2 * ENH_HL + 1];
|
||||
size_t blockStartPos[2 * ENH_HL + 1]; /* The position to search around (Q2) */
|
||||
size_t plocs2[ENH_PLOCSL];
|
||||
|
||||
centerEndPos = centerStartPos + ENH_BLOCKL - 1;
|
||||
|
||||
/* present (find predicted lag from this position) */
|
||||
|
||||
WebRtcIlbcfix_NearestNeighbor(lagBlock + hl,
|
||||
plocs,
|
||||
2 * (centerStartPos + centerEndPos),
|
||||
periodl);
|
||||
|
||||
blockStartPos[hl] = 4 * centerStartPos;
|
||||
|
||||
/* past (find predicted position and perform a refined
|
||||
search to find the best sequence) */
|
||||
|
||||
for (q = hl; q > 0; q--) {
|
||||
size_t qq = q - 1;
|
||||
size_t period_q = period[lagBlock[q]];
|
||||
/* Stop if this sequence would be outside the buffer; that means all
|
||||
further-past sequences would also be outside the buffer. */
|
||||
if (blockStartPos[q] < period_q + (4 * ENH_OVERHANG))
|
||||
break;
|
||||
blockStartPos[qq] = blockStartPos[q] - period_q;
|
||||
|
||||
size_t value = blockStartPos[qq] + 4 * ENH_BLOCKL_HALF;
|
||||
value = (value > period_q) ? (value - period_q) : 0;
|
||||
WebRtcIlbcfix_NearestNeighbor(lagBlock + qq, plocs, value, periodl);
|
||||
|
||||
/* Find the best possible sequence in the 4 times upsampled
|
||||
domain around blockStartPos+q */
|
||||
WebRtcIlbcfix_Refiner(blockStartPos + qq, idata, idatal, centerStartPos,
|
||||
blockStartPos[qq], surround,
|
||||
WebRtcIlbcfix_kEnhWt[qq]);
|
||||
}
|
||||
|
||||
/* future (find predicted position and perform a refined
|
||||
search to find the best sequence) */
|
||||
|
||||
for (i = 0; i < periodl; i++) {
|
||||
plocs2[i] = plocs[i] - period[i];
|
||||
}
|
||||
|
||||
for (q = hl + 1; q <= (2 * hl); q++) {
|
||||
|
||||
WebRtcIlbcfix_NearestNeighbor(
|
||||
lagBlock + q,
|
||||
plocs2,
|
||||
blockStartPos[q - 1] + 4 * ENH_BLOCKL_HALF,
|
||||
periodl);
|
||||
|
||||
blockStartPos[q]=blockStartPos[q-1]+period[lagBlock[q]];
|
||||
|
||||
if (blockStartPos[q] + 4 * (ENH_BLOCKL + ENH_OVERHANG) < 4 * idatal) {
|
||||
|
||||
/* Find the best possible sequence in the 4 times upsampled
|
||||
domain around blockStartPos+q */
|
||||
WebRtcIlbcfix_Refiner(blockStartPos + q, idata, idatal, centerStartPos,
|
||||
blockStartPos[q], surround,
|
||||
WebRtcIlbcfix_kEnhWt[2 * hl - q]);
|
||||
|
||||
} else {
|
||||
/* Don't add anything since this sequence would
|
||||
be outside the buffer */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_GetSyncSeq.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* get the pitch-synchronous sample sequence
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_GetSyncSeq(
|
||||
int16_t* idata, /* (i) original data */
|
||||
size_t idatal, /* (i) dimension of data */
|
||||
size_t centerStartPos, /* (i) where current block starts */
|
||||
size_t* period, /* (i) rough-pitch-period array (Q-2) */
|
||||
const size_t* plocs, /* (i) where periods of period array are taken (Q-2) */
|
||||
size_t periodl, /* (i) dimension period array */
|
||||
size_t hl, /* (i) 2*hl+1 is the number of sequences */
|
||||
int16_t* surround /* (i/o) The contribution from this sequence
|
||||
summed with earlier contributions */
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_HpInput.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/hp_input.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* high-pass filter of input with *0.5 and saturation
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_HpInput(
|
||||
int16_t *signal, /* (i/o) signal vector */
|
||||
int16_t *ba, /* (i) B- and A-coefficients (2:nd order)
|
||||
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
|
||||
is assumed to be 1.0 */
|
||||
int16_t *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
|
||||
yhi[n-2] ylow[n-2] */
|
||||
int16_t *x, /* (i/o) Filter state x[n-1] x[n-2] */
|
||||
size_t len) /* (i) Number of samples to filter */
|
||||
{
|
||||
size_t i;
|
||||
int32_t tmpW32;
|
||||
int32_t tmpW32b;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
|
||||
/*
|
||||
y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
|
||||
+ (-a[1])*y[i-1] + (-a[2])*y[i-2];
|
||||
*/
|
||||
|
||||
tmpW32 = y[1] * ba[3]; /* (-a[1])*y[i-1] (low part) */
|
||||
tmpW32 += y[3] * ba[4]; /* (-a[2])*y[i-2] (low part) */
|
||||
tmpW32 = (tmpW32>>15);
|
||||
tmpW32 += y[0] * ba[3]; /* (-a[1])*y[i-1] (high part) */
|
||||
tmpW32 += y[2] * ba[4]; /* (-a[2])*y[i-2] (high part) */
|
||||
tmpW32 = (tmpW32<<1);
|
||||
|
||||
tmpW32 += signal[i] * ba[0]; /* b[0]*x[0] */
|
||||
tmpW32 += x[0] * ba[1]; /* b[1]*x[i-1] */
|
||||
tmpW32 += x[1] * ba[2]; /* b[2]*x[i-2] */
|
||||
|
||||
/* Update state (input part) */
|
||||
x[1] = x[0];
|
||||
x[0] = signal[i];
|
||||
|
||||
/* Rounding in Q(12+1), i.e. add 2^12 */
|
||||
tmpW32b = tmpW32 + 4096;
|
||||
|
||||
/* Saturate (to 2^28) so that the HP filtered signal does not overflow */
|
||||
tmpW32b = WEBRTC_SPL_SAT((int32_t)268435455, tmpW32b, (int32_t)-268435456);
|
||||
|
||||
/* Convert back to Q0 and multiply with 0.5 */
|
||||
signal[i] = (int16_t)(tmpW32b >> 13);
|
||||
|
||||
/* Update state (filtered part) */
|
||||
y[2] = y[0];
|
||||
y[3] = y[1];
|
||||
|
||||
/* upshift tmpW32 by 3 with saturation */
|
||||
if (tmpW32>268435455) {
|
||||
tmpW32 = WEBRTC_SPL_WORD32_MAX;
|
||||
} else if (tmpW32<-268435456) {
|
||||
tmpW32 = WEBRTC_SPL_WORD32_MIN;
|
||||
} else {
|
||||
tmpW32 <<= 3;
|
||||
}
|
||||
|
||||
y[0] = (int16_t)(tmpW32 >> 16);
|
||||
y[1] = (int16_t)((tmpW32 - (y[0] << 16)) >> 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_HpInput.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
// Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
|
||||
void WebRtcIlbcfix_HpInput(
|
||||
int16_t* signal, /* (i/o) signal vector */
|
||||
int16_t* ba, /* (i) B- and A-coefficients (2:nd order)
|
||||
{b[0] b[1] b[2] -a[1] -a[2]}
|
||||
a[0] is assumed to be 1.0 */
|
||||
int16_t* y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
|
||||
yhi[n-2] ylow[n-2] */
|
||||
int16_t* x, /* (i/o) Filter state x[n-1] x[n-2] */
|
||||
size_t len); /* (i) Number of samples to filter */
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_HpOutput.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/hp_output.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* high-pass filter of output and *2 with saturation
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void WebRtcIlbcfix_HpOutput(
|
||||
int16_t *signal, /* (i/o) signal vector */
|
||||
int16_t *ba, /* (i) B- and A-coefficients (2:nd order)
|
||||
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
|
||||
is assumed to be 1.0 */
|
||||
int16_t *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
|
||||
yhi[n-2] ylow[n-2] */
|
||||
int16_t *x, /* (i/o) Filter state x[n-1] x[n-2] */
|
||||
size_t len) /* (i) Number of samples to filter */
|
||||
{
|
||||
size_t i;
|
||||
int32_t tmpW32;
|
||||
int32_t tmpW32b;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
|
||||
/*
|
||||
y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
|
||||
+ (-a[1])*y[i-1] + (-a[2])*y[i-2];
|
||||
*/
|
||||
|
||||
tmpW32 = y[1] * ba[3]; /* (-a[1])*y[i-1] (low part) */
|
||||
tmpW32 += y[3] * ba[4]; /* (-a[2])*y[i-2] (low part) */
|
||||
tmpW32 = (tmpW32>>15);
|
||||
tmpW32 += y[0] * ba[3]; /* (-a[1])*y[i-1] (high part) */
|
||||
tmpW32 += y[2] * ba[4]; /* (-a[2])*y[i-2] (high part) */
|
||||
tmpW32 *= 2;
|
||||
|
||||
tmpW32 += signal[i] * ba[0]; /* b[0]*x[0] */
|
||||
tmpW32 += x[0] * ba[1]; /* b[1]*x[i-1] */
|
||||
tmpW32 += x[1] * ba[2]; /* b[2]*x[i-2] */
|
||||
|
||||
/* Update state (input part) */
|
||||
x[1] = x[0];
|
||||
x[0] = signal[i];
|
||||
|
||||
/* Rounding in Q(12-1), i.e. add 2^10 */
|
||||
tmpW32b = tmpW32 + 1024;
|
||||
|
||||
/* Saturate (to 2^26) so that the HP filtered signal does not overflow */
|
||||
tmpW32b = WEBRTC_SPL_SAT((int32_t)67108863, tmpW32b, (int32_t)-67108864);
|
||||
|
||||
/* Convert back to Q0 and multiply with 2 */
|
||||
signal[i] = (int16_t)(tmpW32b >> 11);
|
||||
|
||||
/* Update state (filtered part) */
|
||||
y[2] = y[0];
|
||||
y[3] = y[1];
|
||||
|
||||
/* upshift tmpW32 by 3 with saturation */
|
||||
if (tmpW32>268435455) {
|
||||
tmpW32 = WEBRTC_SPL_WORD32_MAX;
|
||||
} else if (tmpW32<-268435456) {
|
||||
tmpW32 = WEBRTC_SPL_WORD32_MIN;
|
||||
} else {
|
||||
tmpW32 *= 8;
|
||||
}
|
||||
|
||||
y[0] = (int16_t)(tmpW32 >> 16);
|
||||
y[1] = (int16_t)((tmpW32 & 0xffff) >> 1);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_HpOutput.h
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
// Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
|
||||
void WebRtcIlbcfix_HpOutput(
|
||||
int16_t* signal, /* (i/o) signal vector */
|
||||
int16_t* ba, /* (i) B- and A-coefficients (2:nd order)
|
||||
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
|
||||
is assumed to be 1.0 */
|
||||
int16_t* y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
|
||||
yhi[n-2] ylow[n-2] */
|
||||
int16_t* x, /* (i/o) Filter state x[n-1] x[n-2] */
|
||||
size_t len); /* (i) Number of samples to filter */
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
iLBCInterface.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/ilbc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/decode.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/encode.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/init_decode.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/init_encode.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst,
|
||||
int16_t* ILBCENC_inst_Addr,
|
||||
int16_t* size) {
|
||||
*iLBC_encinst=(IlbcEncoderInstance*)ILBCENC_inst_Addr;
|
||||
*size=sizeof(IlbcEncoder)/sizeof(int16_t);
|
||||
if (*iLBC_encinst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_DecoderAssign(IlbcDecoderInstance** iLBC_decinst,
|
||||
int16_t* ILBCDEC_inst_Addr,
|
||||
int16_t* size) {
|
||||
*iLBC_decinst=(IlbcDecoderInstance*)ILBCDEC_inst_Addr;
|
||||
*size=sizeof(IlbcDecoder)/sizeof(int16_t);
|
||||
if (*iLBC_decinst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderCreate(IlbcEncoderInstance **iLBC_encinst) {
|
||||
*iLBC_encinst=(IlbcEncoderInstance*)malloc(sizeof(IlbcEncoder));
|
||||
if (*iLBC_encinst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_DecoderCreate(IlbcDecoderInstance **iLBC_decinst) {
|
||||
*iLBC_decinst=(IlbcDecoderInstance*)malloc(sizeof(IlbcDecoder));
|
||||
if (*iLBC_decinst!=NULL) {
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderFree(IlbcEncoderInstance *iLBC_encinst) {
|
||||
free(iLBC_encinst);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_DecoderFree(IlbcDecoderInstance *iLBC_decinst) {
|
||||
free(iLBC_decinst);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderInit(IlbcEncoderInstance* iLBCenc_inst,
|
||||
int16_t mode) {
|
||||
if ((mode==20)||(mode==30)) {
|
||||
WebRtcIlbcfix_InitEncode((IlbcEncoder*) iLBCenc_inst, mode);
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int WebRtcIlbcfix_Encode(IlbcEncoderInstance* iLBCenc_inst,
|
||||
const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded) {
|
||||
size_t pos = 0;
|
||||
size_t encpos = 0;
|
||||
|
||||
if ((len != ((IlbcEncoder*)iLBCenc_inst)->blockl) &&
|
||||
#ifdef SPLIT_10MS
|
||||
(len != 80) &&
|
||||
#endif
|
||||
(len != 2*((IlbcEncoder*)iLBCenc_inst)->blockl) &&
|
||||
(len != 3*((IlbcEncoder*)iLBCenc_inst)->blockl))
|
||||
{
|
||||
/* A maximum of 3 frames/packet is allowed */
|
||||
return(-1);
|
||||
} else {
|
||||
|
||||
/* call encoder */
|
||||
while (pos<len) {
|
||||
WebRtcIlbcfix_EncodeImpl((uint16_t*)&encoded[2 * encpos], &speechIn[pos],
|
||||
(IlbcEncoder*)iLBCenc_inst);
|
||||
#ifdef SPLIT_10MS
|
||||
pos += 80;
|
||||
if(((IlbcEncoder*)iLBCenc_inst)->section == 0)
|
||||
#else
|
||||
pos += ((IlbcEncoder*)iLBCenc_inst)->blockl;
|
||||
#endif
|
||||
encpos += ((IlbcEncoder*)iLBCenc_inst)->no_of_words;
|
||||
}
|
||||
return (int)(encpos*2);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcIlbcfix_DecoderInit(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t mode) {
|
||||
if ((mode==20)||(mode==30)) {
|
||||
WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, mode, 1);
|
||||
return(0);
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
void WebRtcIlbcfix_DecoderInit20Ms(IlbcDecoderInstance* iLBCdec_inst) {
|
||||
WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 20, 1);
|
||||
}
|
||||
void WebRtcIlbcfix_Decoderinit30Ms(IlbcDecoderInstance* iLBCdec_inst) {
|
||||
WebRtcIlbcfix_InitDecode((IlbcDecoder*) iLBCdec_inst, 30, 1);
|
||||
}
|
||||
|
||||
|
||||
int WebRtcIlbcfix_Decode(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType)
|
||||
{
|
||||
size_t i=0;
|
||||
/* Allow for automatic switching between the frame sizes
|
||||
(although you do get some discontinuity) */
|
||||
if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
|
||||
/* ok, do nothing */
|
||||
} else {
|
||||
/* Test if the mode has changed */
|
||||
if (((IlbcDecoder*)iLBCdec_inst)->mode==20) {
|
||||
if ((len==NO_OF_BYTES_30MS)||
|
||||
(len==2*NO_OF_BYTES_30MS)||
|
||||
(len==3*NO_OF_BYTES_30MS)) {
|
||||
WebRtcIlbcfix_InitDecode(
|
||||
((IlbcDecoder*)iLBCdec_inst), 30,
|
||||
((IlbcDecoder*)iLBCdec_inst)->use_enhancer);
|
||||
} else {
|
||||
/* Unsupported frame length */
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
if ((len==NO_OF_BYTES_20MS)||
|
||||
(len==2*NO_OF_BYTES_20MS)||
|
||||
(len==3*NO_OF_BYTES_20MS)) {
|
||||
WebRtcIlbcfix_InitDecode(
|
||||
((IlbcDecoder*)iLBCdec_inst), 20,
|
||||
((IlbcDecoder*)iLBCdec_inst)->use_enhancer);
|
||||
} else {
|
||||
/* Unsupported frame length */
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
|
||||
if (WebRtcIlbcfix_DecodeImpl(
|
||||
&decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
|
||||
(const uint16_t*)&encoded
|
||||
[2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
|
||||
(IlbcDecoder*)iLBCdec_inst, 1) == -1)
|
||||
return -1;
|
||||
i++;
|
||||
}
|
||||
/* iLBC does not support VAD/CNG yet */
|
||||
*speechType=1;
|
||||
return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
|
||||
}
|
||||
|
||||
int WebRtcIlbcfix_Decode20Ms(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType)
|
||||
{
|
||||
size_t i=0;
|
||||
if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
|
||||
/* ok, do nothing */
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
|
||||
if (!WebRtcIlbcfix_DecodeImpl(
|
||||
&decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
|
||||
(const uint16_t*)&encoded
|
||||
[2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
|
||||
(IlbcDecoder*)iLBCdec_inst, 1))
|
||||
return -1;
|
||||
i++;
|
||||
}
|
||||
/* iLBC does not support VAD/CNG yet */
|
||||
*speechType=1;
|
||||
return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
|
||||
}
|
||||
|
||||
int WebRtcIlbcfix_Decode30Ms(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType)
|
||||
{
|
||||
size_t i=0;
|
||||
if ((len==((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==2*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)||
|
||||
(len==3*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)) {
|
||||
/* ok, do nothing */
|
||||
} else {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
while ((i*((IlbcDecoder*)iLBCdec_inst)->no_of_bytes)<len) {
|
||||
if (!WebRtcIlbcfix_DecodeImpl(
|
||||
&decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl],
|
||||
(const uint16_t*)&encoded
|
||||
[2 * i * ((IlbcDecoder*)iLBCdec_inst)->no_of_words],
|
||||
(IlbcDecoder*)iLBCdec_inst, 1))
|
||||
return -1;
|
||||
i++;
|
||||
}
|
||||
/* iLBC does not support VAD/CNG yet */
|
||||
*speechType=1;
|
||||
return (int)(i*((IlbcDecoder*)iLBCdec_inst)->blockl);
|
||||
}
|
||||
|
||||
size_t WebRtcIlbcfix_DecodePlc(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t* decoded,
|
||||
size_t noOfLostFrames) {
|
||||
size_t i;
|
||||
uint16_t dummy;
|
||||
|
||||
for (i=0;i<noOfLostFrames;i++) {
|
||||
// PLC decoding shouldn't fail, because there is no external input data
|
||||
// that can be bad.
|
||||
int result = WebRtcIlbcfix_DecodeImpl(
|
||||
&decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], &dummy,
|
||||
(IlbcDecoder*)iLBCdec_inst, 0);
|
||||
RTC_CHECK_EQ(result, 0);
|
||||
}
|
||||
return (noOfLostFrames*((IlbcDecoder*)iLBCdec_inst)->blockl);
|
||||
}
|
||||
|
||||
size_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t* decoded,
|
||||
size_t noOfLostFrames) {
|
||||
/* Two input parameters not used, but needed for function pointers in NetEQ */
|
||||
(void)(decoded = NULL);
|
||||
(void)(noOfLostFrames = 0);
|
||||
|
||||
WebRtcSpl_MemSetW16(((IlbcDecoder*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL);
|
||||
((IlbcDecoder*)iLBCdec_inst)->prev_enh_pl = 2;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void WebRtcIlbcfix_version(char *version)
|
||||
{
|
||||
strcpy((char*)version, "1.1.1");
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ilbc.h
|
||||
*
|
||||
* This header file contains all of the API's for iLBC.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
|
||||
#define MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Solution to support multiple instances
|
||||
* Customer has to cast instance to proper type
|
||||
*/
|
||||
|
||||
typedef struct iLBC_encinst_t_ IlbcEncoderInstance;
|
||||
|
||||
typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
|
||||
|
||||
/*
|
||||
* Comfort noise constants
|
||||
*/
|
||||
|
||||
#define ILBC_SPEECH 1
|
||||
#define ILBC_CNG 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_XxxAssign(...)
|
||||
*
|
||||
* These functions assigns the encoder/decoder instance to the specified
|
||||
* memory location
|
||||
*
|
||||
* Input:
|
||||
* - XXX_xxxinst : Pointer to created instance that should be
|
||||
* assigned
|
||||
* - ILBCXXX_inst_Addr : Pointer to the desired memory space
|
||||
* - size : The size that this structure occupies (in Word16)
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst,
|
||||
int16_t* ILBCENC_inst_Addr,
|
||||
int16_t* size);
|
||||
int16_t WebRtcIlbcfix_DecoderAssign(IlbcDecoderInstance** iLBC_decinst,
|
||||
int16_t* ILBCDEC_inst_Addr,
|
||||
int16_t* size);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_XxxAssign(...)
|
||||
*
|
||||
* These functions create a instance to the specified structure
|
||||
*
|
||||
* Input:
|
||||
* - XXX_inst : Pointer to created instance that should be created
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderCreate(IlbcEncoderInstance** iLBC_encinst);
|
||||
int16_t WebRtcIlbcfix_DecoderCreate(IlbcDecoderInstance** iLBC_decinst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_XxxFree(...)
|
||||
*
|
||||
* These functions frees the dynamic memory of a specified instance
|
||||
*
|
||||
* Input:
|
||||
* - XXX_inst : Pointer to created instance that should be freed
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderFree(IlbcEncoderInstance* iLBC_encinst);
|
||||
int16_t WebRtcIlbcfix_DecoderFree(IlbcDecoderInstance* iLBC_decinst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_EncoderInit(...)
|
||||
*
|
||||
* This function initializes a iLBC instance
|
||||
*
|
||||
* Input:
|
||||
* - iLBCenc_inst : iLBC instance, i.e. the user that should receive
|
||||
* be initialized
|
||||
* - frameLen : The frame length of the codec 20/30 (ms)
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcIlbcfix_EncoderInit(IlbcEncoderInstance* iLBCenc_inst,
|
||||
int16_t frameLen);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_Encode(...)
|
||||
*
|
||||
* This function encodes one iLBC frame. Input speech length has be a
|
||||
* multiple of the frame length.
|
||||
*
|
||||
* Input:
|
||||
* - iLBCenc_inst : iLBC instance, i.e. the user that should encode
|
||||
* a package
|
||||
* - speechIn : Input speech vector
|
||||
* - len : Samples in speechIn (160, 240, 320 or 480)
|
||||
*
|
||||
* Output:
|
||||
* - encoded : The encoded data vector
|
||||
*
|
||||
* Return value : >0 - Length (in bytes) of coded data
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int WebRtcIlbcfix_Encode(IlbcEncoderInstance* iLBCenc_inst,
|
||||
const int16_t* speechIn,
|
||||
size_t len,
|
||||
uint8_t* encoded);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_DecoderInit(...)
|
||||
*
|
||||
* This function initializes a iLBC instance with either 20 or 30 ms frames
|
||||
* Alternatively the WebRtcIlbcfix_DecoderInit_XXms can be used. Then it's
|
||||
* not needed to specify the frame length with a variable.
|
||||
*
|
||||
* Input:
|
||||
* - IlbcDecoderInstance : iLBC decoder instance
|
||||
* - frameLen : The frame length of the codec 20/30 (ms)
|
||||
*
|
||||
* Return value : 0 - Ok
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int16_t WebRtcIlbcfix_DecoderInit(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t frameLen);
|
||||
void WebRtcIlbcfix_DecoderInit20Ms(IlbcDecoderInstance* iLBCdec_inst);
|
||||
void WebRtcIlbcfix_Decoderinit30Ms(IlbcDecoderInstance* iLBCdec_inst);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_Decode(...)
|
||||
*
|
||||
* This function decodes a packet with iLBC frame(s). Output speech length
|
||||
* will be a multiple of 160 or 240 samples ((160 or 240)*frames/packet).
|
||||
*
|
||||
* Input:
|
||||
* - iLBCdec_inst : iLBC instance, i.e. the user that should decode
|
||||
* a packet
|
||||
* - encoded : Encoded iLBC frame(s)
|
||||
* - len : Bytes in encoded vector
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The decoded vector
|
||||
* - speechType : 1 normal, 2 CNG
|
||||
*
|
||||
* Return value : >0 - Samples in decoded vector
|
||||
* -1 - Error
|
||||
*/
|
||||
|
||||
int WebRtcIlbcfix_Decode(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
int WebRtcIlbcfix_Decode20Ms(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
int WebRtcIlbcfix_Decode30Ms(IlbcDecoderInstance* iLBCdec_inst,
|
||||
const uint8_t* encoded,
|
||||
size_t len,
|
||||
int16_t* decoded,
|
||||
int16_t* speechType);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_DecodePlc(...)
|
||||
*
|
||||
* This function conducts PLC for iLBC frame(s). Output speech length
|
||||
* will be a multiple of 160 or 240 samples.
|
||||
*
|
||||
* Input:
|
||||
* - iLBCdec_inst : iLBC instance, i.e. the user that should perform
|
||||
* a PLC
|
||||
* - noOfLostFrames : Number of PLC frames to produce
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The "decoded" vector
|
||||
*
|
||||
* Return value : Samples in decoded PLC vector
|
||||
*/
|
||||
|
||||
size_t WebRtcIlbcfix_DecodePlc(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t* decoded,
|
||||
size_t noOfLostFrames);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_NetEqPlc(...)
|
||||
*
|
||||
* This function updates the decoder when a packet loss has occured, but it
|
||||
* does not produce any PLC data. Function can be used if another PLC method
|
||||
* is used (i.e NetEq).
|
||||
*
|
||||
* Input:
|
||||
* - iLBCdec_inst : iLBC instance that should be updated
|
||||
* - noOfLostFrames : Number of lost frames
|
||||
*
|
||||
* Output:
|
||||
* - decoded : The "decoded" vector (nothing in this case)
|
||||
*
|
||||
* Return value : Samples in decoded PLC vector
|
||||
*/
|
||||
|
||||
size_t WebRtcIlbcfix_NetEqPlc(IlbcDecoderInstance* iLBCdec_inst,
|
||||
int16_t* decoded,
|
||||
size_t noOfLostFrames);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcIlbcfix_version(...)
|
||||
*
|
||||
* This function returns the version number of iLBC
|
||||
*
|
||||
* Output:
|
||||
* - version : Version number of iLBC (maximum 20 char)
|
||||
*/
|
||||
|
||||
void WebRtcIlbcfix_version(char* version);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2016 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 "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
|
||||
#include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(IlbcTest, BadPacket) {
|
||||
// Get a good packet.
|
||||
AudioEncoderIlbcConfig config;
|
||||
config.frame_size_ms = 20; // We need 20 ms rather than the default 30 ms;
|
||||
// otherwise, all possible values of cb_index[2]
|
||||
// are valid.
|
||||
AudioEncoderIlbcImpl encoder(config, 102);
|
||||
std::vector<int16_t> samples(encoder.SampleRateHz() / 100, 4711);
|
||||
rtc::Buffer packet;
|
||||
int num_10ms_chunks = 0;
|
||||
while (packet.size() == 0) {
|
||||
encoder.Encode(0, samples, &packet);
|
||||
num_10ms_chunks += 1;
|
||||
}
|
||||
|
||||
// Break the packet by setting all bits of the unsigned 7-bit number
|
||||
// cb_index[2] to 1, giving it a value of 127. For a 20 ms packet, this is
|
||||
// too large.
|
||||
EXPECT_EQ(38u, packet.size());
|
||||
rtc::Buffer bad_packet(packet.data(), packet.size());
|
||||
bad_packet[29] |= 0x3f; // Bits 1-6.
|
||||
bad_packet[30] |= 0x80; // Bit 0.
|
||||
|
||||
// Decode the bad packet. We expect the decoder to respond by returning -1.
|
||||
AudioDecoderIlbcImpl decoder;
|
||||
std::vector<int16_t> decoded_samples(num_10ms_chunks * samples.size());
|
||||
AudioDecoder::SpeechType speech_type;
|
||||
EXPECT_EQ(-1, decoder.Decode(bad_packet.data(), bad_packet.size(),
|
||||
encoder.SampleRateHz(),
|
||||
sizeof(int16_t) * decoded_samples.size(),
|
||||
decoded_samples.data(), &speech_type));
|
||||
|
||||
// Decode the good packet. This should work, because the failed decoding
|
||||
// should not have left the decoder in a broken state.
|
||||
EXPECT_EQ(static_cast<int>(decoded_samples.size()),
|
||||
decoder.Decode(packet.data(), packet.size(), encoder.SampleRateHz(),
|
||||
sizeof(int16_t) * decoded_samples.size(),
|
||||
decoded_samples.data(), &speech_type));
|
||||
}
|
||||
|
||||
class SplitIlbcTest : public ::testing::TestWithParam<std::pair<int, int> > {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
const std::pair<int, int> parameters = GetParam();
|
||||
num_frames_ = parameters.first;
|
||||
frame_length_ms_ = parameters.second;
|
||||
frame_length_bytes_ = (frame_length_ms_ == 20) ? 38 : 50;
|
||||
}
|
||||
size_t num_frames_;
|
||||
int frame_length_ms_;
|
||||
size_t frame_length_bytes_;
|
||||
};
|
||||
|
||||
TEST_P(SplitIlbcTest, NumFrames) {
|
||||
AudioDecoderIlbcImpl decoder;
|
||||
const size_t frame_length_samples = frame_length_ms_ * 8;
|
||||
const auto generate_payload = [](size_t payload_length_bytes) {
|
||||
rtc::Buffer payload(payload_length_bytes);
|
||||
// Fill payload with increasing integers {0, 1, 2, ...}.
|
||||
for (size_t i = 0; i < payload.size(); ++i) {
|
||||
payload[i] = static_cast<uint8_t>(i);
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
|
||||
const auto results = decoder.ParsePayload(
|
||||
generate_payload(frame_length_bytes_ * num_frames_), 0);
|
||||
EXPECT_EQ(num_frames_, results.size());
|
||||
|
||||
size_t frame_num = 0;
|
||||
uint8_t payload_value = 0;
|
||||
for (const auto& result : results) {
|
||||
EXPECT_EQ(frame_length_samples * frame_num, result.timestamp);
|
||||
const LegacyEncodedAudioFrame* frame =
|
||||
static_cast<const LegacyEncodedAudioFrame*>(result.frame.get());
|
||||
const rtc::Buffer& payload = frame->payload();
|
||||
EXPECT_EQ(frame_length_bytes_, payload.size());
|
||||
for (size_t i = 0; i < payload.size(); ++i, ++payload_value) {
|
||||
EXPECT_EQ(payload_value, payload[i]);
|
||||
}
|
||||
++frame_num;
|
||||
}
|
||||
}
|
||||
|
||||
// Test 1 through 5 frames of 20 and 30 ms size.
|
||||
// Also test the maximum number of frames in one packet for 20 and 30 ms.
|
||||
// The maximum is defined by the largest payload length that can be uniquely
|
||||
// resolved to a frame size of either 38 bytes (20 ms) or 50 bytes (30 ms).
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IlbcTest,
|
||||
SplitIlbcTest,
|
||||
::testing::Values(std::pair<int, int>(1, 20), // 1 frame, 20 ms.
|
||||
std::pair<int, int>(2, 20), // 2 frames, 20 ms.
|
||||
std::pair<int, int>(3, 20), // And so on.
|
||||
std::pair<int, int>(4, 20),
|
||||
std::pair<int, int>(5, 20),
|
||||
std::pair<int, int>(24, 20),
|
||||
std::pair<int, int>(1, 30),
|
||||
std::pair<int, int>(2, 30),
|
||||
std::pair<int, int>(3, 30),
|
||||
std::pair<int, int>(4, 30),
|
||||
std::pair<int, int>(5, 30),
|
||||
std::pair<int, int>(18, 30)));
|
||||
|
||||
// Test too large payload size.
|
||||
TEST(IlbcTest, SplitTooLargePayload) {
|
||||
AudioDecoderIlbcImpl decoder;
|
||||
constexpr size_t kPayloadLengthBytes = 950;
|
||||
const auto results =
|
||||
decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
|
||||
EXPECT_TRUE(results.empty());
|
||||
}
|
||||
|
||||
// Payload not an integer number of frames.
|
||||
TEST(IlbcTest, SplitUnevenPayload) {
|
||||
AudioDecoderIlbcImpl decoder;
|
||||
constexpr size_t kPayloadLengthBytes = 39; // Not an even number of frames.
|
||||
const auto results =
|
||||
decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
|
||||
EXPECT_TRUE(results.empty());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
WebRtcIlbcfix_IndexConvDec.c
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
|
||||
|
||||
#include "modules/audio_coding/codecs/ilbc/defines.h"
|
||||
|
||||
void WebRtcIlbcfix_IndexConvDec(
|
||||
int16_t *index /* (i/o) Codebook indexes */
|
||||
){
|
||||
int k;
|
||||
|
||||
for (k=4;k<6;k++) {
|
||||
/* Readjust the second and third codebook index for the first 40 sample
|
||||
so that they look the same as the first (in terms of lag)
|
||||
*/
|
||||
if ((index[k]>=44)&&(index[k]<108)) {
|
||||
index[k]+=64;
|
||||
} else if ((index[k]>=108)&&(index[k]<128)) {
|
||||
index[k]+=128;
|
||||
} else {
|
||||
/* ERROR */
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue