diff options
Diffstat (limited to 'webrtc/modules/audio_processing/audio_buffer.cc')
-rw-r--r-- | webrtc/modules/audio_processing/audio_buffer.cc | 689 |
1 files changed, 317 insertions, 372 deletions
diff --git a/webrtc/modules/audio_processing/audio_buffer.cc b/webrtc/modules/audio_processing/audio_buffer.cc index 81790a1..ff6636d 100644 --- a/webrtc/modules/audio_processing/audio_buffer.cc +++ b/webrtc/modules/audio_processing/audio_buffer.cc @@ -8,455 +8,400 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/audio_processing/audio_buffer.h" +#include "modules/audio_processing/audio_buffer.h" -#include "webrtc/common_audio/include/audio_util.h" -#include "webrtc/common_audio/resampler/push_sinc_resampler.h" -#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" -#include "webrtc/common_audio/channel_buffer.h" -#include "webrtc/modules/audio_processing/common.h" +#include <string.h> + +#include <cstdint> + +#include "common_audio/channel_buffer.h" +#include "common_audio/include/audio_util.h" +#include "common_audio/resampler/push_sinc_resampler.h" +#include "modules/audio_processing/splitting_filter.h" +#include "rtc_base/checks.h" namespace webrtc { namespace { -const size_t kSamplesPer16kHzChannel = 160; -const size_t kSamplesPer32kHzChannel = 320; -const size_t kSamplesPer48kHzChannel = 480; +constexpr size_t kSamplesPer32kHzChannel = 320; +constexpr size_t kSamplesPer48kHzChannel = 480; +constexpr size_t kMaxSamplesPerChannel = AudioBuffer::kMaxSampleRate / 100; -int KeyboardChannelIndex(const StreamConfig& stream_config) { - if (!stream_config.has_keyboard()) { - assert(false); - return -1; +size_t NumBandsFromFramesPerChannel(size_t num_frames) { + if (num_frames == kSamplesPer32kHzChannel) { + return 2; } - - return stream_config.num_channels(); -} - -size_t NumBandsFromSamplesPerChannel(size_t num_frames) { - size_t num_bands = 1; - if (num_frames == kSamplesPer32kHzChannel || - num_frames == kSamplesPer48kHzChannel) { - num_bands = rtc::CheckedDivExact(num_frames, kSamplesPer16kHzChannel); + if (num_frames == kSamplesPer48kHzChannel) { + return 3; } - return num_bands; + return 1; } } // namespace +AudioBuffer::AudioBuffer(size_t input_rate, + size_t input_num_channels, + size_t buffer_rate, + size_t buffer_num_channels, + size_t output_rate, + size_t output_num_channels) + : AudioBuffer(static_cast<int>(input_rate) / 100, + input_num_channels, + static_cast<int>(buffer_rate) / 100, + buffer_num_channels, + static_cast<int>(output_rate) / 100) {} + AudioBuffer::AudioBuffer(size_t input_num_frames, - int num_input_channels, - size_t process_num_frames, - int num_process_channels, + size_t input_num_channels, + size_t buffer_num_frames, + size_t buffer_num_channels, size_t output_num_frames) - : input_num_frames_(input_num_frames), - num_input_channels_(num_input_channels), - proc_num_frames_(process_num_frames), - num_proc_channels_(num_process_channels), - output_num_frames_(output_num_frames), - num_channels_(num_process_channels), - 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), - 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); - assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_); - - if (input_num_frames_ != proc_num_frames_ || - output_num_frames_ != proc_num_frames_) { - // Create an intermediate buffer for resampling. - process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_, - num_proc_channels_)); - - 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_)); - } + : input_num_frames_(input_num_frames), + input_num_channels_(input_num_channels), + buffer_num_frames_(buffer_num_frames), + buffer_num_channels_(buffer_num_channels), + output_num_frames_(output_num_frames), + output_num_channels_(0), + num_channels_(buffer_num_channels), + num_bands_(NumBandsFromFramesPerChannel(buffer_num_frames_)), + num_split_frames_(rtc::CheckedDivExact(buffer_num_frames_, num_bands_)), + data_( + new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)) { + RTC_DCHECK_GT(input_num_frames_, 0); + RTC_DCHECK_GT(buffer_num_frames_, 0); + RTC_DCHECK_GT(output_num_frames_, 0); + RTC_DCHECK_GT(input_num_channels_, 0); + RTC_DCHECK_GT(buffer_num_channels_, 0); + RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_); + + const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_; + const bool output_resampling_needed = + output_num_frames_ != buffer_num_frames_; + if (input_resampling_needed) { + for (size_t i = 0; i < buffer_num_channels_; ++i) { + input_resamplers_.push_back(std::unique_ptr<PushSincResampler>( + new PushSincResampler(input_num_frames_, buffer_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_resampling_needed) { + for (size_t i = 0; i < buffer_num_channels_; ++i) { + output_resamplers_.push_back(std::unique_ptr<PushSincResampler>( + new PushSincResampler(buffer_num_frames_, output_num_frames_))); } } 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_, - num_bands_, - proc_num_frames_)); + split_data_.reset(new ChannelBuffer<float>( + buffer_num_frames_, buffer_num_channels_, num_bands_)); + splitting_filter_.reset(new SplittingFilter( + buffer_num_channels_, num_bands_, buffer_num_frames_)); } } AudioBuffer::~AudioBuffer() {} -void AudioBuffer::CopyFrom(const float* const* data, - const StreamConfig& stream_config) { - assert(stream_config.num_frames() == input_num_frames_); - assert(stream_config.num_channels() == num_input_channels_); - InitForNewData(); - // Initialized lazily because there's a different condition in - // DeinterleaveFrom. - const bool need_to_downmix = - num_input_channels_ > 1 && num_proc_channels_ == 1; - if (need_to_downmix && !input_buffer_) { - input_buffer_.reset( - new IFChannelBuffer(input_num_frames_, num_proc_channels_)); - } - - if (stream_config.has_keyboard()) { - keyboard_data_ = data[KeyboardChannelIndex(stream_config)]; - } +void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) { + downmix_by_averaging_ = false; + RTC_DCHECK_GT(input_num_channels_, channel); + channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1); +} - // Downmix. - const float* const* data_ptr = data; - if (need_to_downmix) { - DownmixToMono<float, float>(data, input_num_frames_, num_input_channels_, - input_buffer_->fbuf()->channels()[0]); - data_ptr = input_buffer_->fbuf_const()->channels(); - } +void AudioBuffer::set_downmixing_by_averaging() { + downmix_by_averaging_ = true; +} - // Resample. - if (input_num_frames_ != proc_num_frames_) { - for (int i = 0; i < num_proc_channels_; ++i) { - input_resamplers_[i]->Resample(data_ptr[i], - input_num_frames_, - process_buffer_->channels()[i], - proc_num_frames_); +void AudioBuffer::CopyFrom(const float* const* stacked_data, + const StreamConfig& stream_config) { + RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_); + RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_); + RestoreNumChannels(); + const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1; + + const bool resampling_needed = input_num_frames_ != buffer_num_frames_; + + if (downmix_needed) { + RTC_DCHECK_GE(kMaxSamplesPerChannel, input_num_frames_); + + std::array<float, kMaxSamplesPerChannel> downmix; + if (downmix_by_averaging_) { + const float kOneByNumChannels = 1.f / input_num_channels_; + for (size_t i = 0; i < input_num_frames_; ++i) { + float value = stacked_data[0][i]; + for (size_t j = 1; j < input_num_channels_; ++j) { + value += stacked_data[j][i]; + } + downmix[i] = value * kOneByNumChannels; + } } - data_ptr = process_buffer_->channels(); - } + const float* downmixed_data = downmix_by_averaging_ + ? downmix.data() + : stacked_data[channel_for_downmixing_]; - // Convert to the S16 range. - for (int i = 0; i < num_proc_channels_; ++i) { - FloatToFloatS16(data_ptr[i], - proc_num_frames_, - data_->fbuf()->channels()[i]); + if (resampling_needed) { + input_resamplers_[0]->Resample(downmixed_data, input_num_frames_, + data_->channels()[0], buffer_num_frames_); + } + const float* data_to_convert = + resampling_needed ? data_->channels()[0] : downmixed_data; + FloatToFloatS16(data_to_convert, buffer_num_frames_, data_->channels()[0]); + } else { + if (resampling_needed) { + for (size_t i = 0; i < num_channels_; ++i) { + input_resamplers_[i]->Resample(stacked_data[i], input_num_frames_, + data_->channels()[i], + buffer_num_frames_); + FloatToFloatS16(data_->channels()[i], buffer_num_frames_, + data_->channels()[i]); + } + } else { + for (size_t i = 0; i < num_channels_; ++i) { + FloatToFloatS16(stacked_data[i], buffer_num_frames_, + data_->channels()[i]); + } + } } } void AudioBuffer::CopyTo(const StreamConfig& stream_config, - float* const* data) { - assert(stream_config.num_frames() == output_num_frames_); - assert(stream_config.num_channels() == num_channels_); - - // Convert to the float range. - float* const* data_ptr = data; - 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(data_->fbuf()->channels()[i], - proc_num_frames_, - data_ptr[i]); - } - - // Resample. - if (output_num_frames_ != proc_num_frames_) { - for (int i = 0; i < num_channels_; ++i) { - output_resamplers_[i]->Resample(data_ptr[i], - proc_num_frames_, - data[i], - output_num_frames_); + float* const* stacked_data) { + RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_); + + const bool resampling_needed = output_num_frames_ != buffer_num_frames_; + if (resampling_needed) { + for (size_t i = 0; i < num_channels_; ++i) { + FloatS16ToFloat(data_->channels()[i], buffer_num_frames_, + data_->channels()[i]); + output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_, + stacked_data[i], output_num_frames_); + } + } else { + for (size_t i = 0; i < num_channels_; ++i) { + FloatS16ToFloat(data_->channels()[i], buffer_num_frames_, + stacked_data[i]); } } -} - -void AudioBuffer::InitForNewData() { - keyboard_data_ = NULL; - mixed_low_pass_valid_ = false; - reference_copied_ = false; - activity_ = AudioFrame::kVadUnknown; - num_channels_ = num_proc_channels_; -} - -const int16_t* const* AudioBuffer::channels_const() const { - return data_->ibuf_const()->channels(); -} -int16_t* const* AudioBuffer::channels() { - mixed_low_pass_valid_ = false; - return data_->ibuf()->channels(); -} - -const int16_t* const* AudioBuffer::split_bands_const(int channel) const { - return split_data_.get() ? - split_data_->ibuf_const()->bands(channel) : - data_->ibuf_const()->bands(channel); + for (size_t i = num_channels_; i < stream_config.num_channels(); ++i) { + memcpy(stacked_data[i], stacked_data[0], + output_num_frames_ * sizeof(**stacked_data)); + } } -int16_t* const* AudioBuffer::split_bands(int channel) { - mixed_low_pass_valid_ = false; - return split_data_.get() ? - split_data_->ibuf()->bands(channel) : - data_->ibuf()->bands(channel); -} +void AudioBuffer::CopyTo(AudioBuffer* buffer) const { + RTC_DCHECK_EQ(buffer->num_frames(), output_num_frames_); -const int16_t* const* AudioBuffer::split_channels_const(Band band) const { - if (split_data_.get()) { - return split_data_->ibuf_const()->channels(band); + const bool resampling_needed = output_num_frames_ != buffer_num_frames_; + if (resampling_needed) { + for (size_t i = 0; i < num_channels_; ++i) { + output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_, + buffer->channels()[i], + buffer->num_frames()); + } } else { - return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr; + for (size_t i = 0; i < num_channels_; ++i) { + memcpy(buffer->channels()[i], data_->channels()[i], + buffer_num_frames_ * sizeof(**buffer->channels())); + } } -} -int16_t* const* AudioBuffer::split_channels(Band band) { - mixed_low_pass_valid_ = false; - if (split_data_.get()) { - return split_data_->ibuf()->channels(band); - } else { - return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr; + for (size_t i = num_channels_; i < buffer->num_channels(); ++i) { + memcpy(buffer->channels()[i], buffer->channels()[0], + output_num_frames_ * sizeof(**buffer->channels())); } } -ChannelBuffer<int16_t>* AudioBuffer::data() { - mixed_low_pass_valid_ = false; - return data_->ibuf(); -} - -const ChannelBuffer<int16_t>* AudioBuffer::data() const { - return data_->ibuf_const(); -} - -ChannelBuffer<int16_t>* AudioBuffer::split_data() { - mixed_low_pass_valid_ = false; - return split_data_.get() ? split_data_->ibuf() : data_->ibuf(); -} - -const ChannelBuffer<int16_t>* AudioBuffer::split_data() const { - return split_data_.get() ? split_data_->ibuf_const() : data_->ibuf_const(); -} - -const float* const* AudioBuffer::channels_const_f() const { - return data_->fbuf_const()->channels(); -} - -float* const* AudioBuffer::channels_f() { - mixed_low_pass_valid_ = false; - return data_->fbuf()->channels(); -} - -const float* const* AudioBuffer::split_bands_const_f(int channel) const { - 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; - return split_data_.get() ? - split_data_->fbuf()->bands(channel) : - data_->fbuf()->bands(channel); -} - -const float* const* AudioBuffer::split_channels_const_f(Band band) const { +void AudioBuffer::RestoreNumChannels() { + num_channels_ = buffer_num_channels_; + data_->set_num_channels(buffer_num_channels_); if (split_data_.get()) { - return split_data_->fbuf_const()->channels(band); - } else { - return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr; + split_data_->set_num_channels(buffer_num_channels_); } } -float* const* AudioBuffer::split_channels_f(Band band) { - mixed_low_pass_valid_ = false; +void AudioBuffer::set_num_channels(size_t num_channels) { + RTC_DCHECK_GE(buffer_num_channels_, num_channels); + num_channels_ = num_channels; + data_->set_num_channels(num_channels); if (split_data_.get()) { - return split_data_->fbuf()->channels(band); - } else { - return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr; + split_data_->set_num_channels(num_channels); } } -ChannelBuffer<float>* AudioBuffer::data_f() { - mixed_low_pass_valid_ = false; - return data_->fbuf(); -} - -const ChannelBuffer<float>* AudioBuffer::data_f() const { - return data_->fbuf_const(); -} - -ChannelBuffer<float>* AudioBuffer::split_data_f() { - mixed_low_pass_valid_ = false; - return split_data_.get() ? split_data_->fbuf() : data_->fbuf(); -} - -const ChannelBuffer<float>* AudioBuffer::split_data_f() const { - return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const(); -} - -const int16_t* AudioBuffer::mixed_low_pass_data() { - if (num_proc_channels_ == 1) { - return split_bands_const(0)[kBand0To8kHz]; - } +// The resampler is only for supporting 48kHz to 16kHz in the reverse stream. +void AudioBuffer::CopyFrom(const int16_t* const interleaved_data, + const StreamConfig& stream_config) { + RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_); + RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_); + RestoreNumChannels(); + + const bool resampling_required = input_num_frames_ != buffer_num_frames_; + + const int16_t* interleaved = interleaved_data; + if (num_channels_ == 1) { + if (input_num_channels_ == 1) { + if (resampling_required) { + std::array<float, kMaxSamplesPerChannel> float_buffer; + S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data()); + input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_, + data_->channels()[0], + buffer_num_frames_); + } else { + S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]); + } + } else { + std::array<float, kMaxSamplesPerChannel> float_buffer; + float* downmixed_data = + resampling_required ? float_buffer.data() : data_->channels()[0]; + if (downmix_by_averaging_) { + for (size_t j = 0, k = 0; j < input_num_frames_; ++j) { + int32_t sum = 0; + for (size_t i = 0; i < input_num_channels_; ++i, ++k) { + sum += interleaved[k]; + } + downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_); + } + } else { + for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_; + ++j, k += input_num_channels_) { + downmixed_data[j] = interleaved[k]; + } + } - if (!mixed_low_pass_valid_) { - if (!mixed_low_pass_channels_.get()) { - mixed_low_pass_channels_.reset( - new ChannelBuffer<int16_t>(num_split_frames_, 1)); + if (resampling_required) { + input_resamplers_[0]->Resample(downmixed_data, input_num_frames_, + data_->channels()[0], + buffer_num_frames_); + } + } + } else { + auto deinterleave_channel = [](size_t channel, size_t num_channels, + size_t samples_per_channel, const int16_t* x, + float* y) { + for (size_t j = 0, k = channel; j < samples_per_channel; + ++j, k += num_channels) { + y[j] = x[k]; + } + }; + + if (resampling_required) { + std::array<float, kMaxSamplesPerChannel> float_buffer; + for (size_t i = 0; i < num_channels_; ++i) { + deinterleave_channel(i, num_channels_, input_num_frames_, interleaved, + float_buffer.data()); + input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_, + data_->channels()[i], + buffer_num_frames_); + } + } else { + for (size_t i = 0; i < num_channels_; ++i) { + deinterleave_channel(i, num_channels_, input_num_frames_, interleaved, + data_->channels()[i]); + } } - - DownmixToMono<int16_t, int32_t>(split_channels_const(kBand0To8kHz), - num_split_frames_, num_channels_, - mixed_low_pass_channels_->channels()[0]); - mixed_low_pass_valid_ = true; - } - return mixed_low_pass_channels_->channels()[0]; -} - -const int16_t* AudioBuffer::low_pass_reference(int channel) const { - if (!reference_copied_) { - return NULL; } - - return low_pass_reference_channels_->channels()[channel]; } -const float* AudioBuffer::keyboard_data() const { - return keyboard_data_; -} +void AudioBuffer::CopyTo(const StreamConfig& stream_config, + int16_t* const interleaved_data) { + const size_t config_num_channels = stream_config.num_channels(); -void AudioBuffer::set_activity(AudioFrame::VADActivity activity) { - activity_ = activity; -} + RTC_DCHECK(config_num_channels == num_channels_ || num_channels_ == 1); + RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_); -AudioFrame::VADActivity AudioBuffer::activity() const { - return activity_; -} + const bool resampling_required = buffer_num_frames_ != output_num_frames_; -int AudioBuffer::num_channels() const { - return num_channels_; -} + int16_t* interleaved = interleaved_data; + if (num_channels_ == 1) { + std::array<float, kMaxSamplesPerChannel> float_buffer; -void AudioBuffer::set_num_channels(int num_channels) { - num_channels_ = num_channels; -} + if (resampling_required) { + output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_, + float_buffer.data(), output_num_frames_); + } + const float* deinterleaved = + resampling_required ? float_buffer.data() : data_->channels()[0]; -size_t AudioBuffer::num_frames() const { - return proc_num_frames_; -} + if (config_num_channels == 1) { + for (size_t j = 0; j < output_num_frames_; ++j) { + interleaved[j] = FloatS16ToS16(deinterleaved[j]); + } + } else { + for (size_t i = 0, k = 0; i < output_num_frames_; ++i) { + float tmp = FloatS16ToS16(deinterleaved[i]); + for (size_t j = 0; j < config_num_channels; ++j, ++k) { + interleaved[k] = tmp; + } + } + } + } else { + auto interleave_channel = [](size_t channel, size_t num_channels, + size_t samples_per_channel, const float* x, + int16_t* y) { + for (size_t k = 0, j = channel; k < samples_per_channel; + ++k, j += num_channels) { + y[j] = FloatS16ToS16(x[k]); + } + }; + + if (resampling_required) { + for (size_t i = 0; i < num_channels_; ++i) { + std::array<float, kMaxSamplesPerChannel> float_buffer; + output_resamplers_[i]->Resample(data_->channels()[i], + buffer_num_frames_, float_buffer.data(), + output_num_frames_); + interleave_channel(i, config_num_channels, output_num_frames_, + float_buffer.data(), interleaved); + } + } else { + for (size_t i = 0; i < num_channels_; ++i) { + interleave_channel(i, config_num_channels, output_num_frames_, + data_->channels()[i], interleaved); + } + } -size_t AudioBuffer::num_frames_per_band() const { - return num_split_frames_; + for (size_t i = num_channels_; i < config_num_channels; ++i) { + for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_; + ++j, k += config_num_channels, n += config_num_channels) { + interleaved[k] = interleaved[n]; + } + } + } } -size_t AudioBuffer::num_keyboard_frames() const { - // We don't resample the keyboard channel. - return input_num_frames_; +void AudioBuffer::SplitIntoFrequencyBands() { + splitting_filter_->Analysis(data_.get(), split_data_.get()); } -size_t AudioBuffer::num_bands() const { - return num_bands_; +void AudioBuffer::MergeFrequencyBands() { + splitting_filter_->Synthesis(split_data_.get(), data_.get()); } -// The resampler is only for supporting 48kHz to 16kHz in the reverse stream. -void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) { - assert(frame->num_channels_ == num_input_channels_); - assert(frame->samples_per_channel_ == input_num_frames_); - InitForNewData(); - // Initialized lazily because there's a different condition in CopyFrom. - if ((input_num_frames_ != proc_num_frames_) && !input_buffer_) { - input_buffer_.reset( - new IFChannelBuffer(input_num_frames_, num_proc_channels_)); - } - activity_ = frame->vad_activity_; - - int16_t* const* deinterleaved; - if (input_num_frames_ == proc_num_frames_) { - deinterleaved = data_->ibuf()->channels(); - } else { - deinterleaved = input_buffer_->ibuf()->channels(); - } - if (num_proc_channels_ == 1) { - // Downmix and deinterleave simultaneously. - DownmixInterleavedToMono(frame->data_, input_num_frames_, - num_input_channels_, deinterleaved[0]); - } else { - assert(num_proc_channels_ == num_input_channels_); - Deinterleave(frame->data_, - input_num_frames_, - num_proc_channels_, - deinterleaved); - } +void AudioBuffer::ExportSplitChannelData( + size_t channel, + int16_t* const* split_band_data) const { + for (size_t k = 0; k < num_bands(); ++k) { + const float* band_data = split_bands_const(channel)[k]; - // Resample. - if (input_num_frames_ != proc_num_frames_) { - for (int i = 0; i < num_proc_channels_; ++i) { - input_resamplers_[i]->Resample(input_buffer_->fbuf_const()->channels()[i], - input_num_frames_, - data_->fbuf()->channels()[i], - proc_num_frames_); + RTC_DCHECK(split_band_data[k]); + RTC_DCHECK(band_data); + for (size_t i = 0; i < num_frames_per_band(); ++i) { + split_band_data[k][i] = FloatS16ToS16(band_data[i]); } } } -void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) { - frame->vad_activity_ = activity_; - if (!data_changed) { - return; - } - - assert(frame->num_channels_ == num_channels_ || num_channels_ == 1); - assert(frame->samples_per_channel_ == output_num_frames_); - - // Resample if necessary. - IFChannelBuffer* data_ptr = data_.get(); - if (proc_num_frames_ != output_num_frames_) { - if (!output_buffer_) { - output_buffer_.reset( - new IFChannelBuffer(output_num_frames_, num_channels_)); - } - for (int i = 0; i < num_channels_; ++i) { - output_resamplers_[i]->Resample( - data_->fbuf()->channels()[i], proc_num_frames_, - output_buffer_->fbuf()->channels()[i], output_num_frames_); +void AudioBuffer::ImportSplitChannelData( + size_t channel, + const int16_t* const* split_band_data) { + for (size_t k = 0; k < num_bands(); ++k) { + float* band_data = split_bands(channel)[k]; + RTC_DCHECK(split_band_data[k]); + RTC_DCHECK(band_data); + for (size_t i = 0; i < num_frames_per_band(); ++i) { + band_data[i] = split_band_data[k][i]; } - data_ptr = output_buffer_.get(); - } - - if (frame->num_channels_ == num_channels_) { - Interleave(data_ptr->ibuf()->channels(), proc_num_frames_, num_channels_, - frame->data_); - } else { - UpmixMonoToInterleaved(data_ptr->ibuf()->channels()[0], proc_num_frames_, - frame->num_channels_, frame->data_); - } -} - -void AudioBuffer::CopyLowPassToReference() { - reference_copied_ = true; - if (!low_pass_reference_channels_.get() || - low_pass_reference_channels_->num_channels() != num_channels_) { - low_pass_reference_channels_.reset( - new ChannelBuffer<int16_t>(num_split_frames_, - num_proc_channels_)); - } - for (int i = 0; i < num_proc_channels_; 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(data_.get(), split_data_.get()); -} - -void AudioBuffer::MergeFrequencyBands() { - splitting_filter_->Synthesis(split_data_.get(), data_.get()); -} - } // namespace webrtc |