Resampler modifications in preparation for arbitrary audioproc rates.
- Templatize PushResampler to support int16 and float. - Add a helper method to PushSincResampler to compute the algorithmic delay. This is a prerequisite of: http://review.webrtc.org/9919004/ BUG=2894 R=turaj@webrtc.org Review URL: https://webrtc-codereview.appspot.com/12169004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5943 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
3d9ec1fed4
commit
f5a33f145b
@ -20,6 +20,7 @@ class PushSincResampler;
|
||||
|
||||
// Wraps PushSincResampler to provide stereo support.
|
||||
// TODO(ajm): add support for an arbitrary number of channels.
|
||||
template <typename T>
|
||||
class PushResampler {
|
||||
public:
|
||||
PushResampler();
|
||||
@ -32,22 +33,18 @@ class PushResampler {
|
||||
|
||||
// Returns the total number of samples provided in destination (e.g. 32 kHz,
|
||||
// 2 channel audio gives 640 samples).
|
||||
int Resample(const int16_t* src, int src_length, int16_t* dst,
|
||||
int dst_capacity);
|
||||
int Resample(const T* src, int src_length, T* dst, int dst_capacity);
|
||||
|
||||
private:
|
||||
int ResampleSinc(const int16_t* src, int src_length, int16_t* dst,
|
||||
int dst_capacity);
|
||||
|
||||
scoped_ptr<PushSincResampler> sinc_resampler_;
|
||||
scoped_ptr<PushSincResampler> sinc_resampler_right_;
|
||||
int src_sample_rate_hz_;
|
||||
int dst_sample_rate_hz_;
|
||||
int num_channels_;
|
||||
scoped_array<int16_t> src_left_;
|
||||
scoped_array<int16_t> src_right_;
|
||||
scoped_array<int16_t> dst_left_;
|
||||
scoped_array<int16_t> dst_right_;
|
||||
scoped_ptr<T[]> src_left_;
|
||||
scoped_ptr<T[]> src_right_;
|
||||
scoped_ptr<T[]> dst_left_;
|
||||
scoped_ptr<T[]> dst_right_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -18,22 +18,21 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
PushResampler::PushResampler()
|
||||
template <typename T>
|
||||
PushResampler<T>::PushResampler()
|
||||
: src_sample_rate_hz_(0),
|
||||
dst_sample_rate_hz_(0),
|
||||
num_channels_(0),
|
||||
src_left_(NULL),
|
||||
src_right_(NULL),
|
||||
dst_left_(NULL),
|
||||
dst_right_(NULL) {
|
||||
num_channels_(0) {
|
||||
}
|
||||
|
||||
PushResampler::~PushResampler() {
|
||||
template <typename T>
|
||||
PushResampler<T>::~PushResampler() {
|
||||
}
|
||||
|
||||
int PushResampler::InitializeIfNeeded(int src_sample_rate_hz,
|
||||
int dst_sample_rate_hz,
|
||||
int num_channels) {
|
||||
template <typename T>
|
||||
int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz,
|
||||
int dst_sample_rate_hz,
|
||||
int num_channels) {
|
||||
if (src_sample_rate_hz == src_sample_rate_hz_ &&
|
||||
dst_sample_rate_hz == dst_sample_rate_hz_ &&
|
||||
num_channels == num_channels_)
|
||||
@ -53,10 +52,10 @@ int PushResampler::InitializeIfNeeded(int src_sample_rate_hz,
|
||||
sinc_resampler_.reset(new PushSincResampler(src_size_10ms_mono,
|
||||
dst_size_10ms_mono));
|
||||
if (num_channels_ == 2) {
|
||||
src_left_.reset(new int16_t[src_size_10ms_mono]);
|
||||
src_right_.reset(new int16_t[src_size_10ms_mono]);
|
||||
dst_left_.reset(new int16_t[dst_size_10ms_mono]);
|
||||
dst_right_.reset(new int16_t[dst_size_10ms_mono]);
|
||||
src_left_.reset(new T[src_size_10ms_mono]);
|
||||
src_right_.reset(new T[src_size_10ms_mono]);
|
||||
dst_left_.reset(new T[dst_size_10ms_mono]);
|
||||
dst_right_.reset(new T[dst_size_10ms_mono]);
|
||||
sinc_resampler_right_.reset(new PushSincResampler(src_size_10ms_mono,
|
||||
dst_size_10ms_mono));
|
||||
}
|
||||
@ -64,8 +63,9 @@ int PushResampler::InitializeIfNeeded(int src_sample_rate_hz,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PushResampler::Resample(const int16_t* src, int src_length,
|
||||
int16_t* dst, int dst_capacity) {
|
||||
template <typename T>
|
||||
int PushResampler<T>::Resample(const T* src, int src_length, T* dst,
|
||||
int dst_capacity) {
|
||||
const int src_size_10ms = src_sample_rate_hz_ * num_channels_ / 100;
|
||||
const int dst_size_10ms = dst_sample_rate_hz_ * num_channels_ / 100;
|
||||
if (src_length != src_size_10ms || dst_capacity < dst_size_10ms)
|
||||
@ -74,13 +74,13 @@ int PushResampler::Resample(const int16_t* src, int src_length,
|
||||
if (src_sample_rate_hz_ == dst_sample_rate_hz_) {
|
||||
// The old resampler provides this memcpy facility in the case of matching
|
||||
// sample rates, so reproduce it here for the sinc resampler.
|
||||
memcpy(dst, src, src_length * sizeof(int16_t));
|
||||
memcpy(dst, src, src_length * sizeof(T));
|
||||
return src_length;
|
||||
}
|
||||
if (num_channels_ == 2) {
|
||||
const int src_length_mono = src_length / num_channels_;
|
||||
const int dst_capacity_mono = dst_capacity / num_channels_;
|
||||
int16_t* deinterleaved[] = {src_left_.get(), src_right_.get()};
|
||||
T* deinterleaved[] = {src_left_.get(), src_right_.get()};
|
||||
Deinterleave(src, src_length_mono, num_channels_, deinterleaved);
|
||||
|
||||
int dst_length_mono =
|
||||
@ -98,4 +98,8 @@ int PushResampler::Resample(const int16_t* src, int src_length,
|
||||
}
|
||||
}
|
||||
|
||||
// Explictly generate required instantiations.
|
||||
template class PushResampler<int16_t>;
|
||||
template class PushResampler<float>;
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
TEST(PushResamplerTest, VerifiesInputParameters) {
|
||||
PushResampler resampler;
|
||||
PushResampler<int16_t> resampler;
|
||||
EXPECT_EQ(-1, resampler.InitializeIfNeeded(-1, 16000, 1));
|
||||
EXPECT_EQ(-1, resampler.InitializeIfNeeded(16000, -1, 1));
|
||||
EXPECT_EQ(-1, resampler.InitializeIfNeeded(16000, 16000, 0));
|
||||
|
@ -44,6 +44,9 @@ class PushSincResampler : public SincResamplerCallback {
|
||||
virtual void Run(int frames, float* destination) OVERRIDE;
|
||||
|
||||
SincResampler* get_resampler_for_testing() { return resampler_.get(); }
|
||||
static float AlgorithmicDelaySeconds(int source_rate_hz) {
|
||||
return 1.f / source_rate_hz * SincResampler::kKernelSize / 2;
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_ptr<SincResampler> resampler_;
|
||||
|
@ -29,7 +29,7 @@ class ACMResampler {
|
||||
int16_t* out_audio);
|
||||
|
||||
private:
|
||||
PushResampler resampler_;
|
||||
PushResampler<int16_t> resampler_;
|
||||
};
|
||||
|
||||
} // namespace acm2
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace acm1 {
|
||||
|
||||
class ACMResampler {
|
||||
@ -30,11 +29,10 @@ class ACMResampler {
|
||||
uint8_t num_audio_channels);
|
||||
|
||||
private:
|
||||
PushResampler resampler_;
|
||||
PushResampler<int16_t> resampler_;
|
||||
};
|
||||
|
||||
} // namespace acm1
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RESAMPLER_H_
|
||||
|
@ -519,8 +519,8 @@ private:
|
||||
bool _externalTransport;
|
||||
AudioFrame _audioFrame;
|
||||
scoped_ptr<int16_t[]> mono_recording_audio_;
|
||||
// Resampler is used when input data is stereo while codec is mono.
|
||||
PushResampler input_resampler_;
|
||||
// Downsamples to the codec rate if necessary.
|
||||
PushResampler<int16_t> input_resampler_;
|
||||
uint8_t _audioLevel_dBov;
|
||||
FilePlayer* _inputFilePlayerPtr;
|
||||
FilePlayer* _outputFilePlayerPtr;
|
||||
|
@ -133,8 +133,10 @@ private:
|
||||
CriticalSectionWrapper& _fileCritSect;
|
||||
AudioConferenceMixer& _mixerModule;
|
||||
AudioFrame _audioFrame;
|
||||
PushResampler resampler_; // converts mixed audio to fit ADM format
|
||||
PushResampler audioproc_resampler_; // converts mixed audio to fit APM rate
|
||||
// Converts mixed audio to the audio device output rate.
|
||||
PushResampler<int16_t> resampler_;
|
||||
// Converts mixed audio to the audio processing rate.
|
||||
PushResampler<int16_t> audioproc_resampler_;
|
||||
AudioLevel _audioLevel; // measures audio level for the combined signal
|
||||
DtmfInband _dtmfGenerator;
|
||||
int _instanceId;
|
||||
|
@ -200,7 +200,7 @@ private:
|
||||
// owns
|
||||
MonitorModule _monitorModule;
|
||||
AudioFrame _audioFrame;
|
||||
PushResampler resampler_; // ADM sample rate -> mixing rate
|
||||
PushResampler<int16_t> resampler_; // ADM sample rate -> mixing rate
|
||||
FilePlayer* _filePlayerPtr;
|
||||
FileRecorder* _fileRecorderPtr;
|
||||
FileRecorder* _fileCallRecorderPtr;
|
||||
|
@ -25,7 +25,7 @@ namespace voe {
|
||||
// ConvertToCodecFormat, but if we're to consolidate we should probably make a
|
||||
// real converter class.
|
||||
void RemixAndResample(const AudioFrame& src_frame,
|
||||
PushResampler* resampler,
|
||||
PushResampler<int16_t>* resampler,
|
||||
AudioFrame* dst_frame) {
|
||||
const int16_t* audio_ptr = src_frame.data_;
|
||||
int audio_ptr_num_channels = src_frame.num_channels_;
|
||||
@ -76,7 +76,7 @@ void DownConvertToCodecFormat(const int16_t* src_data,
|
||||
int codec_num_channels,
|
||||
int codec_rate_hz,
|
||||
int16_t* mono_buffer,
|
||||
PushResampler* resampler,
|
||||
PushResampler<int16_t>* resampler,
|
||||
AudioFrame* dst_af) {
|
||||
assert(samples_per_channel <= kMaxMonoDataSizeSamples);
|
||||
assert(num_channels == 1 || num_channels == 2);
|
||||
|
@ -15,12 +15,12 @@
|
||||
#ifndef WEBRTC_VOICE_ENGINE_UTILITY_H_
|
||||
#define WEBRTC_VOICE_ENGINE_UTILITY_H_
|
||||
|
||||
#include "webrtc/common_audio/resampler/include/push_resampler.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioFrame;
|
||||
class PushResampler;
|
||||
|
||||
namespace voe {
|
||||
|
||||
@ -30,7 +30,7 @@ namespace voe {
|
||||
//
|
||||
// On failure, returns -1 and copies |src_frame| to |dst_frame|.
|
||||
void RemixAndResample(const AudioFrame& src_frame,
|
||||
PushResampler* resampler,
|
||||
PushResampler<int16_t>* resampler,
|
||||
AudioFrame* dst_frame);
|
||||
|
||||
// Downmix and downsample the audio in |src_data| to |dst_af| as necessary,
|
||||
@ -44,7 +44,7 @@ void DownConvertToCodecFormat(const int16_t* src_data,
|
||||
int codec_num_channels,
|
||||
int codec_rate_hz,
|
||||
int16_t* mono_buffer,
|
||||
PushResampler* resampler,
|
||||
PushResampler<int16_t>* resampler,
|
||||
AudioFrame* dst_af);
|
||||
|
||||
void MixWithSat(int16_t target[],
|
||||
|
@ -39,7 +39,7 @@ class UtilityTest : public ::testing::Test {
|
||||
int dst_channels, int dst_sample_rate_hz,
|
||||
FunctionToTest function);
|
||||
|
||||
PushResampler resampler_;
|
||||
PushResampler<int16_t> resampler_;
|
||||
AudioFrame src_frame_;
|
||||
AudioFrame dst_frame_;
|
||||
AudioFrame golden_frame_;
|
||||
@ -127,11 +127,11 @@ void VerifyFramesAreEqual(const AudioFrame& ref_frame,
|
||||
}
|
||||
|
||||
void UtilityTest::RunResampleTest(int src_channels,
|
||||
int src_sample_rate_hz,
|
||||
int dst_channels,
|
||||
int dst_sample_rate_hz,
|
||||
FunctionToTest function) {
|
||||
PushResampler resampler; // Create a new one with every test.
|
||||
int src_sample_rate_hz,
|
||||
int dst_channels,
|
||||
int dst_sample_rate_hz,
|
||||
FunctionToTest function) {
|
||||
PushResampler<int16_t> resampler; // Create a new one with every test.
|
||||
const int16_t kSrcLeft = 30; // Shouldn't overflow for any used sample rate.
|
||||
const int16_t kSrcRight = 15;
|
||||
const float resampling_factor = (1.0 * src_sample_rate_hz) /
|
||||
|
Loading…
Reference in New Issue
Block a user