Chromium Code Reviews| Index: webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc |
| diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc |
| index fe964aba8c3eb2a795f30db17cc49d93c2f788fa..bcb8b1b6a34196069bc57217a85cd18107ebb717 100644 |
| --- a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc |
| +++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc |
| @@ -47,9 +47,8 @@ using std::min; |
| using VarianceType = intelligibility::VarianceArray::StepType; |
| IntelligibilityEnhancer::TransformCallback::TransformCallback( |
| - IntelligibilityEnhancer* parent, |
| - IntelligibilityEnhancer::AudioSource source) |
| - : parent_(parent), source_(source) { |
| + IntelligibilityEnhancer* parent) |
| + : parent_(parent) { |
| } |
| void IntelligibilityEnhancer::TransformCallback::ProcessAudioBlock( |
| @@ -60,7 +59,7 @@ void IntelligibilityEnhancer::TransformCallback::ProcessAudioBlock( |
| complex<float>* const* out_block) { |
| RTC_DCHECK_EQ(parent_->freqs_, frames); |
| for (size_t i = 0; i < in_channels; ++i) { |
| - parent_->DispatchAudio(source_, in_block[i], out_block[i]); |
| + parent_->ProcessClearBlock(in_block[i], out_block[i]); |
| } |
| } |
| @@ -85,27 +84,26 @@ IntelligibilityEnhancer::IntelligibilityEnhancer(const Config& config) |
| config.var_type, |
| config.var_window_size, |
| config.var_decay_rate), |
| - noise_variance_(freqs_, |
| - config.var_type, |
| - config.var_window_size, |
| - config.var_decay_rate), |
| filtered_clear_var_(new float[bank_size_]), |
| filtered_noise_var_(new float[bank_size_]), |
| - filter_bank_(bank_size_), |
| center_freqs_(new float[bank_size_]), |
| + render_filter_bank_(CreateErbBank(freqs_)), |
| rho_(new float[bank_size_]), |
| gains_eq_(new float[bank_size_]), |
| gain_applier_(freqs_, config.gain_change_limit), |
| temp_render_out_buffer_(chunk_length_, num_render_channels_), |
| - temp_capture_out_buffer_(chunk_length_, num_capture_channels_), |
| kbd_window_(new float[window_size_]), |
| - render_callback_(this, AudioSource::kRenderStream), |
| - capture_callback_(this, AudioSource::kCaptureStream), |
| + render_callback_(this), |
| block_count_(0), |
| analysis_step_(0) { |
| RTC_DCHECK_LE(config.rho, 1.0f); |
| - CreateErbBank(); |
| + memset(filtered_clear_var_.get(), |
| + 0, |
| + bank_size_ * sizeof(filtered_clear_var_[0])); |
| + memset(filtered_noise_var_.get(), |
| + 0, |
| + bank_size_ * sizeof(filtered_noise_var_[0])); |
| // Assumes all rho equal. |
| for (size_t i = 0; i < bank_size_; ++i) { |
| @@ -122,9 +120,23 @@ IntelligibilityEnhancer::IntelligibilityEnhancer(const Config& config) |
| render_mangler_.reset(new LappedTransform( |
| num_render_channels_, num_render_channels_, chunk_length_, |
| kbd_window_.get(), window_size_, window_size_ / 2, &render_callback_)); |
| - capture_mangler_.reset(new LappedTransform( |
| - num_capture_channels_, num_capture_channels_, chunk_length_, |
| - kbd_window_.get(), window_size_, window_size_ / 2, &capture_callback_)); |
| +} |
| + |
| +void IntelligibilityEnhancer::SetCaptureNoiseEstimate( |
| + const std::vector<float>& noise) { |
| + if (capture_filter_bank_.size() != bank_size_ || |
|
hlundin-webrtc
2016/02/08 10:29:28
What kind of events lead up to capture_filter_bank
aluebs-webrtc
2016/02/09 00:19:15
Because the input length of the noise vector is no
|
| + capture_filter_bank_[0].size() != noise.size()) { |
| + capture_filter_bank_ = CreateErbBank(noise.size()); |
| + } |
| + if (noise_power_.size() != noise.size()) { |
| + noise_power_.resize(noise.size()); |
| + } |
| + for (size_t i = 0; i < noise.size(); ++i) { |
| + noise_power_[i] = noise[i] * noise[i]; |
| + } |
| + FilterVariance(&noise_power_[0], |
| + capture_filter_bank_, |
| + filtered_noise_var_.get()); |
| } |
| void IntelligibilityEnhancer::ProcessRenderAudio(float* const* audio, |
| @@ -145,29 +157,6 @@ void IntelligibilityEnhancer::ProcessRenderAudio(float* const* audio, |
| } |
| } |
| -void IntelligibilityEnhancer::AnalyzeCaptureAudio(float* const* audio, |
| - int sample_rate_hz, |
| - size_t num_channels) { |
| - RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz); |
| - RTC_CHECK_EQ(num_capture_channels_, num_channels); |
| - |
| - capture_mangler_->ProcessChunk(audio, temp_capture_out_buffer_.channels()); |
| -} |
| - |
| -void IntelligibilityEnhancer::DispatchAudio( |
| - IntelligibilityEnhancer::AudioSource source, |
| - const complex<float>* in_block, |
| - complex<float>* out_block) { |
| - switch (source) { |
| - case kRenderStream: |
| - ProcessClearBlock(in_block, out_block); |
| - break; |
| - case kCaptureStream: |
| - ProcessNoiseBlock(in_block, out_block); |
| - break; |
| - } |
| -} |
| - |
| void IntelligibilityEnhancer::ProcessClearBlock(const complex<float>* in_block, |
| complex<float>* out_block) { |
| if (block_count_ < 2) { |
| @@ -194,9 +183,9 @@ void IntelligibilityEnhancer::ProcessClearBlock(const complex<float>* in_block, |
| } |
| void IntelligibilityEnhancer::AnalyzeClearBlock(float power_target) { |
| - FilterVariance(clear_variance_.variance(), filtered_clear_var_.get()); |
| - FilterVariance(noise_variance_.variance(), filtered_noise_var_.get()); |
| - |
| + FilterVariance(clear_variance_.variance(), |
| + render_filter_bank_, |
| + filtered_clear_var_.get()); |
| SolveForGainsGivenLambda(kLambdaTop, start_freq_, gains_eq_.get()); |
| const float power_top = |
| DotProduct(gains_eq_.get(), filtered_clear_var_.get(), bank_size_); |
| @@ -242,16 +231,11 @@ void IntelligibilityEnhancer::UpdateErbGains() { |
| for (size_t i = 0; i < freqs_; ++i) { |
| gains[i] = 0.0f; |
| for (size_t j = 0; j < bank_size_; ++j) { |
| - gains[i] = fmaf(filter_bank_[j][i], gains_eq_[j], gains[i]); |
| + gains[i] = fmaf(render_filter_bank_[j][i], gains_eq_[j], gains[i]); |
| } |
| } |
| } |
| -void IntelligibilityEnhancer::ProcessNoiseBlock(const complex<float>* in_block, |
| - complex<float>* /*out_block*/) { |
| - noise_variance_.Step(in_block); |
| -} |
| - |
| size_t IntelligibilityEnhancer::GetBankSize(int sample_rate, |
| size_t erb_resolution) { |
| float freq_limit = sample_rate / 2000.0f; |
| @@ -260,7 +244,9 @@ size_t IntelligibilityEnhancer::GetBankSize(int sample_rate, |
| return erb_scale * erb_resolution; |
| } |
| -void IntelligibilityEnhancer::CreateErbBank() { |
| +std::vector<std::vector<float>> IntelligibilityEnhancer::CreateErbBank( |
| + size_t num_freqs) { |
| + std::vector<std::vector<float>> filter_bank(bank_size_); |
| size_t lf = 1, rf = 4; |
| for (size_t i = 0; i < bank_size_; ++i) { |
| @@ -274,58 +260,60 @@ void IntelligibilityEnhancer::CreateErbBank() { |
| } |
| for (size_t i = 0; i < bank_size_; ++i) { |
| - filter_bank_[i].resize(freqs_); |
| + filter_bank[i].resize(num_freqs); |
| } |
| for (size_t i = 1; i <= bank_size_; ++i) { |
| size_t lll, ll, rr, rrr; |
| static const size_t kOne = 1; // Avoids repeated static_cast<>s below. |
| lll = static_cast<size_t>(round( |
| - center_freqs_[max(kOne, i - lf) - 1] * freqs_ / |
| + center_freqs_[max(kOne, i - lf) - 1] * num_freqs / |
| (0.5f * sample_rate_hz_))); |
| ll = static_cast<size_t>(round( |
| - center_freqs_[max(kOne, i) - 1] * freqs_ / (0.5f * sample_rate_hz_))); |
| - lll = min(freqs_, max(lll, kOne)) - 1; |
| - ll = min(freqs_, max(ll, kOne)) - 1; |
| + center_freqs_[max(kOne, i) - 1] * num_freqs / |
| + (0.5f * sample_rate_hz_))); |
| + lll = min(num_freqs, max(lll, kOne)) - 1; |
| + ll = min(num_freqs, max(ll, kOne)) - 1; |
| rrr = static_cast<size_t>(round( |
| - center_freqs_[min(bank_size_, i + rf) - 1] * freqs_ / |
| + center_freqs_[min(bank_size_, i + rf) - 1] * num_freqs / |
| (0.5f * sample_rate_hz_))); |
| rr = static_cast<size_t>(round( |
| - center_freqs_[min(bank_size_, i + 1) - 1] * freqs_ / |
| + center_freqs_[min(bank_size_, i + 1) - 1] * num_freqs / |
| (0.5f * sample_rate_hz_))); |
| - rrr = min(freqs_, max(rrr, kOne)) - 1; |
| - rr = min(freqs_, max(rr, kOne)) - 1; |
| + rrr = min(num_freqs, max(rrr, kOne)) - 1; |
| + rr = min(num_freqs, max(rr, kOne)) - 1; |
| float step, element; |
| step = 1.0f / (ll - lll); |
| element = 0.0f; |
| for (size_t j = lll; j <= ll; ++j) { |
| - filter_bank_[i - 1][j] = element; |
| + filter_bank[i - 1][j] = element; |
| element += step; |
| } |
| step = 1.0f / (rrr - rr); |
| element = 1.0f; |
| for (size_t j = rr; j <= rrr; ++j) { |
| - filter_bank_[i - 1][j] = element; |
| + filter_bank[i - 1][j] = element; |
| element -= step; |
| } |
| for (size_t j = ll; j <= rr; ++j) { |
| - filter_bank_[i - 1][j] = 1.0f; |
| + filter_bank[i - 1][j] = 1.0f; |
| } |
| } |
| float sum; |
| - for (size_t i = 0; i < freqs_; ++i) { |
| + for (size_t i = 0; i < num_freqs; ++i) { |
| sum = 0.0f; |
| for (size_t j = 0; j < bank_size_; ++j) { |
| - sum += filter_bank_[j][i]; |
| + sum += filter_bank[j][i]; |
| } |
| for (size_t j = 0; j < bank_size_; ++j) { |
| - filter_bank_[j][i] /= sum; |
| + filter_bank[j][i] /= sum; |
| } |
| } |
| + return filter_bank; |
| } |
| void IntelligibilityEnhancer::SolveForGainsGivenLambda(float lambda, |
| @@ -356,10 +344,13 @@ void IntelligibilityEnhancer::SolveForGainsGivenLambda(float lambda, |
| } |
| } |
| -void IntelligibilityEnhancer::FilterVariance(const float* var, float* result) { |
| - RTC_DCHECK_GT(freqs_, 0u); |
| +void IntelligibilityEnhancer::FilterVariance( |
|
hlundin-webrtc
2016/02/08 10:29:28
This method no longer uses any class members, righ
aluebs-webrtc
2016/02/09 00:19:15
Done.
|
| + const float* var, |
| + const std::vector<std::vector<float>>& filter_bank, |
| + float* result) { |
| for (size_t i = 0; i < bank_size_; ++i) { |
| - result[i] = DotProduct(&filter_bank_[i][0], var, freqs_); |
| + RTC_DCHECK_GT(filter_bank[i].size(), 0u); |
| + result[i] = DotProduct(&filter_bank[i][0], var, filter_bank[i].size()); |
| } |
| } |