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:
andrew@webrtc.org
2014-04-19 00:32:07 +00:00
parent 3d9ec1fed4
commit f5a33f145b
12 changed files with 52 additions and 48 deletions

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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_;