From 3e8bf282c46d1010fdd56e2516147f268cae3a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85hgren?= Date: Thu, 29 Aug 2019 23:38:40 +0200 Subject: [PATCH] Increase the maximum supported sample rate to 384000 Hz and add tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL increases the maximum supported sample rate so that all rates up to 384000 Hz are handled. The CL also adds tests that verifies that APM works as intended for different combinations of number of channels and sample rates. Bug: webrtc:10882 Change-Id: I98738e33ac21413ae00fec10bb43b8796ae2078c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/150532 Commit-Queue: Per Ã…hgren Reviewed-by: Sam Zackrisson Cr-Commit-Position: refs/heads/master@{#29014} --- modules/audio_processing/audio_buffer.cc | 5 +- modules/audio_processing/audio_buffer.h | 1 + .../audio_processing_unittest.cc | 148 ++++++++++++++++++ 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/modules/audio_processing/audio_buffer.cc b/modules/audio_processing/audio_buffer.cc index 5ac4f94d30..4b0ca20d82 100644 --- a/modules/audio_processing/audio_buffer.cc +++ b/modules/audio_processing/audio_buffer.cc @@ -25,8 +25,7 @@ namespace { constexpr size_t kSamplesPer32kHzChannel = 320; constexpr size_t kSamplesPer48kHzChannel = 480; -constexpr size_t kSamplesPer192kHzChannel = 1920; -constexpr size_t kMaxSamplesPerChannel = kSamplesPer192kHzChannel; +constexpr size_t kMaxSamplesPerChannel = AudioBuffer::kMaxSampleRate / 100; size_t NumBandsFromFramesPerChannel(size_t num_frames) { if (num_frames == kSamplesPer32kHzChannel) { @@ -123,7 +122,7 @@ void AudioBuffer::CopyFrom(const float* const* data, const bool resampling_needed = input_num_frames_ != buffer_num_frames_; if (downmix_needed) { - RTC_DCHECK_GT(kMaxSamplesPerChannel, input_num_frames_); + RTC_DCHECK_GE(kMaxSamplesPerChannel, input_num_frames_); std::array downmix; if (downmix_by_averaging_) { diff --git a/modules/audio_processing/audio_buffer.h b/modules/audio_processing/audio_buffer.h index 2d136d8aa6..7bab26d4c9 100644 --- a/modules/audio_processing/audio_buffer.h +++ b/modules/audio_processing/audio_buffer.h @@ -33,6 +33,7 @@ enum Band { kBand0To8kHz = 0, kBand8To16kHz = 1, kBand16To24kHz = 2 }; class AudioBuffer { public: static const int kSplitBandSize = 160; + static const size_t kMaxSampleRate = 384000; AudioBuffer(size_t input_rate, size_t input_num_channels, size_t buffer_rate, diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc index 2556f67d4e..9c30ab088b 100644 --- a/modules/audio_processing/audio_processing_unittest.cc +++ b/modules/audio_processing/audio_processing_unittest.cc @@ -2257,6 +2257,128 @@ INSTANTIATE_TEST_SUITE_P( std::make_tuple(16000, 16000, 16000, 16000, 0, 0))); #endif +// Produces a scoped trace debug output. +std::string ProduceDebugText(int render_input_sample_rate_hz, + int render_output_sample_rate_hz, + int capture_input_sample_rate_hz, + int capture_output_sample_rate_hz, + size_t render_input_num_channels, + size_t render_output_num_channels, + size_t capture_input_num_channels, + size_t capture_output_num_channels) { + rtc::StringBuilder ss; + ss << "Sample rates:" + << "\n" + << " Render input: " << render_input_sample_rate_hz << " Hz" + << "\n" + << " Render output: " << render_output_sample_rate_hz << " Hz" + << "\n" + << " Capture input: " << capture_input_sample_rate_hz << " Hz" + << "\n" + << " Capture output: " << capture_output_sample_rate_hz << " Hz" + << "\n" + << "Number of channels:" + << "\n" + << " Render input: " << render_input_num_channels << "\n" + << " Render output: " << render_output_num_channels << "\n" + << " Capture input: " << capture_input_num_channels << "\n" + << " Capture output: " << capture_output_num_channels; + return ss.Release(); +} + +// Validates that running the audio processing module using various combinations +// of sample rates and number of channels works as intended. +void RunApmRateAndChannelTest( + rtc::ArrayView sample_rates_hz, + rtc::ArrayView render_channel_counts, + rtc::ArrayView capture_channel_counts) { + std::unique_ptr apm(AudioProcessingBuilder().Create()); + webrtc::AudioProcessing::Config apm_config; + apm_config.echo_canceller.enabled = true; + apm->ApplyConfig(apm_config); + + StreamConfig render_input_stream_config; + StreamConfig render_output_stream_config; + StreamConfig capture_input_stream_config; + StreamConfig capture_output_stream_config; + + std::vector render_input_frame_channels; + std::vector render_input_frame; + std::vector render_output_frame_channels; + std::vector render_output_frame; + std::vector capture_input_frame_channels; + std::vector capture_input_frame; + std::vector capture_output_frame_channels; + std::vector capture_output_frame; + + for (auto render_input_sample_rate_hz : sample_rates_hz) { + for (auto render_output_sample_rate_hz : sample_rates_hz) { + for (auto capture_input_sample_rate_hz : sample_rates_hz) { + for (auto capture_output_sample_rate_hz : sample_rates_hz) { + for (size_t render_input_num_channels : render_channel_counts) { + for (size_t capture_input_num_channels : capture_channel_counts) { + size_t render_output_num_channels = render_input_num_channels; + size_t capture_output_num_channels = capture_input_num_channels; + auto populate_audio_frame = [](int sample_rate_hz, + size_t num_channels, + StreamConfig* cfg, + std::vector* channels_data, + std::vector* frame_data) { + cfg->set_sample_rate_hz(sample_rate_hz); + cfg->set_num_channels(num_channels); + cfg->set_has_keyboard(false); + + size_t max_frame_size = ceil(sample_rate_hz / 100.f); + channels_data->resize(num_channels * max_frame_size); + std::fill(channels_data->begin(), channels_data->end(), 0.5f); + frame_data->resize(num_channels); + for (size_t channel = 0; channel < num_channels; ++channel) { + (*frame_data)[channel] = + &(*channels_data)[channel * max_frame_size]; + } + }; + + populate_audio_frame( + render_input_sample_rate_hz, render_input_num_channels, + &render_input_stream_config, &render_input_frame_channels, + &render_input_frame); + populate_audio_frame( + render_output_sample_rate_hz, render_output_num_channels, + &render_output_stream_config, &render_output_frame_channels, + &render_output_frame); + populate_audio_frame( + capture_input_sample_rate_hz, capture_input_num_channels, + &capture_input_stream_config, &capture_input_frame_channels, + &capture_input_frame); + populate_audio_frame( + capture_output_sample_rate_hz, capture_output_num_channels, + &capture_output_stream_config, &capture_output_frame_channels, + &capture_output_frame); + + for (size_t frame = 0; frame < 2; ++frame) { + SCOPED_TRACE(ProduceDebugText( + render_input_sample_rate_hz, render_output_sample_rate_hz, + capture_input_sample_rate_hz, capture_output_sample_rate_hz, + render_input_num_channels, render_output_num_channels, + render_input_num_channels, capture_output_num_channels)); + + int result = apm->ProcessReverseStream( + &render_input_frame[0], render_input_stream_config, + render_output_stream_config, &render_output_frame[0]); + EXPECT_EQ(result, AudioProcessing::kNoError); + result = apm->ProcessStream( + &capture_input_frame[0], capture_input_stream_config, + capture_output_stream_config, &capture_output_frame[0]); + EXPECT_EQ(result, AudioProcessing::kNoError); + } + } + } + } + } + } + } +} + } // namespace TEST(RuntimeSettingTest, TestDefaultCtor) { @@ -2622,4 +2744,30 @@ TEST(ApmStatistics, ReportHasVoice) { EXPECT_EQ(apm->ProcessStream(&frame), 0); EXPECT_FALSE(apm->GetStatistics(false).voice_detected); } + +TEST(ApmConfiguration, HandlingOfRateAndChannelCombinations) { + std::array sample_rates_hz = {16000, 32000, 48000}; + std::array render_channel_counts = {1, 7}; + std::array capture_channel_counts = {1, 7}; + RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts, + capture_channel_counts); +} + +TEST(ApmConfiguration, HandlingOfChannelCombinations) { + std::array sample_rates_hz = {48000}; + std::array render_channel_counts = {1, 2, 3, 4, 5, 6, 7, 8}; + std::array capture_channel_counts = {1, 2, 3, 4, 5, 6, 7, 8}; + RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts, + capture_channel_counts); +} + +TEST(ApmConfiguration, HandlingOfRateCombinations) { + std::array sample_rates_hz = {8000, 11025, 16000, 22050, 32000, + 48000, 96000, 192000, 384000}; + std::array render_channel_counts = {2}; + std::array capture_channel_counts = {2}; + RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts, + capture_channel_counts); +} + } // namespace webrtc