Chromium Code Reviews| Index: media/filters/audio_renderer_algorithm.cc |
| diff --git a/media/filters/audio_renderer_algorithm.cc b/media/filters/audio_renderer_algorithm.cc |
| index ebe334a0f1a0c76c1063ed1c79512cc36fd4c6bb..31bb8a22b38854ae8dca10bc64be5fd015664171 100644 |
| --- a/media/filters/audio_renderer_algorithm.cc |
| +++ b/media/filters/audio_renderer_algorithm.cc |
| @@ -82,9 +82,11 @@ AudioRendererAlgorithm::AudioRendererAlgorithm() |
| AudioRendererAlgorithm::~AudioRendererAlgorithm() {} |
| -void AudioRendererAlgorithm::Initialize(const AudioParameters& params) { |
| +void AudioRendererAlgorithm::Initialize(const AudioParameters& params, |
| + std::vector<bool> channel_mask) { |
| CHECK(params.IsValid()); |
| + channel_mask_ = std::move(channel_mask); |
| channels_ = params.channels(); |
| samples_per_second_ = params.sample_rate(); |
| initial_capacity_ = capacity_ = |
| @@ -137,6 +139,29 @@ void AudioRendererAlgorithm::Initialize(const AudioParameters& params) { |
| search_block_ = AudioBus::Create( |
| channels_, num_candidate_blocks_ + (ola_window_size_ - 1)); |
| target_block_ = AudioBus::Create(channels_, ola_window_size_); |
| + |
| + if (channel_mask_.empty()) { |
| + channel_mask_ = std::vector<bool>(channels_, true); |
| + return; |
| + } |
| + |
| + DCHECK_EQ(channel_mask_.size(), static_cast<size_t>(channels_)); |
| + |
| + // WSOLA is quite expensive to run, so if a channel mask exists, use it to |
| + // reduce the size of our search space. |
| + std::vector<float*> active_target_channels; |
| + std::vector<float*> active_search_channels; |
| + for (int ch = 0; ch < channels_; ++ch) { |
| + if (channel_mask_[ch]) { |
| + active_target_channels.push_back(target_block_->channel(ch)); |
| + active_search_channels.push_back(search_block_->channel(ch)); |
| + } |
| + } |
| + |
| + reduced_target_block_ = |
| + AudioBus::WrapVector(target_block_->frames(), active_target_channels); |
| + reduced_search_block_ = |
| + AudioBus::WrapVector(search_block_->frames(), active_search_channels); |
| } |
| int AudioRendererAlgorithm::FillBuffer(AudioBus* dest, |
| @@ -254,11 +279,14 @@ bool AudioRendererAlgorithm::RunOneWsolaIteration(double playback_rate) { |
| // Overlap-and-add. |
| for (int k = 0; k < channels_; ++k) { |
| + if (!channel_mask_[k]) |
| + continue; |
| + |
| const float* const ch_opt_frame = optimal_block_->channel(k); |
| float* ch_output = wsola_output_->channel(k) + num_complete_frames_; |
| for (int n = 0; n < ola_hop_size_; ++n) { |
| ch_output[n] = ch_output[n] * ola_window_[ola_hop_size_ + n] + |
| - ch_opt_frame[n] * ola_window_[n]; |
| + ch_opt_frame[n] * ola_window_[n]; |
| } |
| // Copy the second half to the output. |
| @@ -310,6 +338,8 @@ int AudioRendererAlgorithm::WriteCompletedFramesTo( |
| // Remove the frames which are read. |
| int frames_to_move = wsola_output_->frames() - rendered_frames; |
| for (int k = 0; k < channels_; ++k) { |
| + if (!channel_mask_[k]) |
| + continue; |
| float* ch = wsola_output_->channel(k); |
| memmove(ch, &ch[rendered_frames], sizeof(*ch) * frames_to_move); |
| } |
| @@ -338,16 +368,20 @@ void AudioRendererAlgorithm::GetOptimalBlock() { |
| } else { |
| PeekAudioWithZeroPrepend(target_block_index_, target_block_.get()); |
| PeekAudioWithZeroPrepend(search_block_index_, search_block_.get()); |
| - int last_optimal = target_block_index_ - ola_hop_size_ - |
| - search_block_index_; |
| - internal::Interval exclude_iterval = std::make_pair( |
| - last_optimal - kExcludeIntervalLengthFrames / 2, |
| - last_optimal + kExcludeIntervalLengthFrames / 2); |
| + int last_optimal = |
| + target_block_index_ - ola_hop_size_ - search_block_index_; |
| + internal::Interval exclude_interval = |
| + std::make_pair(last_optimal - kExcludeIntervalLengthFrames / 2, |
| + last_optimal + kExcludeIntervalLengthFrames / 2); |
| // |optimal_index| is in frames and it is relative to the beginning of the |
| // |search_block_|. |
| optimal_index = internal::OptimalIndex( |
| - search_block_.get(), target_block_.get(), exclude_iterval); |
| + reduced_search_block_ ? reduced_search_block_.get() |
| + : search_block_.get(), |
|
sandersd (OOO until July 31)
2016/11/22 00:59:24
Nit: Simpler to understand if |reduced_search_bloc
DaleCurtis
2016/11/22 01:07:49
Done. Renamed to search_block_wrapper_ since it's
|
| + reduced_target_block_ ? reduced_target_block_.get() |
| + : target_block_.get(), |
| + exclude_interval); |
| // Translate |index| w.r.t. the beginning of |audio_buffer_| and extract the |
| // optimal block. |
| @@ -363,11 +397,13 @@ void AudioRendererAlgorithm::GetOptimalBlock() { |
| // where target-block has higher weight close to zero (weight of 1 at index |
| // 0) and lower weight close the end. |
| for (int k = 0; k < channels_; ++k) { |
| + if (!channel_mask_[k]) |
| + continue; |
| float* ch_opt = optimal_block_->channel(k); |
| const float* const ch_target = target_block_->channel(k); |
| for (int n = 0; n < ola_window_size_; ++n) { |
| - ch_opt[n] = ch_opt[n] * transition_window_[n] + ch_target[n] * |
| - transition_window_[ola_window_size_ + n]; |
| + ch_opt[n] = ch_opt[n] * transition_window_[n] + |
| + ch_target[n] * transition_window_[ola_window_size_ + n]; |
| } |
| } |
| } |