Support for CELT in NetEq4.

BUG=1359
R=henrik.lundin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2291004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4884 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
turaj@webrtc.org 2013-09-30 20:07:39 +00:00
parent 7e809c323a
commit 6ad6a07fd3
4 changed files with 206 additions and 7 deletions

View File

@ -74,6 +74,10 @@ bool AudioDecoder::CodecSupported(NetEqDecoder codec_type) {
case kDecoderG722:
case kDecoderG722_2ch:
#endif
#ifdef WEBRTC_CODEC_CELT
case kDecoderCELT_32:
case kDecoderCELT_32_2ch:
#endif
#ifdef WEBRTC_CODEC_OPUS
case kDecoderOpus:
case kDecoderOpus_2ch:
@ -131,6 +135,10 @@ int AudioDecoder::CodecSampleRateHz(NetEqDecoder codec_type) {
#ifdef WEBRTC_CODEC_PCM16
case kDecoderPCM16Bswb32kHz:
case kDecoderPCM16Bswb32kHz_2ch:
#endif
#ifdef WEBRTC_CODEC_CELT
case kDecoderCELT_32:
case kDecoderCELT_32_2ch:
#endif
case kDecoderCNGswb32kHz: {
return 32000;
@ -206,6 +214,11 @@ AudioDecoder* AudioDecoder::CreateAudioDecoder(NetEqDecoder codec_type) {
case kDecoderG722_2ch:
return new AudioDecoderG722Stereo;
#endif
#ifdef WEBRTC_CODEC_CELT
case kDecoderCELT_32:
case kDecoderCELT_32_2ch:
return new AudioDecoderCelt(codec_type);
#endif
#ifdef WEBRTC_CODEC_OPUS
case kDecoderOpus:
case kDecoderOpus_2ch:

View File

@ -13,6 +13,9 @@
#include <assert.h>
#include <string.h> // memmove
#ifdef WEBRTC_CODEC_CELT
#include "webrtc/modules/audio_coding/codecs/celt/include/celt_interface.h"
#endif
#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
#ifdef WEBRTC_CODEC_G722
@ -377,6 +380,55 @@ void AudioDecoderG722Stereo::SplitStereoPacket(const uint8_t* encoded,
}
#endif
// CELT
#ifdef WEBRTC_CODEC_CELT
AudioDecoderCelt::AudioDecoderCelt(enum NetEqDecoder type)
: AudioDecoder(type) {
assert(type == kDecoderCELT_32 || type == kDecoderCELT_32_2ch);
if (type == kDecoderCELT_32) {
channels_ = 1;
} else {
channels_ = 2;
}
WebRtcCelt_CreateDec(reinterpret_cast<CELT_decinst_t**>(&state_),
static_cast<int>(channels_));
}
AudioDecoderCelt::~AudioDecoderCelt() {
WebRtcCelt_FreeDec(static_cast<CELT_decinst_t*>(state_));
}
int AudioDecoderCelt::Decode(const uint8_t* encoded, size_t encoded_len,
int16_t* decoded, SpeechType* speech_type) {
int16_t temp_type = 1; // Default to speech.
int ret = WebRtcCelt_DecodeUniversal(static_cast<CELT_decinst_t*>(state_),
encoded, static_cast<int>(encoded_len),
decoded, &temp_type);
*speech_type = ConvertSpeechType(temp_type);
if (ret < 0) {
return -1;
}
// Return the total number of samples.
return ret * static_cast<int>(channels_);
}
int AudioDecoderCelt::Init() {
return WebRtcCelt_DecoderInit(static_cast<CELT_decinst_t*>(state_));
}
bool AudioDecoderCelt::HasDecodePlc() const { return true; }
int AudioDecoderCelt::DecodePlc(int num_frames, int16_t* decoded) {
int ret = WebRtcCelt_DecodePlc(static_cast<CELT_decinst_t*>(state_),
decoded, num_frames);
if (ret < 0) {
return -1;
}
// Return the total number of samples.
return ret * static_cast<int>(channels_);
}
#endif
// Opus
#ifdef WEBRTC_CODEC_OPUS
AudioDecoderOpus::AudioDecoderOpus(enum NetEqDecoder type)

View File

@ -212,6 +212,23 @@ class AudioDecoderG722Stereo : public AudioDecoderG722 {
};
#endif
#ifdef WEBRTC_CODEC_CELT
class AudioDecoderCelt : public AudioDecoder {
public:
explicit AudioDecoderCelt(enum NetEqDecoder type);
virtual ~AudioDecoderCelt();
virtual int Decode(const uint8_t* encoded, size_t encoded_len,
int16_t* decoded, SpeechType* speech_type);
virtual int Init();
virtual bool HasDecodePlc() const;
virtual int DecodePlc(int num_frames, int16_t* decoded);
private:
DISALLOW_COPY_AND_ASSIGN(AudioDecoderCelt);
};
#endif
#ifdef WEBRTC_CODEC_OPUS
class AudioDecoderOpus : public AudioDecoder {
public:

View File

@ -17,6 +17,9 @@
#include "gtest/gtest.h"
#include "webrtc/common_audio/resampler/include/resampler.h"
#ifdef WEBRTC_CODEC_CELT
#include "webrtc/modules/audio_coding/codecs/celt/include/celt_interface.h"
#endif
#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
@ -143,11 +146,12 @@ class AudioDecoderTest : public ::testing::Test {
// The absolute difference between the two channels in a stereo is compared vs
// |tolerance|.
virtual void CompareTwoChannels(size_t num_samples, int tolerance) const {
assert(num_samples <= data_length_);
for (unsigned int n = 0; n < num_samples; ++n)
ASSERT_NEAR(decoded_[channels_ * n], decoded_[channels_ * n + 1],
tolerance) << "Stereo samples differ.";
virtual void CompareTwoChannels(size_t samples_per_channel,
int tolerance) const {
assert(samples_per_channel <= data_length_);
for (unsigned int n = 0; n < samples_per_channel; ++n)
ASSERT_NEAR(decoded_[channels_ * n], decoded_[channels_ * n + 1],
tolerance) << "Stereo samples differ.";
}
// Calculates mean-squared error between input and output (the first channel).
@ -199,12 +203,12 @@ class AudioDecoderTest : public ::testing::Test {
EXPECT_EQ(0, decoder_->Init());
size_t dec_len =
decoder_->Decode(encoded_, enc_len, decoded_, &speech_type);
EXPECT_EQ(frame_size_, dec_len);
EXPECT_EQ(frame_size_ * channels_, dec_len);
// Call DecodePlc and verify that we get one frame of data.
// (Overwrite the output from the above Decode call, but that does not
// matter.)
dec_len = decoder_->DecodePlc(1, decoded_);
EXPECT_EQ(frame_size_, dec_len);
EXPECT_EQ(frame_size_ * channels_, dec_len);
}
std::string input_file_;
@ -527,6 +531,77 @@ class AudioDecoderG722StereoTest : public AudioDecoderG722Test {
}
};
#ifdef WEBRTC_CODEC_CELT
class AudioDecoderCeltTest : public AudioDecoderTest {
protected:
static const int kEncodingRateBitsPerSecond = 64000;
AudioDecoderCeltTest() : AudioDecoderTest(), encoder_(NULL) {
frame_size_ = 640;
data_length_ = 10 * frame_size_;
decoder_ = AudioDecoder::CreateAudioDecoder(kDecoderCELT_32);
assert(decoder_);
WebRtcCelt_CreateEnc(&encoder_, static_cast<int>(channels_));
}
~AudioDecoderCeltTest() {
WebRtcCelt_FreeEnc(encoder_);
}
virtual void InitEncoder() {
assert(encoder_);
ASSERT_EQ(0, WebRtcCelt_EncoderInit(
encoder_, static_cast<int>(channels_), kEncodingRateBitsPerSecond));
}
virtual int EncodeFrame(const int16_t* input, size_t input_len_samples,
uint8_t* output) {
assert(encoder_);
return WebRtcCelt_Encode(encoder_, input, output);
}
CELT_encinst_t* encoder_;
};
class AudioDecoderCeltStereoTest : public AudioDecoderTest {
protected:
static const int kEncodingRateBitsPerSecond = 64000;
AudioDecoderCeltStereoTest() : AudioDecoderTest(), encoder_(NULL) {
channels_ = 2;
frame_size_ = 640;
data_length_ = 10 * frame_size_;
decoder_ = AudioDecoder::CreateAudioDecoder(kDecoderCELT_32_2ch);
assert(decoder_);
stereo_input_ = new int16_t[frame_size_ * channels_];
WebRtcCelt_CreateEnc(&encoder_, static_cast<int>(channels_));
}
~AudioDecoderCeltStereoTest() {
delete [] stereo_input_;
WebRtcCelt_FreeEnc(encoder_);
}
virtual void InitEncoder() {
assert(encoder_);
ASSERT_EQ(0, WebRtcCelt_EncoderInit(
encoder_, static_cast<int>(channels_), kEncodingRateBitsPerSecond));
}
virtual int EncodeFrame(const int16_t* input, size_t input_len_samples,
uint8_t* output) {
assert(encoder_);
assert(stereo_input_);
for (size_t n = 0; n < frame_size_; ++n) {
stereo_input_[n * 2] = stereo_input_[n * 2 + 1] = input[n];
}
return WebRtcCelt_Encode(encoder_, stereo_input_, output);
}
int16_t* stereo_input_;
CELT_encinst_t* encoder_;
};
#endif
class AudioDecoderOpusTest : public AudioDecoderTest {
protected:
AudioDecoderOpusTest() : AudioDecoderTest() {
@ -742,6 +817,38 @@ TEST_F(AudioDecoderOpusStereoTest, EncodeDecode) {
EXPECT_FALSE(decoder_->HasDecodePlc());
}
#ifdef WEBRTC_CODEC_CELT
// In the two following CELT tests, the low amplitude of the test signal allow
// us to have such low error thresholds, i.e. |tolerance|, |mse|. Furthermore,
// in general, stereo signals with identical channels do not result in identical
// encoded channels.
TEST_F(AudioDecoderCeltTest, EncodeDecode) {
int tolerance = 20;
double mse = 17.0;
int delay = 80; // Delay from input to output in samples.
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderCELT_32));
EncodeDecodeTest(1600, tolerance, mse, delay);
ReInitTest();
EXPECT_TRUE(decoder_->HasDecodePlc());
DecodePlcTest();
}
TEST_F(AudioDecoderCeltStereoTest, EncodeDecode) {
int tolerance = 20;
// If both channels are identical, CELT not necessarily decodes identical
// channels. However, for this input this is the case.
int channel_diff_tolerance = 0;
double mse = 20.0;
// Delay from input to output in samples, accounting for stereo.
int delay = 160;
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderCELT_32_2ch));
EncodeDecodeTest(1600, tolerance, mse, delay, channel_diff_tolerance);
ReInitTest();
EXPECT_TRUE(decoder_->HasDecodePlc());
DecodePlcTest();
}
#endif
TEST(AudioDecoder, CodecSampleRateHz) {
EXPECT_EQ(8000, AudioDecoder::CodecSampleRateHz(kDecoderPCMu));
EXPECT_EQ(8000, AudioDecoder::CodecSampleRateHz(kDecoderPCMa));
@ -772,8 +879,13 @@ TEST(AudioDecoder, CodecSampleRateHz) {
EXPECT_EQ(-1, AudioDecoder::CodecSampleRateHz(kDecoderArbitrary));
EXPECT_EQ(32000, AudioDecoder::CodecSampleRateHz(kDecoderOpus));
EXPECT_EQ(32000, AudioDecoder::CodecSampleRateHz(kDecoderOpus_2ch));
#ifdef WEBRTC_CODEC_CELT
EXPECT_EQ(32000, AudioDecoder::CodecSampleRateHz(kDecoderCELT_32));
EXPECT_EQ(32000, AudioDecoder::CodecSampleRateHz(kDecoderCELT_32_2ch));
#else
EXPECT_EQ(-1, AudioDecoder::CodecSampleRateHz(kDecoderCELT_32));
EXPECT_EQ(-1, AudioDecoder::CodecSampleRateHz(kDecoderCELT_32_2ch));
#endif
}
TEST(AudioDecoder, CodecSupported) {
@ -805,8 +917,13 @@ TEST(AudioDecoder, CodecSupported) {
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderArbitrary));
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderOpus));
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderOpus_2ch));
#ifdef WEBRTC_CODEC_CELT
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderCELT_32));
EXPECT_TRUE(AudioDecoder::CodecSupported(kDecoderCELT_32_2ch));
#else
EXPECT_FALSE(AudioDecoder::CodecSupported(kDecoderCELT_32));
EXPECT_FALSE(AudioDecoder::CodecSupported(kDecoderCELT_32_2ch));
#endif
}
} // namespace webrtc