diff --git a/webrtc/common_audio/audio_converter.cc b/webrtc/common_audio/audio_converter.cc index f085ff13d1..2549393a43 100644 --- a/webrtc/common_audio/audio_converter.cc +++ b/webrtc/common_audio/audio_converter.cc @@ -89,7 +89,7 @@ void AudioConverter::Convert(const float* const* src, if (src_frames != dst_frames) { // Downmix to a buffer for subsequent resampling. DCHECK_EQ(downmix_buffer_->num_channels(), dst_channels); - DCHECK_EQ(downmix_buffer_->samples_per_channel(), src_frames); + DCHECK_EQ(downmix_buffer_->num_frames(), src_frames); dst_ptr = downmix_buffer_->channels(); } diff --git a/webrtc/common_audio/audio_converter_unittest.cc b/webrtc/common_audio/audio_converter_unittest.cc index 435f928bea..205bd984ce 100644 --- a/webrtc/common_audio/audio_converter_unittest.cc +++ b/webrtc/common_audio/audio_converter_unittest.cc @@ -28,14 +28,14 @@ ScopedBuffer CreateBuffer(const std::vector& data, int frames) { ScopedBuffer sb(new ChannelBuffer(frames, num_channels)); for (int i = 0; i < num_channels; ++i) for (int j = 0; j < frames; ++j) - sb->channel(i)[j] = data[i] * j; + sb->channels()[i][j] = data[i] * j; return sb; } void VerifyParams(const ChannelBuffer& ref, const ChannelBuffer& test) { EXPECT_EQ(ref.num_channels(), test.num_channels()); - EXPECT_EQ(ref.samples_per_channel(), test.samples_per_channel()); + EXPECT_EQ(ref.num_frames(), test.num_frames()); } // Computes the best SNR based on the error between |ref_frame| and @@ -50,20 +50,20 @@ float ComputeSNR(const ChannelBuffer& ref, // Search within one sample of the expected delay. for (int delay = std::max(expected_delay - 1, 0); - delay <= std::min(expected_delay + 1, ref.samples_per_channel()); + delay <= std::min(expected_delay + 1, ref.num_frames()); ++delay) { float mse = 0; float variance = 0; float mean = 0; for (int i = 0; i < ref.num_channels(); ++i) { - for (int j = 0; j < ref.samples_per_channel() - delay; ++j) { - float error = ref.channel(i)[j] - test.channel(i)[j + delay]; + for (int j = 0; j < ref.num_frames() - delay; ++j) { + float error = ref.channels()[i][j] - test.channels()[i][j + delay]; mse += error * error; - variance += ref.channel(i)[j] * ref.channel(i)[j]; - mean += ref.channel(i)[j]; + variance += ref.channels()[i][j] * ref.channels()[i][j]; + mean += ref.channels()[i][j]; } } - const int length = ref.num_channels() * (ref.samples_per_channel() - delay); + const int length = ref.num_channels() * (ref.num_frames() - delay); mse /= length; variance /= length; mean /= length; diff --git a/webrtc/common_audio/audio_ring_buffer_unittest.cc b/webrtc/common_audio/audio_ring_buffer_unittest.cc index 582d981c05..2d7d2c7b9a 100644 --- a/webrtc/common_audio/audio_ring_buffer_unittest.cc +++ b/webrtc/common_audio/audio_ring_buffer_unittest.cc @@ -25,7 +25,7 @@ void ReadAndWriteTest(const ChannelBuffer& input, size_t buffer_frames, ChannelBuffer* output) { const size_t num_channels = input.num_channels(); - const size_t total_frames = input.samples_per_channel(); + const size_t total_frames = input.num_frames(); AudioRingBuffer buf(num_channels, buffer_frames); scoped_ptr slice(new float*[num_channels]); @@ -91,17 +91,18 @@ TEST_F(AudioRingBufferTest, MoveReadPosition) { const size_t kNumChannels = 1; const float kInputArray[] = {1, 2, 3, 4}; const size_t kNumFrames = sizeof(kInputArray) / sizeof(*kInputArray); - ChannelBuffer input(kInputArray, kNumFrames, kNumChannels); + ChannelBuffer input(kNumFrames, kNumChannels); + input.SetDataForTesting(kInputArray, kNumFrames); AudioRingBuffer buf(kNumChannels, kNumFrames); buf.Write(input.channels(), kNumChannels, kNumFrames); buf.MoveReadPosition(3); ChannelBuffer output(1, kNumChannels); buf.Read(output.channels(), kNumChannels, 1); - EXPECT_EQ(4, output.data()[0]); + EXPECT_EQ(4, output.channels()[0][0]); buf.MoveReadPosition(-3); buf.Read(output.channels(), kNumChannels, 1); - EXPECT_EQ(2, output.data()[0]); + EXPECT_EQ(2, output.channels()[0][0]); } } // namespace webrtc diff --git a/webrtc/common_audio/blocker_unittest.cc b/webrtc/common_audio/blocker_unittest.cc index d1bfa6981f..bff447f5c8 100644 --- a/webrtc/common_audio/blocker_unittest.cc +++ b/webrtc/common_audio/blocker_unittest.cc @@ -132,13 +132,15 @@ TEST_F(BlockerTest, TestBlockerMutuallyPrimeChunkandBlockSize) { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 3, 3, 3, 3, 3, 3, 3}}; - const ChannelBuffer input_cb(kInput[0], kNumFrames, kNumInputChannels); + ChannelBuffer input_cb(kNumFrames, kNumInputChannels); + input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput)); const float kExpectedOutput[kNumInputChannels][kNumFrames] = { {6, 6, 12, 20, 20, 20, 20, 20, 20, 20}, {6, 6, 12, 28, 28, 28, 28, 28, 28, 28}}; - const ChannelBuffer expected_output_cb( - kExpectedOutput[0], kNumFrames, kNumInputChannels); + ChannelBuffer expected_output_cb(kNumFrames, kNumInputChannels); + expected_output_cb.SetDataForTesting( + kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput)); const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f}; @@ -183,13 +185,15 @@ TEST_F(BlockerTest, TestBlockerMutuallyPrimeShiftAndBlockSize) { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}}; - const ChannelBuffer input_cb(kInput[0], kNumFrames, kNumInputChannels); + ChannelBuffer input_cb(kNumFrames, kNumInputChannels); + input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput)); const float kExpectedOutput[kNumOutputChannels][kNumFrames] = { {6, 10, 10, 20, 10, 10, 20, 10, 10, 20, 10, 10}, {6, 14, 14, 28, 14, 14, 28, 14, 14, 28, 14, 14}}; - const ChannelBuffer expected_output_cb( - kExpectedOutput[0], kNumFrames, kNumOutputChannels); + ChannelBuffer expected_output_cb(kNumFrames, kNumOutputChannels); + expected_output_cb.SetDataForTesting( + kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput)); const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f}; @@ -234,13 +238,15 @@ TEST_F(BlockerTest, TestBlockerNoOverlap) { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}}; - const ChannelBuffer input_cb(kInput[0], kNumFrames, kNumInputChannels); + ChannelBuffer input_cb(kNumFrames, kNumInputChannels); + input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput)); const float kExpectedOutput[kNumOutputChannels][kNumFrames] = { {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}}; - const ChannelBuffer expected_output_cb( - kExpectedOutput[0], kNumFrames, kNumOutputChannels); + ChannelBuffer expected_output_cb(kNumFrames, kNumOutputChannels); + expected_output_cb.SetDataForTesting( + kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput)); const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f}; @@ -292,7 +298,8 @@ TEST_F(BlockerTest, InitialDelaysAreMinimum) { input[i][j] = i + 1; } } - const ChannelBuffer input_cb(input[0], kNumFrames, kNumInputChannels); + ChannelBuffer input_cb(kNumFrames, kNumInputChannels); + input_cb.SetDataForTesting(input[0], sizeof(input) / sizeof(**input)); ChannelBuffer output_cb(kNumFrames, kNumOutputChannels); diff --git a/webrtc/common_audio/channel_buffer.cc b/webrtc/common_audio/channel_buffer.cc index 9c07550170..14aaa7af09 100644 --- a/webrtc/common_audio/channel_buffer.cc +++ b/webrtc/common_audio/channel_buffer.cc @@ -12,11 +12,13 @@ namespace webrtc { -IFChannelBuffer::IFChannelBuffer(int samples_per_channel, int num_channels) +IFChannelBuffer::IFChannelBuffer(int num_frames, + int num_channels, + int num_bands) : ivalid_(true), - ibuf_(samples_per_channel, num_channels), + ibuf_(num_frames, num_channels, num_bands), fvalid_(true), - fbuf_(samples_per_channel, num_channels) {} + fbuf_(num_frames, num_channels, num_bands) {} ChannelBuffer* IFChannelBuffer::ibuf() { RefreshI(); @@ -43,11 +45,13 @@ const ChannelBuffer* IFChannelBuffer::fbuf_const() const { void IFChannelBuffer::RefreshF() const { if (!fvalid_) { assert(ivalid_); - const int16_t* const int_data = ibuf_.data(); - float* const float_data = fbuf_.data(); - const int length = fbuf_.length(); - for (int i = 0; i < length; ++i) - float_data[i] = int_data[i]; + const int16_t* const* int_channels = ibuf_.channels(); + float* const* float_channels = fbuf_.channels(); + for (int i = 0; i < ibuf_.num_channels(); ++i) { + for (int j = 0; j < ibuf_.num_frames(); ++j) { + float_channels[i][j] = int_channels[i][j]; + } + } fvalid_ = true; } } @@ -55,7 +59,13 @@ void IFChannelBuffer::RefreshF() const { void IFChannelBuffer::RefreshI() const { if (!ivalid_) { assert(fvalid_); - FloatS16ToS16(fbuf_.data(), ibuf_.length(), ibuf_.data()); + int16_t* const* int_channels = ibuf_.channels(); + const float* const* float_channels = fbuf_.channels(); + for (int i = 0; i < ibuf_.num_channels(); ++i) { + FloatS16ToS16(float_channels[i], + ibuf_.num_frames(), + int_channels[i]); + } ivalid_ = true; } } diff --git a/webrtc/common_audio/channel_buffer.h b/webrtc/common_audio/channel_buffer.h index 31ebaa2d57..a5c4870d35 100644 --- a/webrtc/common_audio/channel_buffer.h +++ b/webrtc/common_audio/channel_buffer.h @@ -15,70 +15,96 @@ #include "webrtc/base/checks.h" #include "webrtc/common_audio/include/audio_util.h" +#include "webrtc/test/testsupport/gtest_prod_util.h" namespace webrtc { -// Helper to encapsulate a contiguous data buffer with access to a pointer -// array of the deinterleaved channels. The buffer is zero initialized at -// creation. +// Helper to encapsulate a contiguous data buffer, full or split into frequency +// bands, with access to a pointer arrays of the deinterleaved channels and +// bands. The buffer is zero initialized at creation. +// +// The buffer structure is showed below for a 2 channel and 2 bands case: +// +// |data_|: +// { [ --- b1ch1 --- ] [ --- b2ch1 --- ] [ --- b1ch2 --- ] [ --- b2ch2 --- ] } +// +// The pointer arrays for the same example are as follows: +// +// |channels_|: +// { [ b1ch1* ] [ b1ch2* ] [ b2ch1* ] [ b2ch2* ] } +// +// |bands_|: +// { [ b1ch1* ] [ b2ch1* ] [ b1ch2* ] [ b2ch2* ] } template class ChannelBuffer { public: - ChannelBuffer(int samples_per_channel, int num_channels) - : data_(new T[samples_per_channel * num_channels]), - channels_(new T*[num_channels]), - samples_per_channel_(samples_per_channel), - num_channels_(num_channels) { - Initialize(); + ChannelBuffer(int num_frames, + int num_channels, + int num_bands = 1) + : data_(new T[num_frames * num_channels]), + channels_(new T*[num_channels * num_bands]), + bands_(new T*[num_channels * num_bands]), + num_frames_(num_frames), + num_frames_per_band_(num_frames / num_bands), + num_channels_(num_channels), + num_bands_(num_bands) { + memset(data_.get(), 0, size() * sizeof(T)); + for (int i = 0; i < num_channels_; ++i) { + for (int j = 0; j < num_bands_; ++j) { + channels_[j * num_channels_ + i] = + &data_[i * num_frames_ + j * num_frames_per_band_]; + bands_[i * num_bands_ + j] = channels_[j * num_channels_ + i]; + } + } } - ChannelBuffer(const T* data, int samples_per_channel, int num_channels) - : data_(new T[samples_per_channel * num_channels]), - channels_(new T*[num_channels]), - samples_per_channel_(samples_per_channel), - num_channels_(num_channels) { - Initialize(); - memcpy(data_.get(), data, length() * sizeof(T)); + // Returns a pointer array to the full-band channels (or lower band channels). + // Usage: + // channels()[channel][sample]. + // Where: + // 0 <= channel < |num_channels_| + // 0 <= sample < |num_frames_| + T* const* channels() { return channels(0); } + const T* const* channels() const { return channels(0); } + + // Returns a pointer array to the channels for a specific band. + // Usage: + // channels(band)[channel][sample]. + // Where: + // 0 <= band < |num_bands_| + // 0 <= channel < |num_channels_| + // 0 <= sample < |num_frames_per_band_| + const T* const* channels(int band) const { + DCHECK_LT(band, num_bands_); + DCHECK_GE(band, 0); + return &channels_[band * num_channels_]; } - - ChannelBuffer(const T* const* channels, int samples_per_channel, - int num_channels) - : data_(new T[samples_per_channel * num_channels]), - channels_(new T*[num_channels]), - samples_per_channel_(samples_per_channel), - num_channels_(num_channels) { - Initialize(); - for (int i = 0; i < num_channels_; ++i) - CopyFrom(channels[i], i); - } - - ~ChannelBuffer() {} - - void CopyFrom(const void* channel_ptr, int i) { - DCHECK_LT(i, num_channels_); - memcpy(channels_[i], channel_ptr, samples_per_channel_ * sizeof(T)); - } - - T* data() { return data_.get(); } - const T* data() const { return data_.get(); } - - const T* channel(int i) const { - DCHECK_GE(i, 0); - DCHECK_LT(i, num_channels_); - return channels_[i]; - } - T* channel(int i) { + T* const* channels(int band) { const ChannelBuffer* t = this; - return const_cast(t->channel(i)); + return const_cast(t->channels(band)); } - T* const* channels() { return channels_.get(); } - const T* const* channels() const { return channels_.get(); } + // Returns a pointer array to the bands for a specific channel. + // Usage: + // bands(channel)[band][sample]. + // Where: + // 0 <= channel < |num_channels_| + // 0 <= band < |num_bands_| + // 0 <= sample < |num_frames_per_band_| + const T* const* bands(int channel) const { + DCHECK_LT(channel, num_channels_); + DCHECK_GE(channel, 0); + return &bands_[channel * num_bands_]; + } + T* const* bands(int channel) { + const ChannelBuffer* t = this; + return const_cast(t->bands(channel)); + } // Sets the |slice| pointers to the |start_frame| position for each channel. // Returns |slice| for convenience. const T* const* Slice(T** slice, int start_frame) const { - DCHECK_LT(start_frame, samples_per_channel_); + DCHECK_LT(start_frame, num_frames_); for (int i = 0; i < num_channels_; ++i) slice[i] = &channels_[i][start_frame]; return slice; @@ -88,21 +114,25 @@ class ChannelBuffer { return const_cast(t->Slice(slice, start_frame)); } - int samples_per_channel() const { return samples_per_channel_; } + int num_frames() const { return num_frames_; } + int num_frames_per_band() const { return num_frames_per_band_; } int num_channels() const { return num_channels_; } - int length() const { return samples_per_channel_ * num_channels_; } + int num_bands() const { return num_bands_; } + size_t size() const {return num_frames_ * num_channels_; } - private: - void Initialize() { - memset(data_.get(), 0, sizeof(T) * length()); - for (int i = 0; i < num_channels_; ++i) - channels_[i] = &data_[i * samples_per_channel_]; + void SetDataForTesting(const T* data, size_t size) { + CHECK_EQ(size, this->size()); + memcpy(data_.get(), data, size * sizeof(*data)); } + private: scoped_ptr data_; scoped_ptr channels_; - const int samples_per_channel_; + scoped_ptr bands_; + const int num_frames_; + const int num_frames_per_band_; const int num_channels_; + const int num_bands_; }; // One int16_t and one float ChannelBuffer that are kept in sync. The sync is @@ -113,15 +143,17 @@ class ChannelBuffer { // fbuf() until the next call to any of the other functions. class IFChannelBuffer { public: - IFChannelBuffer(int samples_per_channel, int num_channels); + IFChannelBuffer(int num_frames, int num_channels, int num_bands = 1); ChannelBuffer* ibuf(); ChannelBuffer* fbuf(); const ChannelBuffer* ibuf_const() const; const ChannelBuffer* fbuf_const() const; + int num_frames() const { return ibuf_.num_frames(); } + int num_frames_per_band() const { return ibuf_.num_frames_per_band(); } int num_channels() const { return ibuf_.num_channels(); } - int samples_per_channel() const { return ibuf_.samples_per_channel(); } + int num_bands() const { return ibuf_.num_bands(); } private: void RefreshF() const; diff --git a/webrtc/modules/audio_processing/audio_buffer.cc b/webrtc/modules/audio_processing/audio_buffer.cc index 7b302cff07..c4dff8a8d0 100644 --- a/webrtc/modules/audio_processing/audio_buffer.cc +++ b/webrtc/modules/audio_processing/audio_buffer.cc @@ -48,92 +48,90 @@ int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) { template void StereoToMono(const T* left, const T* right, T* out, - int samples_per_channel) { - for (int i = 0; i < samples_per_channel; ++i) + int num_frames) { + for (int i = 0; i < num_frames; ++i) out[i] = (left[i] + right[i]) / 2; } +int NumBandsFromSamplesPerChannel(int num_frames) { + int num_bands = 1; + if (num_frames == kSamplesPer32kHzChannel || + num_frames == kSamplesPer48kHzChannel) { + num_bands = rtc::CheckedDivExact(num_frames, + static_cast(kSamplesPer16kHzChannel)); + } + return num_bands; +} + } // namespace -AudioBuffer::AudioBuffer(int input_samples_per_channel, +AudioBuffer::AudioBuffer(int input_num_frames, int num_input_channels, - int process_samples_per_channel, + int process_num_frames, int num_process_channels, - int output_samples_per_channel) - : input_samples_per_channel_(input_samples_per_channel), + int output_num_frames) + : input_num_frames_(input_num_frames), num_input_channels_(num_input_channels), - proc_samples_per_channel_(process_samples_per_channel), + proc_num_frames_(process_num_frames), num_proc_channels_(num_process_channels), - output_samples_per_channel_(output_samples_per_channel), + output_num_frames_(output_num_frames), num_channels_(num_process_channels), - num_bands_(1), - samples_per_split_channel_(proc_samples_per_channel_), + num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)), + num_split_frames_(rtc::CheckedDivExact( + proc_num_frames_, num_bands_)), mixed_low_pass_valid_(false), reference_copied_(false), activity_(AudioFrame::kVadUnknown), keyboard_data_(NULL), - channels_(new IFChannelBuffer(proc_samples_per_channel_, - num_proc_channels_)) { - assert(input_samples_per_channel_ > 0); - assert(proc_samples_per_channel_ > 0); - assert(output_samples_per_channel_ > 0); + data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) { + assert(input_num_frames_ > 0); + assert(proc_num_frames_ > 0); + assert(output_num_frames_ > 0); assert(num_input_channels_ > 0 && num_input_channels_ <= 2); - assert(num_proc_channels_ <= num_input_channels_); + assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_); if (num_input_channels_ == 2 && num_proc_channels_ == 1) { - input_buffer_.reset(new ChannelBuffer(input_samples_per_channel_, + input_buffer_.reset(new ChannelBuffer(input_num_frames_, num_proc_channels_)); } - if (input_samples_per_channel_ != proc_samples_per_channel_ || - output_samples_per_channel_ != proc_samples_per_channel_) { + if (input_num_frames_ != proc_num_frames_ || + output_num_frames_ != proc_num_frames_) { // Create an intermediate buffer for resampling. - process_buffer_.reset(new ChannelBuffer(proc_samples_per_channel_, + process_buffer_.reset(new ChannelBuffer(proc_num_frames_, num_proc_channels_)); - } - if (input_samples_per_channel_ != proc_samples_per_channel_) { - input_resamplers_.reserve(num_proc_channels_); - for (int i = 0; i < num_proc_channels_; ++i) { - input_resamplers_.push_back( - new PushSincResampler(input_samples_per_channel_, - proc_samples_per_channel_)); + if (input_num_frames_ != proc_num_frames_) { + for (int i = 0; i < num_proc_channels_; ++i) { + input_resamplers_.push_back( + new PushSincResampler(input_num_frames_, + proc_num_frames_)); + } + } + + if (output_num_frames_ != proc_num_frames_) { + for (int i = 0; i < num_proc_channels_; ++i) { + output_resamplers_.push_back( + new PushSincResampler(proc_num_frames_, + output_num_frames_)); + } } } - if (output_samples_per_channel_ != proc_samples_per_channel_) { - output_resamplers_.reserve(num_proc_channels_); - for (int i = 0; i < num_proc_channels_; ++i) { - output_resamplers_.push_back( - new PushSincResampler(proc_samples_per_channel_, - output_samples_per_channel_)); - } - } - - if (proc_samples_per_channel_ == kSamplesPer32kHzChannel || - proc_samples_per_channel_ == kSamplesPer48kHzChannel) { - samples_per_split_channel_ = kSamplesPer16kHzChannel; - num_bands_ = proc_samples_per_channel_ / samples_per_split_channel_; - split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_, - num_proc_channels_)); - split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_, - num_proc_channels_)); + if (num_bands_ > 1) { + split_data_.reset(new IFChannelBuffer(proc_num_frames_, + num_proc_channels_, + num_bands_)); splitting_filter_.reset(new SplittingFilter(num_proc_channels_)); - if (proc_samples_per_channel_ == kSamplesPer48kHzChannel) { - split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_, - num_proc_channels_)); - } } - bands_.reset(new int16_t*[num_proc_channels_ * kMaxNumBands]); - bands_f_.reset(new float*[num_proc_channels_ * kMaxNumBands]); } AudioBuffer::~AudioBuffer() {} void AudioBuffer::CopyFrom(const float* const* data, - int samples_per_channel, + int num_frames, AudioProcessing::ChannelLayout layout) { - assert(samples_per_channel == input_samples_per_channel_); + assert(num_frames == input_num_frames_); assert(ChannelsFromLayout(layout) == num_input_channels_); InitForNewData(); @@ -146,53 +144,55 @@ void AudioBuffer::CopyFrom(const float* const* data, if (num_input_channels_ == 2 && num_proc_channels_ == 1) { StereoToMono(data[0], data[1], - input_buffer_->channel(0), - input_samples_per_channel_); + input_buffer_->channels()[0], + input_num_frames_); data_ptr = input_buffer_->channels(); } // Resample. - if (input_samples_per_channel_ != proc_samples_per_channel_) { + if (input_num_frames_ != proc_num_frames_) { for (int i = 0; i < num_proc_channels_; ++i) { input_resamplers_[i]->Resample(data_ptr[i], - input_samples_per_channel_, - process_buffer_->channel(i), - proc_samples_per_channel_); + input_num_frames_, + process_buffer_->channels()[i], + proc_num_frames_); } data_ptr = process_buffer_->channels(); } // Convert to the S16 range. for (int i = 0; i < num_proc_channels_; ++i) { - FloatToFloatS16(data_ptr[i], proc_samples_per_channel_, - channels_->fbuf()->channel(i)); + FloatToFloatS16(data_ptr[i], + proc_num_frames_, + data_->fbuf()->channels()[i]); } } -void AudioBuffer::CopyTo(int samples_per_channel, +void AudioBuffer::CopyTo(int num_frames, AudioProcessing::ChannelLayout layout, float* const* data) { - assert(samples_per_channel == output_samples_per_channel_); + assert(num_frames == output_num_frames_); assert(ChannelsFromLayout(layout) == num_channels_); // Convert to the float range. float* const* data_ptr = data; - if (output_samples_per_channel_ != proc_samples_per_channel_) { + if (output_num_frames_ != proc_num_frames_) { // Convert to an intermediate buffer for subsequent resampling. data_ptr = process_buffer_->channels(); } for (int i = 0; i < num_channels_; ++i) { - FloatS16ToFloat(channels_->fbuf()->channel(i), proc_samples_per_channel_, + FloatS16ToFloat(data_->fbuf()->channels()[i], + proc_num_frames_, data_ptr[i]); } // Resample. - if (output_samples_per_channel_ != proc_samples_per_channel_) { + if (output_num_frames_ != proc_num_frames_) { for (int i = 0; i < num_channels_; ++i) { output_resamplers_[i]->Resample(data_ptr[i], - proc_samples_per_channel_, + proc_num_frames_, data[i], - output_samples_per_channel_); + output_num_frames_); } } } @@ -205,119 +205,81 @@ void AudioBuffer::InitForNewData() { num_channels_ = num_proc_channels_; } -const int16_t* AudioBuffer::data_const(int channel) const { - return channels_const()[channel]; -} - -int16_t* AudioBuffer::data(int channel) { - return channels()[channel]; -} - const int16_t* const* AudioBuffer::channels_const() const { - return channels_->ibuf_const()->channels(); + return data_->ibuf_const()->channels(); } int16_t* const* AudioBuffer::channels() { mixed_low_pass_valid_ = false; - return channels_->ibuf()->channels(); + return data_->ibuf()->channels(); } const int16_t* const* AudioBuffer::split_bands_const(int channel) const { - // This is necessary to make sure that the int16_t data is up to date in the - // IFChannelBuffer. - // TODO(aluebs): Having to depend on this to get the updated data is bug - // prone. One solution is to have ChannelBuffer track the bands as well. - for (int i = 0; i < kMaxNumBands; ++i) { - int16_t* const* channels = - const_cast(split_channels_const(static_cast(i))); - bands_[kMaxNumBands * channel + i] = channels ? channels[channel] : NULL; - } - return &bands_[kMaxNumBands * channel]; + return split_data_.get() ? + split_data_->ibuf_const()->bands(channel) : + data_->ibuf_const()->bands(channel); } int16_t* const* AudioBuffer::split_bands(int channel) { mixed_low_pass_valid_ = false; - // This is necessary to make sure that the int16_t data is up to date and the - // float data is marked as invalid in the IFChannelBuffer. - for (int i = 0; i < kMaxNumBands; ++i) { - int16_t* const* channels = split_channels(static_cast(i)); - bands_[kMaxNumBands * channel + i] = channels ? channels[channel] : NULL; - } - return &bands_[kMaxNumBands * channel]; + return split_data_.get() ? + split_data_->ibuf()->bands(channel) : + data_->ibuf()->bands(channel); } const int16_t* const* AudioBuffer::split_channels_const(Band band) const { - if (split_channels_.size() > static_cast(band)) { - return split_channels_[band]->ibuf_const()->channels(); + if (split_data_.get()) { + return split_data_->ibuf_const()->channels(band); } else { - return band == kBand0To8kHz ? channels_->ibuf_const()->channels() : NULL; + return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr; } } int16_t* const* AudioBuffer::split_channels(Band band) { mixed_low_pass_valid_ = false; - if (split_channels_.size() > static_cast(band)) { - return split_channels_[band]->ibuf()->channels(); + if (split_data_.get()) { + return split_data_->ibuf()->channels(band); } else { - return band == kBand0To8kHz ? channels_->ibuf()->channels() : NULL; + return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr; } } -const float* AudioBuffer::data_const_f(int channel) const { - return channels_const_f()[channel]; -} - -float* AudioBuffer::data_f(int channel) { - return channels_f()[channel]; -} - const float* const* AudioBuffer::channels_const_f() const { - return channels_->fbuf_const()->channels(); + return data_->fbuf_const()->channels(); } float* const* AudioBuffer::channels_f() { mixed_low_pass_valid_ = false; - return channels_->fbuf()->channels(); + return data_->fbuf()->channels(); } const float* const* AudioBuffer::split_bands_const_f(int channel) const { - // This is necessary to make sure that the float data is up to date in the - // IFChannelBuffer. - for (int i = 0; i < kMaxNumBands; ++i) { - float* const* channels = - const_cast(split_channels_const_f(static_cast(i))); - bands_f_[kMaxNumBands * channel + i] = channels ? channels[channel] : NULL; - - } - return &bands_f_[kMaxNumBands * channel]; + return split_data_.get() ? + split_data_->fbuf_const()->bands(channel) : + data_->fbuf_const()->bands(channel); } float* const* AudioBuffer::split_bands_f(int channel) { mixed_low_pass_valid_ = false; - // This is necessary to make sure that the float data is up to date and the - // int16_t data is marked as invalid in the IFChannelBuffer. - for (int i = 0; i < kMaxNumBands; ++i) { - float* const* channels = split_channels_f(static_cast(i)); - bands_f_[kMaxNumBands * channel + i] = channels ? channels[channel] : NULL; - - } - return &bands_f_[kMaxNumBands * channel]; + return split_data_.get() ? + split_data_->fbuf()->bands(channel) : + data_->fbuf()->bands(channel); } const float* const* AudioBuffer::split_channels_const_f(Band band) const { - if (split_channels_.size() > static_cast(band)) { - return split_channels_[band]->fbuf_const()->channels(); + if (split_data_.get()) { + return split_data_->fbuf_const()->channels(band); } else { - return band == kBand0To8kHz ? channels_->fbuf_const()->channels() : NULL; + return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr; } } float* const* AudioBuffer::split_channels_f(Band band) { mixed_low_pass_valid_ = false; - if (split_channels_.size() > static_cast(band)) { - return split_channels_[band]->fbuf()->channels(); + if (split_data_.get()) { + return split_data_->fbuf()->channels(band); } else { - return band == kBand0To8kHz ? channels_->fbuf()->channels() : NULL; + return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr; } } @@ -332,15 +294,15 @@ const int16_t* AudioBuffer::mixed_low_pass_data() { if (!mixed_low_pass_valid_) { if (!mixed_low_pass_channels_.get()) { mixed_low_pass_channels_.reset( - new ChannelBuffer(samples_per_split_channel_, 1)); + new ChannelBuffer(num_split_frames_, 1)); } StereoToMono(split_bands_const(0)[kBand0To8kHz], split_bands_const(1)[kBand0To8kHz], - mixed_low_pass_channels_->data(), - samples_per_split_channel_); + mixed_low_pass_channels_->channels()[0], + num_split_frames_); mixed_low_pass_valid_ = true; } - return mixed_low_pass_channels_->data(); + return mixed_low_pass_channels_->channels()[0]; } const int16_t* AudioBuffer::low_pass_reference(int channel) const { @@ -348,7 +310,7 @@ const int16_t* AudioBuffer::low_pass_reference(int channel) const { return NULL; } - return low_pass_reference_channels_->channel(channel); + return low_pass_reference_channels_->channels()[channel]; } const float* AudioBuffer::keyboard_data() const { @@ -371,17 +333,17 @@ void AudioBuffer::set_num_channels(int num_channels) { num_channels_ = num_channels; } -int AudioBuffer::samples_per_channel() const { - return proc_samples_per_channel_; +int AudioBuffer::num_frames() const { + return proc_num_frames_; } -int AudioBuffer::samples_per_split_channel() const { - return samples_per_split_channel_; +int AudioBuffer::num_frames_per_band() const { + return num_split_frames_; } -int AudioBuffer::samples_per_keyboard_channel() const { +int AudioBuffer::num_keyboard_frames() const { // We don't resample the keyboard channel. - return input_samples_per_channel_; + return input_num_frames_; } int AudioBuffer::num_bands() const { @@ -390,25 +352,25 @@ int AudioBuffer::num_bands() const { // TODO(andrew): Do deinterleaving and mixing in one step? void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) { - assert(proc_samples_per_channel_ == input_samples_per_channel_); + assert(proc_num_frames_ == input_num_frames_); assert(frame->num_channels_ == num_input_channels_); - assert(frame->samples_per_channel_ == proc_samples_per_channel_); + assert(frame->samples_per_channel_ == proc_num_frames_); InitForNewData(); activity_ = frame->vad_activity_; if (num_input_channels_ == 2 && num_proc_channels_ == 1) { // Downmix directly; no explicit deinterleaving needed. - int16_t* downmixed = channels_->ibuf()->channel(0); - for (int i = 0; i < input_samples_per_channel_; ++i) { + int16_t* downmixed = data_->ibuf()->channels()[0]; + for (int i = 0; i < input_num_frames_; ++i) { downmixed[i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2; } } else { assert(num_proc_channels_ == num_input_channels_); int16_t* interleaved = frame->data_; for (int i = 0; i < num_proc_channels_; ++i) { - int16_t* deinterleaved = channels_->ibuf()->channel(i); + int16_t* deinterleaved = data_->ibuf()->channels()[i]; int interleaved_idx = i; - for (int j = 0; j < proc_samples_per_channel_; ++j) { + for (int j = 0; j < proc_num_frames_; ++j) { deinterleaved[j] = interleaved[interleaved_idx]; interleaved_idx += num_proc_channels_; } @@ -417,10 +379,10 @@ void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) { } void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const { - assert(proc_samples_per_channel_ == output_samples_per_channel_); + assert(proc_num_frames_ == output_num_frames_); assert(num_channels_ == num_input_channels_); assert(frame->num_channels_ == num_channels_); - assert(frame->samples_per_channel_ == proc_samples_per_channel_); + assert(frame->samples_per_channel_ == proc_num_frames_); frame->vad_activity_ = activity_; if (!data_changed) { @@ -429,9 +391,9 @@ void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const { int16_t* interleaved = frame->data_; for (int i = 0; i < num_channels_; i++) { - int16_t* deinterleaved = channels_->ibuf()->channel(i); + int16_t* deinterleaved = data_->ibuf()->channels()[i]; int interleaved_idx = i; - for (int j = 0; j < proc_samples_per_channel_; j++) { + for (int j = 0; j < proc_num_frames_; j++) { interleaved[interleaved_idx] = deinterleaved[j]; interleaved_idx += num_channels_; } @@ -443,23 +405,23 @@ void AudioBuffer::CopyLowPassToReference() { if (!low_pass_reference_channels_.get() || low_pass_reference_channels_->num_channels() != num_channels_) { low_pass_reference_channels_.reset( - new ChannelBuffer(samples_per_split_channel_, + new ChannelBuffer(num_split_frames_, num_proc_channels_)); } for (int i = 0; i < num_proc_channels_; i++) { - low_pass_reference_channels_->CopyFrom(split_bands_const(i)[kBand0To8kHz], - i); + memcpy(low_pass_reference_channels_->channels()[i], + split_bands_const(i)[kBand0To8kHz], + low_pass_reference_channels_->num_frames_per_band() * + sizeof(split_bands_const(i)[kBand0To8kHz][0])); } } void AudioBuffer::SplitIntoFrequencyBands() { - splitting_filter_->Analysis(channels_.get(), - split_channels_.get()); + splitting_filter_->Analysis(data_.get(), split_data_.get()); } void AudioBuffer::MergeFrequencyBands() { - splitting_filter_->Synthesis(split_channels_.get(), - channels_.get()); + splitting_filter_->Synthesis(split_data_.get(), data_.get()); } } // namespace webrtc diff --git a/webrtc/modules/audio_processing/audio_buffer.h b/webrtc/modules/audio_processing/audio_buffer.h index da4f7e8f29..a7f7e892f9 100644 --- a/webrtc/modules/audio_processing/audio_buffer.h +++ b/webrtc/modules/audio_processing/audio_buffer.h @@ -27,7 +27,6 @@ namespace webrtc { class PushSincResampler; class IFChannelBuffer; -static const int kMaxNumBands = 3; enum Band { kBand0To8kHz = 0, kBand8To16kHz = 1, @@ -37,25 +36,23 @@ enum Band { class AudioBuffer { public: // TODO(ajm): Switch to take ChannelLayouts. - AudioBuffer(int input_samples_per_channel, + AudioBuffer(int input_num_frames, int num_input_channels, - int process_samples_per_channel, + int process_num_frames, int num_process_channels, - int output_samples_per_channel); + int output_num_frames); virtual ~AudioBuffer(); int num_channels() const; void set_num_channels(int num_channels); - int samples_per_channel() const; - int samples_per_split_channel() const; - int samples_per_keyboard_channel() const; + int num_frames() const; + int num_frames_per_band() const; + int num_keyboard_frames() const; int num_bands() const; // Sample array accessors. Channels are guaranteed to be stored contiguously // in memory. Prefer to use the const variants of each accessor when // possible, since they incur less float<->int16 conversion overhead. - int16_t* data(int channel); - const int16_t* data_const(int channel) const; int16_t* const* channels(); const int16_t* const* channels_const() const; int16_t* const* split_bands(int channel); @@ -70,8 +67,6 @@ class AudioBuffer { // Float versions of the accessors, with automatic conversion back and forth // as necessary. The range of the numbers are the same as for int16_t. - float* data_f(int channel); - const float* data_const_f(int channel) const; float* const* channels_f(); const float* const* channels_const_f() const; float* const* split_bands_f(int channel); @@ -92,9 +87,9 @@ class AudioBuffer { // Use for float deinterleaved data. void CopyFrom(const float* const* data, - int samples_per_channel, + int num_frames, AudioProcessing::ChannelLayout layout); - void CopyTo(int samples_per_channel, + void CopyTo(int num_frames, AudioProcessing::ChannelLayout layout, float* const* data); void CopyLowPassToReference(); @@ -110,29 +105,27 @@ class AudioBuffer { // The audio is passed into DeinterleaveFrom() or CopyFrom() with input // format (samples per channel and number of channels). - const int input_samples_per_channel_; + const int input_num_frames_; const int num_input_channels_; // The audio is stored by DeinterleaveFrom() or CopyFrom() with processing // format. - const int proc_samples_per_channel_; + const int proc_num_frames_; const int num_proc_channels_; // The audio is returned by InterleaveTo() and CopyTo() with output samples // per channels and the current number of channels. This last one can be // changed at any time using set_num_channels(). - const int output_samples_per_channel_; + const int output_num_frames_; int num_channels_; int num_bands_; - int samples_per_split_channel_; + int num_split_frames_; bool mixed_low_pass_valid_; bool reference_copied_; AudioFrame::VADActivity activity_; const float* keyboard_data_; - scoped_ptr channels_; - ScopedVector split_channels_; - scoped_ptr bands_; - scoped_ptr bands_f_; + scoped_ptr data_; + scoped_ptr split_data_; scoped_ptr splitting_filter_; scoped_ptr > mixed_low_pass_channels_; scoped_ptr > low_pass_reference_channels_; diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc index 1319e16962..06b60385c9 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.cc +++ b/webrtc/modules/audio_processing/audio_processing_impl.cc @@ -598,7 +598,7 @@ int AudioProcessingImpl::ProcessStreamLocked() { AudioBuffer* ca = capture_audio_.get(); // For brevity. if (use_new_agc_ && gain_control_->is_enabled()) { - agc_manager_->AnalyzePreProcess(ca->data(0), + agc_manager_->AnalyzePreProcess(ca->channels()[0], ca->num_channels(), fwd_proc_format_.samples_per_channel()); } @@ -613,7 +613,7 @@ int AudioProcessingImpl::ProcessStreamLocked() { beamformer_->ProcessChunk(ca->split_channels_const_f(kBand0To8kHz), ca->split_channels_const_f(kBand8To16kHz), ca->num_channels(), - ca->samples_per_split_channel(), + ca->num_frames_per_band(), ca->split_channels_f(kBand0To8kHz), ca->split_channels_f(kBand8To16kHz)); ca->set_num_channels(1); @@ -636,7 +636,7 @@ int AudioProcessingImpl::ProcessStreamLocked() { gain_control_->is_enabled() && (!beamformer_enabled_ || beamformer_->is_target_present())) { agc_manager_->Process(ca->split_bands_const(0)[kBand0To8kHz], - ca->samples_per_split_channel(), + ca->num_frames_per_band(), split_rate_); } RETURN_ON_ERR(gain_control_->ProcessCaptureAudio(ca)); @@ -651,13 +651,13 @@ int AudioProcessingImpl::ProcessStreamLocked() { float voice_probability = agc_manager_.get() ? agc_manager_->voice_probability() : 1.f; - transient_suppressor_->Suppress(ca->data_f(0), - ca->samples_per_channel(), + transient_suppressor_->Suppress(ca->channels_f()[0], + ca->num_frames(), ca->num_channels(), ca->split_bands_const_f(0)[kBand0To8kHz], - ca->samples_per_split_channel(), + ca->num_frames_per_band(), ca->keyboard_data(), - ca->samples_per_keyboard_channel(), + ca->num_keyboard_frames(), voice_probability, key_pressed_); } diff --git a/webrtc/modules/audio_processing/beamformer/pcm_utils.cc b/webrtc/modules/audio_processing/beamformer/pcm_utils.cc index 14d9742330..207a2dc30e 100644 --- a/webrtc/modules/audio_processing/beamformer/pcm_utils.cc +++ b/webrtc/modules/audio_processing/beamformer/pcm_utils.cc @@ -51,7 +51,7 @@ size_t PcmReadToFloat(FILE* file, PcmRead(file, length, num_channels, deinterleaved_buffer->channels()); for (int i = 0; i < num_channels; ++i) { - S16ToFloat(deinterleaved_buffer->channel(i), num_frames, buffer[i]); + S16ToFloat(deinterleaved_buffer->channels()[i], num_frames, buffer[i]); } return elements_read; } @@ -82,7 +82,7 @@ void PcmWriteFromFloat(FILE* file, new ChannelBuffer(num_frames, num_channels)); for (int i = 0; i < num_channels; ++i) { - FloatToS16(buffer[i], num_frames, deinterleaved_buffer->channel(i)); + FloatToS16(buffer[i], num_frames, deinterleaved_buffer->channels()[i]); } PcmWrite(file, length, num_channels, deinterleaved_buffer->channels()); } diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc index dd3c7f1cc5..245941a426 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc @@ -77,7 +77,7 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == apm_->num_reverse_channels()); int err = apm_->kNoError; @@ -90,7 +90,7 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { err = WebRtcAec_BufferFarend( my_handle, audio->split_bands_const_f(j)[kBand0To8kHz], - static_cast(audio->samples_per_split_channel())); + static_cast(audio->num_frames_per_band())); if (err != apm_->kNoError) { return GetHandleError(my_handle); // TODO(ajm): warning possible? @@ -116,7 +116,7 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { return apm_->kStreamParameterNotSetError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == apm_->num_output_channels()); int err = apm_->kNoError; @@ -132,7 +132,7 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { audio->split_bands_const_f(i), audio->num_bands(), audio->split_bands_f(i), - static_cast(audio->samples_per_split_channel()), + static_cast(audio->num_frames_per_band()), apm_->stream_delay_ms(), stream_drift_samples_); diff --git a/webrtc/modules/audio_processing/echo_control_mobile_impl.cc b/webrtc/modules/audio_processing/echo_control_mobile_impl.cc index 534732ee97..0f5b4fe7ab 100644 --- a/webrtc/modules/audio_processing/echo_control_mobile_impl.cc +++ b/webrtc/modules/audio_processing/echo_control_mobile_impl.cc @@ -83,7 +83,7 @@ int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == apm_->num_reverse_channels()); int err = apm_->kNoError; @@ -96,7 +96,7 @@ int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { err = WebRtcAecm_BufferFarend( my_handle, audio->split_bands_const(j)[kBand0To8kHz], - static_cast(audio->samples_per_split_channel())); + static_cast(audio->num_frames_per_band())); if (err != apm_->kNoError) { return GetHandleError(my_handle); // TODO(ajm): warning possible? @@ -118,7 +118,7 @@ int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { return apm_->kStreamParameterNotSetError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == apm_->num_output_channels()); int err = apm_->kNoError; @@ -141,7 +141,7 @@ int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { noisy, clean, audio->split_bands(i)[kBand0To8kHz], - static_cast(audio->samples_per_split_channel()), + static_cast(audio->num_frames_per_band()), apm_->stream_delay_ms()); if (err != apm_->kNoError) { diff --git a/webrtc/modules/audio_processing/gain_control_impl.cc b/webrtc/modules/audio_processing/gain_control_impl.cc index af92b9c149..6211c4985c 100644 --- a/webrtc/modules/audio_processing/gain_control_impl.cc +++ b/webrtc/modules/audio_processing/gain_control_impl.cc @@ -57,14 +57,14 @@ int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); for (int i = 0; i < num_handles(); i++) { Handle* my_handle = static_cast(handle(i)); int err = WebRtcAgc_AddFarend( my_handle, audio->mixed_low_pass_data(), - static_cast(audio->samples_per_split_channel())); + static_cast(audio->num_frames_per_band())); if (err != apm_->kNoError) { return GetHandleError(my_handle); @@ -79,7 +79,7 @@ int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == num_handles()); int err = apm_->kNoError; @@ -92,7 +92,7 @@ int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { my_handle, audio->split_bands(i), audio->num_bands(), - static_cast(audio->samples_per_split_channel())); + static_cast(audio->num_frames_per_band())); if (err != apm_->kNoError) { return GetHandleError(my_handle); @@ -108,7 +108,7 @@ int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { my_handle, audio->split_bands(i), audio->num_bands(), - static_cast(audio->samples_per_split_channel()), + static_cast(audio->num_frames_per_band()), analog_capture_level_, &capture_level_out); @@ -133,7 +133,7 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { return apm_->kStreamParameterNotSetError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == num_handles()); stream_is_saturated_ = false; @@ -146,7 +146,7 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { my_handle, audio->split_bands_const(i), audio->num_bands(), - static_cast(audio->samples_per_split_channel()), + static_cast(audio->num_frames_per_band()), audio->split_bands(i), capture_levels_[i], &capture_level_out, diff --git a/webrtc/modules/audio_processing/high_pass_filter_impl.cc b/webrtc/modules/audio_processing/high_pass_filter_impl.cc index 43c3754bdf..588ba41415 100644 --- a/webrtc/modules/audio_processing/high_pass_filter_impl.cc +++ b/webrtc/modules/audio_processing/high_pass_filter_impl.cc @@ -114,13 +114,13 @@ int HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); for (int i = 0; i < num_handles(); i++) { Handle* my_handle = static_cast(handle(i)); err = Filter(my_handle, audio->split_bands(i)[kBand0To8kHz], - audio->samples_per_split_channel()); + audio->num_frames_per_band()); if (err != apm_->kNoError) { return GetHandleError(my_handle); diff --git a/webrtc/modules/audio_processing/level_estimator_impl.cc b/webrtc/modules/audio_processing/level_estimator_impl.cc index 5fbda836e3..26a61dcdb5 100644 --- a/webrtc/modules/audio_processing/level_estimator_impl.cc +++ b/webrtc/modules/audio_processing/level_estimator_impl.cc @@ -31,8 +31,8 @@ int LevelEstimatorImpl::ProcessStream(AudioBuffer* audio) { RMSLevel* rms_level = static_cast(handle(0)); for (int i = 0; i < audio->num_channels(); ++i) { - rms_level->Process(audio->data_const(i), - audio->samples_per_channel()); + rms_level->Process(audio->channels_const()[i], + audio->num_frames()); } return AudioProcessing::kNoError; diff --git a/webrtc/modules/audio_processing/noise_suppression_impl.cc b/webrtc/modules/audio_processing/noise_suppression_impl.cc index 05ef910383..aa37e67fa8 100644 --- a/webrtc/modules/audio_processing/noise_suppression_impl.cc +++ b/webrtc/modules/audio_processing/noise_suppression_impl.cc @@ -60,7 +60,7 @@ int NoiseSuppressionImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { if (!is_component_enabled()) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == num_handles()); for (int i = 0; i < num_handles(); ++i) { @@ -76,7 +76,7 @@ int NoiseSuppressionImpl::ProcessCaptureAudio(AudioBuffer* audio) { if (!is_component_enabled()) { return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); assert(audio->num_channels() == num_handles()); for (int i = 0; i < num_handles(); ++i) { diff --git a/webrtc/modules/audio_processing/splitting_filter.cc b/webrtc/modules/audio_processing/splitting_filter.cc index f3cbcadfb1..623bb05891 100644 --- a/webrtc/modules/audio_processing/splitting_filter.cc +++ b/webrtc/modules/audio_processing/splitting_filter.cc @@ -30,59 +30,53 @@ SplittingFilter::SplittingFilter(int channels) } } -void SplittingFilter::Analysis(const IFChannelBuffer* in_data, - const std::vector& bands) { - DCHECK(bands.size() == 2 || bands.size() == 3); - DCHECK_EQ(channels_, in_data->num_channels()); - for (size_t i = 0; i < bands.size(); ++i) { - DCHECK_EQ(channels_, bands[i]->num_channels()); - DCHECK_EQ(in_data->samples_per_channel(), - static_cast(bands.size()) * bands[i]->samples_per_channel()); - } - if (bands.size() == 2) { - TwoBandsAnalysis(in_data, bands[0], bands[1]); - } else if (bands.size() == 3) { - ThreeBandsAnalysis(in_data, bands[0], bands[1], bands[2]); +void SplittingFilter::Analysis(const IFChannelBuffer* data, + IFChannelBuffer* bands) { + DCHECK(bands->num_bands() == 2 || bands->num_bands() == 3); + DCHECK_EQ(channels_, data->num_channels()); + DCHECK_EQ(channels_, bands->num_channels()); + DCHECK_EQ(data->num_frames(), + bands->num_frames_per_band() * bands->num_bands()); + if (bands->num_bands() == 2) { + TwoBandsAnalysis(data, bands); + } else if (bands->num_bands() == 3) { + ThreeBandsAnalysis(data, bands); } } -void SplittingFilter::Synthesis(const std::vector& bands, - IFChannelBuffer* out_data) { - DCHECK(bands.size() == 2 || bands.size() == 3); - DCHECK_EQ(channels_, out_data->num_channels()); - for (size_t i = 0; i < bands.size(); ++i) { - DCHECK_EQ(channels_, bands[i]->num_channels()); - DCHECK_EQ(out_data->samples_per_channel(), - static_cast(bands.size()) * bands[i]->samples_per_channel()); - } - if (bands.size() == 2) { - TwoBandsSynthesis(bands[0], bands[1], out_data); - } else if (bands.size() == 3) { - ThreeBandsSynthesis(bands[0], bands[1], bands[2], out_data); +void SplittingFilter::Synthesis(const IFChannelBuffer* bands, + IFChannelBuffer* data) { + DCHECK(bands->num_bands() == 2 || bands->num_bands() == 3); + DCHECK_EQ(channels_, data->num_channels()); + DCHECK_EQ(channels_, bands->num_channels()); + DCHECK_EQ(data->num_frames(), + bands->num_frames_per_band() * bands->num_bands()); + if (bands->num_bands() == 2) { + TwoBandsSynthesis(bands, data); + } else if (bands->num_bands() == 3) { + ThreeBandsSynthesis(bands, data); } } -void SplittingFilter::TwoBandsAnalysis(const IFChannelBuffer* in_data, - IFChannelBuffer* band1, - IFChannelBuffer* band2) { +void SplittingFilter::TwoBandsAnalysis(const IFChannelBuffer* data, + IFChannelBuffer* bands) { for (int i = 0; i < channels_; ++i) { - WebRtcSpl_AnalysisQMF(in_data->ibuf_const()->channel(i), - in_data->samples_per_channel(), - band1->ibuf()->channel(i), - band2->ibuf()->channel(i), + WebRtcSpl_AnalysisQMF(data->ibuf_const()->channels()[i], + data->num_frames(), + bands->ibuf()->channels(0)[i], + bands->ibuf()->channels(1)[i], two_bands_states_[i].analysis_state1, two_bands_states_[i].analysis_state2); } } -void SplittingFilter::TwoBandsSynthesis(const IFChannelBuffer* band1, - const IFChannelBuffer* band2, - IFChannelBuffer* out_data) { +void SplittingFilter::TwoBandsSynthesis(const IFChannelBuffer* bands, + IFChannelBuffer* data) { for (int i = 0; i < channels_; ++i) { - WebRtcSpl_SynthesisQMF(band1->ibuf_const()->channel(i), - band2->ibuf_const()->channel(i), - band1->samples_per_channel(), - out_data->ibuf()->channel(i), + WebRtcSpl_SynthesisQMF(bands->ibuf_const()->channels(0)[i], + bands->ibuf_const()->channels(1)[i], + bands->num_frames_per_band(), + data->ibuf()->channels()[i], two_bands_states_[i].synthesis_state1, two_bands_states_[i].synthesis_state2); } @@ -92,15 +86,13 @@ void SplittingFilter::TwoBandsSynthesis(const IFChannelBuffer* band1, // by a proper 3 band filter bank. // It up-samples from 48kHz to 64kHz, splits twice into 2 bands and discards the // uppermost band, because it is empty anyway. -void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* in_data, - IFChannelBuffer* band1, - IFChannelBuffer* band2, - IFChannelBuffer* band3) { +void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* data, + IFChannelBuffer* bands) { DCHECK_EQ(kSamplesPer48kHzChannel, - in_data->samples_per_channel()); + data->num_frames()); InitBuffers(); for (int i = 0; i < channels_; ++i) { - analysis_resamplers_[i]->Resample(in_data->ibuf_const()->channel(i), + analysis_resamplers_[i]->Resample(data->ibuf_const()->channels()[i], kSamplesPer48kHzChannel, int_buffer_.get(), kSamplesPer64kHzChannel); @@ -112,14 +104,14 @@ void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* in_data, two_bands_states_[i].analysis_state2); WebRtcSpl_AnalysisQMF(int_buffer_.get(), kSamplesPer32kHzChannel, - band1->ibuf()->channel(i), - band2->ibuf()->channel(i), + bands->ibuf()->channels(0)[i], + bands->ibuf()->channels(1)[i], band1_states_[i].analysis_state1, band1_states_[i].analysis_state2); WebRtcSpl_AnalysisQMF(int_buffer_.get() + kSamplesPer32kHzChannel, kSamplesPer32kHzChannel, int_buffer_.get(), - band3->ibuf()->channel(i), + bands->ibuf()->channels(2)[i], band2_states_[i].analysis_state1, band2_states_[i].analysis_state2); } @@ -129,25 +121,23 @@ void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* in_data, // by a proper 3 band filter bank. // Using an empty uppermost band, it merges the 4 bands in 2 steps and // down-samples from 64kHz to 48kHz. -void SplittingFilter::ThreeBandsSynthesis(const IFChannelBuffer* band1, - const IFChannelBuffer* band2, - const IFChannelBuffer* band3, - IFChannelBuffer* out_data) { +void SplittingFilter::ThreeBandsSynthesis(const IFChannelBuffer* bands, + IFChannelBuffer* data) { DCHECK_EQ(kSamplesPer48kHzChannel, - out_data->samples_per_channel()); + data->num_frames()); InitBuffers(); for (int i = 0; i < channels_; ++i) { memset(int_buffer_.get(), 0, kSamplesPer64kHzChannel * sizeof(int_buffer_[0])); - WebRtcSpl_SynthesisQMF(band1->ibuf_const()->channel(i), - band2->ibuf_const()->channel(i), + WebRtcSpl_SynthesisQMF(bands->ibuf_const()->channels(0)[i], + bands->ibuf_const()->channels(1)[i], kSamplesPer16kHzChannel, int_buffer_.get(), band1_states_[i].synthesis_state1, band1_states_[i].synthesis_state2); WebRtcSpl_SynthesisQMF(int_buffer_.get() + kSamplesPer32kHzChannel, - band3->ibuf_const()->channel(i), + bands->ibuf_const()->channels(2)[i], kSamplesPer16kHzChannel, int_buffer_.get() + kSamplesPer32kHzChannel, band2_states_[i].synthesis_state1, @@ -160,7 +150,7 @@ void SplittingFilter::ThreeBandsSynthesis(const IFChannelBuffer* band1, two_bands_states_[i].synthesis_state2); synthesis_resamplers_[i]->Resample(int_buffer_.get(), kSamplesPer64kHzChannel, - out_data->ibuf()->channel(i), + data->ibuf()->channels()[i], kSamplesPer48kHzChannel); } } diff --git a/webrtc/modules/audio_processing/splitting_filter.h b/webrtc/modules/audio_processing/splitting_filter.h index 119375b51d..16387a8c56 100644 --- a/webrtc/modules/audio_processing/splitting_filter.h +++ b/webrtc/modules/audio_processing/splitting_filter.h @@ -56,28 +56,16 @@ class SplittingFilter { public: SplittingFilter(int channels); - void Analysis(const IFChannelBuffer* in_data, - const std::vector& bands); - void Synthesis(const std::vector& bands, - IFChannelBuffer* out_data); + void Analysis(const IFChannelBuffer* data, IFChannelBuffer* bands); + void Synthesis(const IFChannelBuffer* bands, IFChannelBuffer* data); private: // These work for 640 samples or less. - void TwoBandsAnalysis(const IFChannelBuffer* in_data, - IFChannelBuffer* band1, - IFChannelBuffer* band2); - void TwoBandsSynthesis(const IFChannelBuffer* band1, - const IFChannelBuffer* band2, - IFChannelBuffer* out_data); + void TwoBandsAnalysis(const IFChannelBuffer* data, IFChannelBuffer* bands); + void TwoBandsSynthesis(const IFChannelBuffer* bands, IFChannelBuffer* data); // These only work for 480 samples at the moment. - void ThreeBandsAnalysis(const IFChannelBuffer* in_data, - IFChannelBuffer* band1, - IFChannelBuffer* band2, - IFChannelBuffer* band3); - void ThreeBandsSynthesis(const IFChannelBuffer* band1, - const IFChannelBuffer* band2, - const IFChannelBuffer* band3, - IFChannelBuffer* out_data); + void ThreeBandsAnalysis(const IFChannelBuffer* data, IFChannelBuffer* bands); + void ThreeBandsSynthesis(const IFChannelBuffer* bands, IFChannelBuffer* data); void InitBuffers(); int channels_; diff --git a/webrtc/modules/audio_processing/splitting_filter_unittest.cc b/webrtc/modules/audio_processing/splitting_filter_unittest.cc index 105392d8de..598057f8c2 100644 --- a/webrtc/modules/audio_processing/splitting_filter_unittest.cc +++ b/webrtc/modules/audio_processing/splitting_filter_unittest.cc @@ -35,36 +35,32 @@ TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) { static const float kAmplitude = 8192; static const int kChunks = 8; SplittingFilter splitting_filter(kChannels); - IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels); - IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels); - ScopedVector bands; - for (int i = 0; i < kNumBands; ++i) { - bands.push_back(new IFChannelBuffer(kSamplesPer16kHzChannel, kChannels)); - } + IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels, kNumBands); + IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels, kNumBands); for (int i = 0; i < kChunks; ++i) { // Input signal generation. bool is_present[kNumBands]; - memset(in_data.fbuf()->channel(0), + memset(in_data.fbuf()->channels()[0], 0, - kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channel(0)[0])); + kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channels()[0][0])); for (int j = 0; j < kNumBands; ++j) { is_present[j] = i & (1 << j); float amplitude = is_present[j] ? kAmplitude : 0; for (int k = 0; k < kSamplesPer48kHzChannel; ++k) { - in_data.fbuf()->channel(0)[k] += + in_data.fbuf()->channels()[0][k] += amplitude * sin(2 * M_PI * kFrequenciesHz[j] * (i * kSamplesPer48kHzChannel + k) / kSampleRateHz); } } // Three band splitting filter. - splitting_filter.Analysis(&in_data, bands.get()); + splitting_filter.Analysis(&in_data, &out_data); // Energy calculation. float energy[kNumBands]; for (int j = 0; j < kNumBands; ++j) { energy[j] = 0; for (int k = 0; k < kSamplesPer16kHzChannel; ++k) { - energy[j] += bands[j]->fbuf_const()->channel(0)[k] * - bands[j]->fbuf_const()->channel(0)[k]; + energy[j] += out_data.fbuf_const()->channels(j)[0][k] * + out_data.fbuf_const()->channels(j)[0][k]; } energy[j] /= kSamplesPer16kHzChannel; if (is_present[j]) { @@ -74,14 +70,14 @@ TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) { } } // Three band merge. - splitting_filter.Synthesis(bands.get(), &out_data); + splitting_filter.Synthesis(&out_data, &out_data); // Delay and cross correlation estimation. float xcorr = 0; for (int delay = 0; delay < kSamplesPer48kHzChannel; ++delay) { float tmpcorr = 0; for (int j = delay; j < kSamplesPer48kHzChannel; ++j) { - tmpcorr += in_data.fbuf_const()->channel(0)[j] * - out_data.fbuf_const()->channel(0)[j - delay]; + tmpcorr += in_data.fbuf_const()->channels()[0][j] * + out_data.fbuf_const()->channels()[0][j - delay]; } tmpcorr /= kSamplesPer48kHzChannel; if (tmpcorr > xcorr) { diff --git a/webrtc/modules/audio_processing/test/audio_processing_unittest.cc b/webrtc/modules/audio_processing/test/audio_processing_unittest.cc index d9ebe8eca9..0c907580bc 100644 --- a/webrtc/modules/audio_processing/test/audio_processing_unittest.cc +++ b/webrtc/modules/audio_processing/test/audio_processing_unittest.cc @@ -62,15 +62,17 @@ const size_t kProcessSampleRatesSize = sizeof(kProcessSampleRates) / sizeof(*kProcessSampleRates); void ConvertToFloat(const int16_t* int_data, ChannelBuffer* cb) { - ChannelBuffer cb_int(cb->samples_per_channel(), + ChannelBuffer cb_int(cb->num_frames(), cb->num_channels()); Deinterleave(int_data, - cb->samples_per_channel(), + cb->num_frames(), cb->num_channels(), cb_int.channels()); - S16ToFloat(cb_int.data(), - cb->samples_per_channel() * cb->num_channels(), - cb->data()); + for (int i = 0; i < cb->num_channels(); ++i) { + S16ToFloat(cb_int.channels()[i], + cb->num_frames(), + cb->channels()[i]); + } } void ConvertToFloat(const AudioFrame& frame, ChannelBuffer* cb) { @@ -294,7 +296,7 @@ void OpenFileAndReadMessage(const std::string filename, bool ReadChunk(FILE* file, int16_t* int_data, float* float_data, ChannelBuffer* cb) { // The files always contain stereo audio. - size_t frame_size = cb->samples_per_channel() * 2; + size_t frame_size = cb->num_frames() * 2; size_t read_count = fread(int_data, sizeof(int16_t), frame_size, file); if (read_count != frame_size) { // Check that the file really ended. @@ -304,9 +306,9 @@ bool ReadChunk(FILE* file, int16_t* int_data, float* float_data, S16ToFloat(int_data, frame_size, float_data); if (cb->num_channels() == 1) { - MixStereoToMono(float_data, cb->data(), cb->samples_per_channel()); + MixStereoToMono(float_data, cb->channels()[0], cb->num_frames()); } else { - Deinterleave(float_data, cb->samples_per_channel(), 2, + Deinterleave(float_data, cb->num_frames(), 2, cb->channels()); } @@ -1250,12 +1252,14 @@ TEST_F(ApmTest, AgcOnlyAdaptsWhenTargetSignalIsPresent) { int_data.get(), float_data.get(), &src_buf)); - for (int j = 0; j < kNumInputChannels * kSamplesPerChannel; ++j) { - src_buf.data()[j] *= kScaleFactor; + for (int j = 0; j < kNumInputChannels; ++j) { + for (int k = 0; k < kSamplesPerChannel; ++k) { + src_buf.channels()[j][k] *= kScaleFactor; + } } EXPECT_EQ(kNoErr, apm->ProcessStream(src_buf.channels(), - src_buf.samples_per_channel(), + src_buf.num_frames(), kSampleRateHz, LayoutFromChannels(src_buf.num_channels()), kSampleRateHz, @@ -1273,12 +1277,14 @@ TEST_F(ApmTest, AgcOnlyAdaptsWhenTargetSignalIsPresent) { int_data.get(), float_data.get(), &src_buf)); - for (int j = 0; j < kNumInputChannels * kSamplesPerChannel; ++j) { - src_buf.data()[j] *= kScaleFactor; + for (int j = 0; j < kNumInputChannels; ++j) { + for (int k = 0; k < kSamplesPerChannel; ++k) { + src_buf.channels()[j][k] *= kScaleFactor; + } } EXPECT_EQ(kNoErr, apm->ProcessStream(src_buf.channels(), - src_buf.samples_per_channel(), + src_buf.num_frames(), kSampleRateHz, LayoutFromChannels(src_buf.num_channels()), kSampleRateHz, @@ -1648,7 +1654,8 @@ void ApmTest::ProcessDebugDump(const std::string& in_filename, if (msg.channel_size() > 0) { ASSERT_EQ(revframe_->num_channels_, msg.channel_size()); for (int i = 0; i < msg.channel_size(); ++i) { - memcpy(revfloat_cb_->channel(i), msg.channel(i).data(), + memcpy(revfloat_cb_->channels()[i], + msg.channel(i).data(), msg.channel(i).size()); } } else { @@ -1677,7 +1684,8 @@ void ApmTest::ProcessDebugDump(const std::string& in_filename, if (msg.input_channel_size() > 0) { ASSERT_EQ(frame_->num_channels_, msg.input_channel_size()); for (int i = 0; i < msg.input_channel_size(); ++i) { - memcpy(float_cb_->channel(i), msg.input_channel(i).data(), + memcpy(float_cb_->channels()[i], + msg.input_channel(i).data(), msg.input_channel(i).size()); } } else { @@ -1835,7 +1843,6 @@ TEST_F(ApmTest, FloatAndIntInterfacesGiveSimilarResults) { const int num_output_channels = test->num_output_channels(); const int samples_per_channel = test->sample_rate() * AudioProcessing::kChunkSizeMs / 1000; - const int output_length = samples_per_channel * num_output_channels; Init(test->sample_rate(), test->sample_rate(), test->sample_rate(), num_input_channels, num_output_channels, num_render_channels, true); @@ -1876,11 +1883,13 @@ TEST_F(ApmTest, FloatAndIntInterfacesGiveSimilarResults) { test->sample_rate(), LayoutFromChannels(num_output_channels), float_cb_->channels())); - - FloatToS16(float_cb_->data(), output_length, output_cb.data()); for (int j = 0; j < num_output_channels; ++j) { + FloatToS16(float_cb_->channels()[j], + samples_per_channel, + output_cb.channels()[j]); float variance = 0; - float snr = ComputeSNR(output_int16.channel(j), output_cb.channel(j), + float snr = ComputeSNR(output_int16.channels()[j], + output_cb.channels()[j], samples_per_channel, &variance); #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) // There are a few chunks in the fixed-point profile that give low SNR. @@ -2171,7 +2180,7 @@ TEST_F(ApmTest, NoErrorsWithKeyboardChannel) { for (int j = 0; j < 10; ++j) { EXPECT_NOERR(ap->ProcessStream( in_cb.channels(), - in_cb.samples_per_channel(), + in_cb.num_frames(), in_rate, cf[i].in_layout, out_rate, @@ -2313,9 +2322,9 @@ class AudioProcessingTest // Temporary buffers. const int max_length = - 2 * std::max(out_cb.samples_per_channel(), - std::max(fwd_cb.samples_per_channel(), - rev_cb.samples_per_channel())); + 2 * std::max(out_cb.num_frames(), + std::max(fwd_cb.num_frames(), + rev_cb.num_frames())); scoped_ptr float_data(new float[max_length]); scoped_ptr int_data(new int16_t[max_length]); @@ -2324,7 +2333,7 @@ class AudioProcessingTest ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) { EXPECT_NOERR(ap->AnalyzeReverseStream( rev_cb.channels(), - rev_cb.samples_per_channel(), + rev_cb.num_frames(), reverse_rate, LayoutFromChannels(num_reverse_channels))); @@ -2334,7 +2343,7 @@ class AudioProcessingTest EXPECT_NOERR(ap->ProcessStream( fwd_cb.channels(), - fwd_cb.samples_per_channel(), + fwd_cb.num_frames(), input_rate, LayoutFromChannels(num_input_channels), output_rate, @@ -2342,13 +2351,14 @@ class AudioProcessingTest out_cb.channels())); Interleave(out_cb.channels(), - out_cb.samples_per_channel(), + out_cb.num_frames(), out_cb.num_channels(), float_data.get()); // Dump output to file. - ASSERT_EQ(static_cast(out_cb.length()), + int out_length = out_cb.num_channels() * out_cb.num_frames(); + ASSERT_EQ(static_cast(out_length), fwrite(float_data.get(), sizeof(float_data[0]), - out_cb.length(), out_file)); + out_length, out_file)); analog_level = ap->gain_control()->stream_analog_level(); } diff --git a/webrtc/modules/audio_processing/test/audioproc_float.cc b/webrtc/modules/audio_processing/test/audioproc_float.cc index bbac9f1c91..e1418e97c8 100644 --- a/webrtc/modules/audio_processing/test/audioproc_float.cc +++ b/webrtc/modules/audio_processing/test/audioproc_float.cc @@ -177,27 +177,30 @@ int main(int argc, char* argv[]) { ChannelBuffer o_buf(o_file.sample_rate() / kChunksPerSecond, o_file.num_channels()); - const size_t c_length = static_cast(c_buf.length()); + const size_t c_length = + static_cast(c_buf.num_channels() * c_buf.num_frames()); + const size_t o_length = + static_cast(o_buf.num_channels() * o_buf.num_frames()); scoped_ptr c_interleaved(new float[c_length]); - scoped_ptr o_interleaved(new float[o_buf.length()]); + scoped_ptr o_interleaved(new float[o_length]); while (c_file.ReadSamples(c_length, c_interleaved.get()) == c_length) { FloatS16ToFloat(c_interleaved.get(), c_length, c_interleaved.get()); - Deinterleave(c_interleaved.get(), c_buf.samples_per_channel(), + Deinterleave(c_interleaved.get(), c_buf.num_frames(), c_buf.num_channels(), c_buf.channels()); CHECK_EQ(kNoErr, ap->ProcessStream(c_buf.channels(), - c_buf.samples_per_channel(), + c_buf.num_frames(), c_file.sample_rate(), LayoutFromChannels(c_buf.num_channels()), o_file.sample_rate(), LayoutFromChannels(o_buf.num_channels()), o_buf.channels())); - Interleave(o_buf.channels(), o_buf.samples_per_channel(), + Interleave(o_buf.channels(), o_buf.num_frames(), o_buf.num_channels(), o_interleaved.get()); - FloatToFloatS16(o_interleaved.get(), o_buf.length(), o_interleaved.get()); - o_file.WriteSamples(o_interleaved.get(), o_buf.length()); + FloatToFloatS16(o_interleaved.get(), o_length, o_interleaved.get()); + o_file.WriteSamples(o_interleaved.get(), o_length); } return 0; diff --git a/webrtc/modules/audio_processing/test/process_test.cc b/webrtc/modules/audio_processing/test/process_test.cc index 3af495c19b..d1fa032a44 100644 --- a/webrtc/modules/audio_processing/test/process_test.cc +++ b/webrtc/modules/audio_processing/test/process_test.cc @@ -654,7 +654,10 @@ void void_main(int argc, char* argv[]) { memcpy(far_frame.data_, msg.data().data(), msg.data().size()); } else { for (int i = 0; i < msg.channel_size(); ++i) { - reverse_cb->CopyFrom(msg.channel(i).data(), i); + memcpy(reverse_cb->channels()[i], + msg.channel(i).data(), + reverse_cb->num_frames() * + sizeof(reverse_cb->channels()[i][0])); } } @@ -704,7 +707,10 @@ void void_main(int argc, char* argv[]) { near_read_bytes += msg.input_data().size(); } else { for (int i = 0; i < msg.input_channel_size(); ++i) { - primary_cb->CopyFrom(msg.input_channel(i).data(), i); + memcpy(primary_cb->channels()[i], + msg.input_channel(i).data(), + primary_cb->num_frames() * + sizeof(primary_cb->channels()[i][0])); near_read_bytes += msg.input_channel(i).size(); } } diff --git a/webrtc/modules/audio_processing/voice_detection_impl.cc b/webrtc/modules/audio_processing/voice_detection_impl.cc index 31336b41df..da51a10ab1 100644 --- a/webrtc/modules/audio_processing/voice_detection_impl.cc +++ b/webrtc/modules/audio_processing/voice_detection_impl.cc @@ -59,7 +59,7 @@ int VoiceDetectionImpl::ProcessCaptureAudio(AudioBuffer* audio) { using_external_vad_ = false; return apm_->kNoError; } - assert(audio->samples_per_split_channel() <= 160); + assert(audio->num_frames_per_band() <= 160); // TODO(ajm): concatenate data in frame buffer here.