Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue