Remove non-functional asynchronous resampling mode.

A few other cleanups, most notably using a sane parameter to specify the
number of channels.

BUG=chromium:469814
R=tina.legrand@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8894}
This commit is contained in:
Andrew MacDonald
2015-03-30 10:08:22 -07:00
parent 45c6449114
commit 2c9c83d7ec
8 changed files with 96 additions and 265 deletions

View File

@ -18,26 +18,30 @@
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
namespace webrtc namespace webrtc {
// All methods return 0 on success and -1 on failure.
class Resampler
{ {
// TODO(andrew): the implementation depends on the exact values of this enum. public:
// It should be rewritten in a less fragile way. Resampler();
enum ResamplerType Resampler(int inFreq, int outFreq, int num_channels);
{ ~Resampler();
// 4 MSB = Number of channels
// 4 LSB = Synchronous or asynchronous
kResamplerSynchronous = 0x10, // Reset all states
kResamplerAsynchronous = 0x11, int Reset(int inFreq, int outFreq, int num_channels);
kResamplerSynchronousStereo = 0x20,
kResamplerAsynchronousStereo = 0x21,
kResamplerInvalid = 0xff
};
// TODO(andrew): doesn't need to be part of the interface. // Reset all states if any parameter has changed
enum ResamplerMode int ResetIfNeeded(int inFreq, int outFreq, int num_channels);
{
// Resample samplesIn to samplesOut.
int Push(const int16_t* samplesIn, int lengthIn, int16_t* samplesOut,
int maxLen, int &outLen);
private:
enum ResamplerMode
{
kResamplerMode1To1, kResamplerMode1To1,
kResamplerMode1To2, kResamplerMode1To2,
kResamplerMode1To3, kResamplerMode1To3,
@ -59,34 +63,8 @@ enum ResamplerMode
kResamplerMode11To2, kResamplerMode11To2,
kResamplerMode11To4, kResamplerMode11To4,
kResamplerMode11To8 kResamplerMode11To8
}; };
// All methods return 0 on success and -1 on failure.
class Resampler
{
public:
Resampler();
Resampler(int inFreq, int outFreq, ResamplerType type);
~Resampler();
// Reset all states
int Reset(int inFreq, int outFreq, ResamplerType type);
// Reset all states if any parameter has changed
int ResetIfNeeded(int inFreq, int outFreq, ResamplerType type);
// Synchronous resampling, all output samples are written to samplesOut
int Push(const int16_t* samplesIn, int lengthIn, int16_t* samplesOut,
int maxLen, int &outLen);
// Asynchronous resampling, input
int Insert(int16_t* samplesIn, int lengthIn);
// Asynchronous resampling output, remaining samples are buffered
int Pull(int16_t* samplesOut, int desiredLen, int &outLen);
private:
// Generic pointers since we don't know what states we'll need // Generic pointers since we don't know what states we'll need
void* state1_; void* state1_;
void* state2_; void* state2_;
@ -100,11 +78,10 @@ private:
int in_buffer_size_max_; int in_buffer_size_max_;
int out_buffer_size_max_; int out_buffer_size_max_;
// State
int my_in_frequency_khz_; int my_in_frequency_khz_;
int my_out_frequency_khz_; int my_out_frequency_khz_;
ResamplerMode my_mode_; ResamplerMode my_mode_;
ResamplerType my_type_; int num_channels_;
// Extra instance for stereo // Extra instance for stereo
Resampler* slave_left_; Resampler* slave_left_;

View File

@ -19,50 +19,29 @@
#include "webrtc/common_audio/resampler/include/resampler.h" #include "webrtc/common_audio/resampler/include/resampler.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
namespace webrtc {
namespace webrtc
{
Resampler::Resampler() Resampler::Resampler()
{ : state1_(nullptr),
state1_ = NULL; state2_(nullptr),
state2_ = NULL; state3_(nullptr),
state3_ = NULL; in_buffer_(nullptr),
in_buffer_ = NULL; out_buffer_(nullptr),
out_buffer_ = NULL; in_buffer_size_(0),
in_buffer_size_ = 0; out_buffer_size_(0),
out_buffer_size_ = 0; in_buffer_size_max_(0),
in_buffer_size_max_ = 0; out_buffer_size_max_(0),
out_buffer_size_max_ = 0; my_in_frequency_khz_(0),
// we need a reset before we will work my_out_frequency_khz_(0),
my_in_frequency_khz_ = 0; my_mode_(kResamplerMode1To1),
my_out_frequency_khz_ = 0; num_channels_(0),
my_mode_ = kResamplerMode1To1; slave_left_(nullptr),
my_type_ = kResamplerInvalid; slave_right_(nullptr) {
slave_left_ = NULL;
slave_right_ = NULL;
} }
Resampler::Resampler(int inFreq, int outFreq, ResamplerType type) Resampler::Resampler(int inFreq, int outFreq, int num_channels)
{ : Resampler() {
state1_ = NULL; Reset(inFreq, outFreq, num_channels);
state2_ = NULL;
state3_ = NULL;
in_buffer_ = NULL;
out_buffer_ = NULL;
in_buffer_size_ = 0;
out_buffer_size_ = 0;
in_buffer_size_max_ = 0;
out_buffer_size_max_ = 0;
// we need a reset before we will work
my_in_frequency_khz_ = 0;
my_out_frequency_khz_ = 0;
my_mode_ = kResamplerMode1To1;
my_type_ = kResamplerInvalid;
slave_left_ = NULL;
slave_right_ = NULL;
Reset(inFreq, outFreq, type);
} }
Resampler::~Resampler() Resampler::~Resampler()
@ -97,23 +76,27 @@ Resampler::~Resampler()
} }
} }
int Resampler::ResetIfNeeded(int inFreq, int outFreq, ResamplerType type) int Resampler::ResetIfNeeded(int inFreq, int outFreq, int num_channels)
{ {
int tmpInFreq_kHz = inFreq / 1000; int tmpInFreq_kHz = inFreq / 1000;
int tmpOutFreq_kHz = outFreq / 1000; int tmpOutFreq_kHz = outFreq / 1000;
if ((tmpInFreq_kHz != my_in_frequency_khz_) || (tmpOutFreq_kHz != my_out_frequency_khz_) if ((tmpInFreq_kHz != my_in_frequency_khz_) || (tmpOutFreq_kHz != my_out_frequency_khz_)
|| (type != my_type_)) || (num_channels != num_channels_))
{ {
return Reset(inFreq, outFreq, type); return Reset(inFreq, outFreq, num_channels);
} else } else
{ {
return 0; return 0;
} }
} }
int Resampler::Reset(int inFreq, int outFreq, ResamplerType type) int Resampler::Reset(int inFreq, int outFreq, int num_channels)
{ {
if (num_channels != 1 && num_channels != 2) {
return -1;
}
num_channels_ = num_channels;
if (state1_) if (state1_)
{ {
@ -156,11 +139,7 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
in_buffer_size_max_ = 0; in_buffer_size_max_ = 0;
out_buffer_size_max_ = 0; out_buffer_size_max_ = 0;
// This might be overridden if parameters are not accepted.
my_type_ = type;
// Start with a math exercise, Euclid's algorithm to find the gcd: // Start with a math exercise, Euclid's algorithm to find the gcd:
int a = inFreq; int a = inFreq;
int b = outFreq; int b = outFreq;
int c = a % b; int c = a % b;
@ -180,14 +159,11 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
inFreq = inFreq / b; inFreq = inFreq / b;
outFreq = outFreq / b; outFreq = outFreq / b;
// Do we need stereo? if (num_channels_ == 2)
if ((my_type_ & 0xf0) == 0x20)
{ {
// Change type to mono // Create two mono resamplers.
type = static_cast<ResamplerType>( slave_left_ = new Resampler(inFreq, outFreq, 1);
((static_cast<int>(type) & 0x0f) + 0x10)); slave_right_ = new Resampler(inFreq, outFreq, 1);
slave_left_ = new Resampler(inFreq, outFreq, type);
slave_right_ = new Resampler(inFreq, outFreq, type);
} }
if (inFreq == outFreq) if (inFreq == outFreq)
@ -213,7 +189,6 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
my_mode_ = kResamplerMode1To12; my_mode_ = kResamplerMode1To12;
break; break;
default: default:
my_type_ = kResamplerInvalid;
return -1; return -1;
} }
} else if (outFreq == 1) } else if (outFreq == 1)
@ -236,7 +211,6 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
my_mode_ = kResamplerMode12To1; my_mode_ = kResamplerMode12To1;
break; break;
default: default:
my_type_ = kResamplerInvalid;
return -1; return -1;
} }
} else if ((inFreq == 2) && (outFreq == 3)) } else if ((inFreq == 2) && (outFreq == 3))
@ -271,7 +245,6 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
my_mode_ = kResamplerMode11To8; my_mode_ = kResamplerMode11To8;
} else } else
{ {
my_type_ = kResamplerInvalid;
return -1; return -1;
} }
@ -428,21 +401,12 @@ int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
} }
// Synchronous resampling, all output samples are written to samplesOut // Synchronous resampling, all output samples are written to samplesOut
int Resampler::Push(const int16_t * samplesIn, int lengthIn, int16_t* samplesOut, int Resampler::Push(const int16_t * samplesIn, int lengthIn,
int maxLen, int &outLen) int16_t* samplesOut, int maxLen, int &outLen)
{ {
// Check that the resampler is not in asynchronous mode if (num_channels_ == 2)
if (my_type_ & 0x0f)
{ {
return -1;
}
// Do we have a stereo signal?
if ((my_type_ & 0xf0) == 0x20)
{
// Split up the signal and call the slave object for each channel // Split up the signal and call the slave object for each channel
int16_t* left = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2); int16_t* left = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2);
int16_t* right = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2); int16_t* right = (int16_t*)malloc(lengthIn * sizeof(int16_t) / 2);
int16_t* out_left = (int16_t*)malloc(maxLen / 2 * sizeof(int16_t)); int16_t* out_left = (int16_t*)malloc(maxLen / 2 * sizeof(int16_t));
@ -992,93 +956,4 @@ int Resampler::Push(const int16_t * samplesIn, int lengthIn, int16_t* samplesOut
return 0; return 0;
} }
// Asynchronous resampling, input
int Resampler::Insert(int16_t * samplesIn, int lengthIn)
{
if (my_type_ != kResamplerAsynchronous)
{
return -1;
}
int sizeNeeded, tenMsblock;
// Determine need for size of outBuffer
sizeNeeded = out_buffer_size_ + ((lengthIn + in_buffer_size_) * my_out_frequency_khz_)
/ my_in_frequency_khz_;
if (sizeNeeded > out_buffer_size_max_)
{
// Round the value upwards to complete 10 ms blocks
tenMsblock = my_out_frequency_khz_ * 10;
sizeNeeded = (sizeNeeded / tenMsblock + 1) * tenMsblock;
out_buffer_ = (int16_t*)realloc(out_buffer_, sizeNeeded * sizeof(int16_t));
out_buffer_size_max_ = sizeNeeded;
}
// If we need to use inBuffer, make sure all input data fits there.
tenMsblock = my_in_frequency_khz_ * 10;
if (in_buffer_size_ || (lengthIn % tenMsblock))
{
// Check if input buffer size is enough
if ((in_buffer_size_ + lengthIn) > in_buffer_size_max_)
{
// Round the value upwards to complete 10 ms blocks
sizeNeeded = ((in_buffer_size_ + lengthIn) / tenMsblock + 1) * tenMsblock;
in_buffer_ = (int16_t*)realloc(in_buffer_,
sizeNeeded * sizeof(int16_t));
in_buffer_size_max_ = sizeNeeded;
}
// Copy in data to input buffer
memcpy(in_buffer_ + in_buffer_size_, samplesIn, lengthIn * sizeof(int16_t));
// Resample all available 10 ms blocks
int lenOut;
int dataLenToResample = (in_buffer_size_ / tenMsblock) * tenMsblock;
Push(in_buffer_, dataLenToResample, out_buffer_ + out_buffer_size_,
out_buffer_size_max_ - out_buffer_size_, lenOut);
out_buffer_size_ += lenOut;
// Save the rest
memmove(in_buffer_, in_buffer_ + dataLenToResample,
(in_buffer_size_ - dataLenToResample) * sizeof(int16_t));
in_buffer_size_ -= dataLenToResample;
} else
{
// Just resample
int lenOut;
Push(in_buffer_, lengthIn, out_buffer_ + out_buffer_size_,
out_buffer_size_max_ - out_buffer_size_, lenOut);
out_buffer_size_ += lenOut;
}
return 0;
}
// Asynchronous resampling output, remaining samples are buffered
int Resampler::Pull(int16_t* samplesOut, int desiredLen, int &outLen)
{
if (my_type_ != kResamplerAsynchronous)
{
return -1;
}
// Check that we have enough data
if (desiredLen <= out_buffer_size_)
{
// Give out the date
memcpy(samplesOut, out_buffer_, desiredLen * sizeof(int32_t));
// Shuffle down remaining
memmove(out_buffer_, out_buffer_ + desiredLen,
(out_buffer_size_ - desiredLen) * sizeof(int16_t));
// Update remaining size
out_buffer_size_ -= desiredLen;
return 0;
} else
{
return -1;
}
}
} // namespace webrtc } // namespace webrtc

View File

@ -16,14 +16,9 @@
namespace webrtc { namespace webrtc {
namespace { namespace {
const ResamplerType kTypes[] = {
kResamplerSynchronous, const int kNumChannels[] = {1, 2};
kResamplerAsynchronous, const size_t kNumChannelsSize = sizeof(kNumChannels) / sizeof(*kNumChannels);
kResamplerSynchronousStereo,
kResamplerAsynchronousStereo
// kResamplerInvalid excluded
};
const size_t kTypesSize = sizeof(kTypes) / sizeof(*kTypes);
// Rates we must support. // Rates we must support.
const int kMaxRate = 96000; const int kMaxRate = 96000;
@ -78,15 +73,15 @@ TEST_F(ResamplerTest, Reset) {
// Check that all required combinations are supported. // Check that all required combinations are supported.
for (size_t i = 0; i < kRatesSize; ++i) { for (size_t i = 0; i < kRatesSize; ++i) {
for (size_t j = 0; j < kRatesSize; ++j) { for (size_t j = 0; j < kRatesSize; ++j) {
for (size_t k = 0; k < kTypesSize; ++k) { for (size_t k = 0; k < kNumChannelsSize; ++k) {
std::ostringstream ss; std::ostringstream ss;
ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j] ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j]
<< ", type: " << kTypes[k]; << ", channels: " << kNumChannels[k];
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
if (ValidRates(kRates[i], kRates[j])) if (ValidRates(kRates[i], kRates[j]))
EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kTypes[k])); EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kNumChannels[k]));
else else
EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kTypes[k])); EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kNumChannels[k]));
} }
} }
} }
@ -94,7 +89,8 @@ TEST_F(ResamplerTest, Reset) {
// TODO(tlegrand): Replace code inside the two tests below with a function // TODO(tlegrand): Replace code inside the two tests below with a function
// with number of channels and ResamplerType as input. // with number of channels and ResamplerType as input.
TEST_F(ResamplerTest, Synchronous) { TEST_F(ResamplerTest, Mono) {
const int kChannels = 1;
for (size_t i = 0; i < kRatesSize; ++i) { for (size_t i = 0; i < kRatesSize; ++i) {
for (size_t j = 0; j < kRatesSize; ++j) { for (size_t j = 0; j < kRatesSize; ++j) {
std::ostringstream ss; std::ostringstream ss;
@ -104,19 +100,18 @@ TEST_F(ResamplerTest, Synchronous) {
if (ValidRates(kRates[i], kRates[j])) { if (ValidRates(kRates[i], kRates[j])) {
int in_length = kRates[i] / 100; int in_length = kRates[i] / 100;
int out_length = 0; int out_length = 0;
EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous)); EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kChannels));
EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize, EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize,
out_length)); out_length));
EXPECT_EQ(kRates[j] / 100, out_length); EXPECT_EQ(kRates[j] / 100, out_length);
} else { } else {
EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous)); EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kChannels));
} }
} }
} }
} }
TEST_F(ResamplerTest, SynchronousStereo) { TEST_F(ResamplerTest, Stereo) {
// Number of channels is 2, stereo mode.
const int kChannels = 2; const int kChannels = 2;
for (size_t i = 0; i < kRatesSize; ++i) { for (size_t i = 0; i < kRatesSize; ++i) {
for (size_t j = 0; j < kRatesSize; ++j) { for (size_t j = 0; j < kRatesSize; ++j) {
@ -128,16 +123,17 @@ TEST_F(ResamplerTest, SynchronousStereo) {
int in_length = kChannels * kRates[i] / 100; int in_length = kChannels * kRates[i] / 100;
int out_length = 0; int out_length = 0;
EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j],
kResamplerSynchronousStereo)); kChannels));
EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize, EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize,
out_length)); out_length));
EXPECT_EQ(kChannels * kRates[j] / 100, out_length); EXPECT_EQ(kChannels * kRates[j] / 100, out_length);
} else { } else {
EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j],
kResamplerSynchronousStereo)); kChannels));
} }
} }
} }
} }
} // namespace } // namespace
} // namespace webrtc } // namespace webrtc

View File

@ -25,8 +25,7 @@ bool ResampleInputAudioFile::Read(size_t samples,
rtc::scoped_ptr<int16_t[]> temp_destination(new int16_t[samples_to_read]); rtc::scoped_ptr<int16_t[]> temp_destination(new int16_t[samples_to_read]);
if (!InputAudioFile::Read(samples_to_read, temp_destination.get())) if (!InputAudioFile::Read(samples_to_read, temp_destination.get()))
return false; return false;
resampler_.ResetIfNeeded( resampler_.ResetIfNeeded(file_rate_hz_, output_rate_hz, 1);
file_rate_hz_, output_rate_hz, kResamplerSynchronous);
int output_length = 0; int output_length = 0;
CHECK_EQ(resampler_.Push(temp_destination.get(), CHECK_EQ(resampler_.Push(temp_destination.get(),
static_cast<int>(samples_to_read), static_cast<int>(samples_to_read),

View File

@ -96,7 +96,7 @@ AudioTransportImpl::AudioTransportImpl(AudioDeviceModule* audioDevice) :
_recCount(0), _recCount(0),
_playCount(0) _playCount(0)
{ {
_resampler.Reset(48000, 48000, kResamplerSynchronousStereo); _resampler.Reset(48000, 48000, 2);
} }
AudioTransportImpl::~AudioTransportImpl() AudioTransportImpl::~AudioTransportImpl()
@ -332,8 +332,7 @@ int32_t AudioTransportImpl::NeedMorePlayData(
if (nChannelsIn == 2 && nBytesPerSampleIn == 4) if (nChannelsIn == 2 && nBytesPerSampleIn == 4)
{ {
// input is stereo => we will resample in stereo // input is stereo => we will resample in stereo
ret = _resampler.ResetIfNeeded(fsInHz, fsOutHz, ret = _resampler.ResetIfNeeded(fsInHz, fsOutHz, 2);
kResamplerSynchronousStereo);
if (ret == 0) if (ret == 0)
{ {
if (nChannels == 2) if (nChannels == 2)
@ -374,8 +373,7 @@ int32_t AudioTransportImpl::NeedMorePlayData(
{ {
// input is mono (can be "reduced from stereo" as well) => // input is mono (can be "reduced from stereo" as well) =>
// we will resample in mono // we will resample in mono
ret = _resampler.ResetIfNeeded(fsInHz, fsOutHz, ret = _resampler.ResetIfNeeded(fsInHz, fsOutHz, 1);
kResamplerSynchronous);
if (ret == 0) if (ret == 0)
{ {
if (nChannels == 1) if (nChannels == 1)

View File

@ -45,7 +45,7 @@ Agc::Agc()
pitch_based_vad_(new PitchBasedVad()), pitch_based_vad_(new PitchBasedVad()),
standalone_vad_(StandaloneVad::Create()), standalone_vad_(StandaloneVad::Create()),
// Initialize to the most common resampling situation. // Initialize to the most common resampling situation.
resampler_(new Resampler(32000, kSampleRateHz, kResamplerSynchronous)) { resampler_(new Resampler(32000, kSampleRateHz, 1)) {
} }
Agc::~Agc() {} Agc::~Agc() {}
@ -69,9 +69,7 @@ int Agc::Process(const int16_t* audio, int length, int sample_rate_hz) {
int16_t resampled[kLength10Ms]; int16_t resampled[kLength10Ms];
const int16_t* resampled_ptr = audio; const int16_t* resampled_ptr = audio;
if (sample_rate_hz != kSampleRateHz) { if (sample_rate_hz != kSampleRateHz) {
if (resampler_->ResetIfNeeded(sample_rate_hz, if (resampler_->ResetIfNeeded(sample_rate_hz, kSampleRateHz, 1) != 0) {
kSampleRateHz,
kResamplerSynchronous) != 0) {
return -1; return -1;
} }
resampler_->Push(audio, length, resampled, kLength10Ms, length); resampler_->Push(audio, length, resampled, kLength10Ms, length);

View File

@ -130,7 +130,7 @@ int32_t FilePlayerImpl::Get10msAudioFromFile(
unresampledAudioFrame.samples_per_channel_ = unresampledAudioFrame.samples_per_channel_ =
(uint16_t)lengthInBytes >> 1; (uint16_t)lengthInBytes >> 1;
}else { } else {
// Decode will generate 10 ms of audio data. PlayoutAudioData(..) // Decode will generate 10 ms of audio data. PlayoutAudioData(..)
// expects a full frame. If the frame size is larger than 10 ms, // expects a full frame. If the frame size is larger than 10 ms,
// PlayoutAudioData(..) data should be called proportionally less often. // PlayoutAudioData(..) data should be called proportionally less often.
@ -158,7 +158,7 @@ int32_t FilePlayerImpl::Get10msAudioFromFile(
int outLen = 0; int outLen = 0;
if(_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_, if(_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_,
frequencyInHz, kResamplerSynchronous)) frequencyInHz, 1))
{ {
LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec."; LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec.";

View File

@ -211,26 +211,14 @@ int32_t FileRecorderImpl::RecordAudioToFile(
} }
} else { } else {
int outLen = 0; int outLen = 0;
if(ptrAudioFrame->num_channels_ == 2)
{
// ptrAudioFrame contains interleaved stereo audio.
_audioResampler.ResetIfNeeded(ptrAudioFrame->sample_rate_hz_, _audioResampler.ResetIfNeeded(ptrAudioFrame->sample_rate_hz_,
codec_info_.plfreq, codec_info_.plfreq,
kResamplerSynchronousStereo); ptrAudioFrame->num_channels_);
_audioResampler.Push(ptrAudioFrame->data_, _audioResampler.Push(ptrAudioFrame->data_,
ptrAudioFrame->samples_per_channel_ * ptrAudioFrame->samples_per_channel_ *
ptrAudioFrame->num_channels_, ptrAudioFrame->num_channels_,
(int16_t*)_audioBuffer, (int16_t*)_audioBuffer,
MAX_AUDIO_BUFFER_IN_BYTES, outLen); MAX_AUDIO_BUFFER_IN_BYTES, outLen);
} else {
_audioResampler.ResetIfNeeded(ptrAudioFrame->sample_rate_hz_,
codec_info_.plfreq,
kResamplerSynchronous);
_audioResampler.Push(ptrAudioFrame->data_,
ptrAudioFrame->samples_per_channel_,
(int16_t*)_audioBuffer,
MAX_AUDIO_BUFFER_IN_BYTES, outLen);
}
encodedLenInBytes = outLen * sizeof(int16_t); encodedLenInBytes = outLen * sizeof(int16_t);
} }