From e364ac902fe7e711de73e2fde22dff3cbe1e3a6f Mon Sep 17 00:00:00 2001 From: "kwiberg@webrtc.org" Date: Fri, 18 Jul 2014 07:50:29 +0000 Subject: [PATCH] AudioBuffer: Optimize const accesses to arrays that autoconvert int16<->float Specifically, when someone asks for a const pointer to the int16 version of the array, there's no need to invalidate the float version of that array, and vice versa. (But obviously, invalidation still has to happen when someone asks for a non-const pointer.) R=aluebs@webrtc.org, andrew@webrtc.org, minyue@webrtc.org Review URL: https://webrtc-codereview.appspot.com/18809004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6725 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../modules/audio_processing/audio_buffer.cc | 62 +++++++++++-------- .../modules/audio_processing/audio_buffer.h | 4 +- webrtc/modules/audio_processing/common.h | 6 +- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/webrtc/modules/audio_processing/audio_buffer.cc b/webrtc/modules/audio_processing/audio_buffer.cc index 1ceba383bd..fb2c200e5d 100644 --- a/webrtc/modules/audio_processing/audio_buffer.cc +++ b/webrtc/modules/audio_processing/audio_buffer.cc @@ -70,8 +70,9 @@ void StereoToMono(const int16_t* left, const int16_t* right, int16_t* out, // One int16_t and one float ChannelBuffer that are kept in sync. The sync is // broken when someone requests write access to either ChannelBuffer, and // reestablished when someone requests the outdated ChannelBuffer. It is -// therefore safe to use the return value of ibuf() and fbuf() until the next -// call to the other method. +// therefore safe to use the return value of ibuf_const() and fbuf_const() +// until the next call to ibuf() or fbuf(), and the return value of ibuf() and +// fbuf() until the next call to any of the other functions. class IFChannelBuffer { public: IFChannelBuffer(int samples_per_channel, int num_channels) @@ -80,19 +81,24 @@ class IFChannelBuffer { fvalid_(true), fbuf_(samples_per_channel, num_channels) {} - ChannelBuffer* ibuf() { + ChannelBuffer* ibuf() { return ibuf(false); } + ChannelBuffer* fbuf() { return fbuf(false); } + const ChannelBuffer* ibuf_const() { return ibuf(true); } + const ChannelBuffer* fbuf_const() { return fbuf(true); } + + private: + ChannelBuffer* ibuf(bool readonly) { RefreshI(); - fvalid_ = false; + fvalid_ = readonly; return &ibuf_; } - ChannelBuffer* fbuf() { + ChannelBuffer* fbuf(bool readonly) { RefreshF(); - ivalid_ = false; + ivalid_ = readonly; return &fbuf_; } - private: void RefreshF() { if (!fvalid_) { assert(ivalid_); @@ -266,69 +272,71 @@ void AudioBuffer::InitForNewData() { } const int16_t* AudioBuffer::data(int channel) const { - return channels_->ibuf()->channel(channel); + return channels_->ibuf_const()->channel(channel); } int16_t* AudioBuffer::data(int channel) { mixed_low_pass_valid_ = false; - const AudioBuffer* t = this; - return const_cast(t->data(channel)); + return channels_->ibuf()->channel(channel); } const float* AudioBuffer::data_f(int channel) const { - return channels_->fbuf()->channel(channel); + return channels_->fbuf_const()->channel(channel); } float* AudioBuffer::data_f(int channel) { mixed_low_pass_valid_ = false; - const AudioBuffer* t = this; - return const_cast(t->data_f(channel)); + return channels_->fbuf()->channel(channel); } const int16_t* AudioBuffer::low_pass_split_data(int channel) const { return split_channels_low_.get() - ? split_channels_low_->ibuf()->channel(channel) + ? split_channels_low_->ibuf_const()->channel(channel) : data(channel); } int16_t* AudioBuffer::low_pass_split_data(int channel) { mixed_low_pass_valid_ = false; - const AudioBuffer* t = this; - return const_cast(t->low_pass_split_data(channel)); + return split_channels_low_.get() + ? split_channels_low_->ibuf()->channel(channel) + : data(channel); } const float* AudioBuffer::low_pass_split_data_f(int channel) const { return split_channels_low_.get() - ? split_channels_low_->fbuf()->channel(channel) + ? split_channels_low_->fbuf_const()->channel(channel) : data_f(channel); } float* AudioBuffer::low_pass_split_data_f(int channel) { mixed_low_pass_valid_ = false; - const AudioBuffer* t = this; - return const_cast(t->low_pass_split_data_f(channel)); + return split_channels_low_.get() + ? split_channels_low_->fbuf()->channel(channel) + : data_f(channel); } const int16_t* AudioBuffer::high_pass_split_data(int channel) const { + return split_channels_high_.get() + ? split_channels_high_->ibuf_const()->channel(channel) + : NULL; +} + +int16_t* AudioBuffer::high_pass_split_data(int channel) { return split_channels_high_.get() ? split_channels_high_->ibuf()->channel(channel) : NULL; } -int16_t* AudioBuffer::high_pass_split_data(int channel) { - const AudioBuffer* t = this; - return const_cast(t->high_pass_split_data(channel)); -} - const float* AudioBuffer::high_pass_split_data_f(int channel) const { return split_channels_high_.get() - ? split_channels_high_->fbuf()->channel(channel) + ? split_channels_high_->fbuf_const()->channel(channel) : NULL; } float* AudioBuffer::high_pass_split_data_f(int channel) { - const AudioBuffer* t = this; - return const_cast(t->high_pass_split_data_f(channel)); + return split_channels_high_.get() + ? split_channels_high_->fbuf()->channel(channel) + : NULL; } const int16_t* AudioBuffer::mixed_low_pass_data() { diff --git a/webrtc/modules/audio_processing/audio_buffer.h b/webrtc/modules/audio_processing/audio_buffer.h index 5c26ae29d0..acf5753cbb 100644 --- a/webrtc/modules/audio_processing/audio_buffer.h +++ b/webrtc/modules/audio_processing/audio_buffer.h @@ -55,7 +55,9 @@ class AudioBuffer { int samples_per_split_channel() const; int samples_per_keyboard_channel() const; - // It can be assumed that channels are stored contiguously. + // 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(int channel) const; int16_t* low_pass_split_data(int channel); diff --git a/webrtc/modules/audio_processing/common.h b/webrtc/modules/audio_processing/common.h index 10249cc2bb..98e36cb098 100644 --- a/webrtc/modules/audio_processing/common.h +++ b/webrtc/modules/audio_processing/common.h @@ -54,10 +54,14 @@ class ChannelBuffer { } T* data() { return data_.get(); } - T* channel(int i) { + const T* channel(int i) const { assert(i >= 0 && i < num_channels_); return channels_[i]; } + T* channel(int i) { + const ChannelBuffer* t = this; + return const_cast(t->channel(i)); + } T** channels() { return channels_.get(); } int samples_per_channel() { return samples_per_channel_; }