diff options
author | kwiberg@webrtc.org <kwiberg@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-18 07:50:29 +0000 |
---|---|---|
committer | kwiberg@webrtc.org <kwiberg@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2014-07-18 07:50:29 +0000 |
commit | 84649c022683027d6c1765fad1d7b447a8e8b03a (patch) | |
tree | 70cfcf3b5afe84069fe28259479791a3d612df6e /modules | |
parent | 8bd216f982a7ecd65fef95db7a40bc034d2062bd (diff) | |
download | webrtc-84649c022683027d6c1765fad1d7b447a8e8b03a.tar.gz |
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/webrtc@6725 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'modules')
-rw-r--r-- | modules/audio_processing/audio_buffer.cc | 58 | ||||
-rw-r--r-- | modules/audio_processing/audio_buffer.h | 4 | ||||
-rw-r--r-- | modules/audio_processing/common.h | 6 |
3 files changed, 41 insertions, 27 deletions
diff --git a/modules/audio_processing/audio_buffer.cc b/modules/audio_processing/audio_buffer.cc index 1ceba383..fb2c200e 100644 --- a/modules/audio_processing/audio_buffer.cc +++ b/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<int16_t>* ibuf() { + ChannelBuffer<int16_t>* ibuf() { return ibuf(false); } + ChannelBuffer<float>* fbuf() { return fbuf(false); } + const ChannelBuffer<int16_t>* ibuf_const() { return ibuf(true); } + const ChannelBuffer<float>* fbuf_const() { return fbuf(true); } + + private: + ChannelBuffer<int16_t>* ibuf(bool readonly) { RefreshI(); - fvalid_ = false; + fvalid_ = readonly; return &ibuf_; } - ChannelBuffer<float>* fbuf() { + ChannelBuffer<float>* 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<int16_t*>(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<float*>(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<int16_t*>(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<float*>(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()->channel(channel) + ? split_channels_high_->ibuf_const()->channel(channel) : NULL; } int16_t* AudioBuffer::high_pass_split_data(int channel) { - const AudioBuffer* t = this; - return const_cast<int16_t*>(t->high_pass_split_data(channel)); + return split_channels_high_.get() + ? split_channels_high_->ibuf()->channel(channel) + : NULL; } 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<float*>(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/modules/audio_processing/audio_buffer.h b/modules/audio_processing/audio_buffer.h index 5c26ae29..acf5753c 100644 --- a/modules/audio_processing/audio_buffer.h +++ b/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/modules/audio_processing/common.h b/modules/audio_processing/common.h index 10249cc2..98e36cb0 100644 --- a/modules/audio_processing/common.h +++ b/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>* t = this; + return const_cast<T*>(t->channel(i)); + } T** channels() { return channels_.get(); } int samples_per_channel() { return samples_per_channel_; } |