diff --git a/test/fake_audio_device.cc b/test/fake_audio_device.cc index eef8bfd015..8e640366cf 100644 --- a/test/fake_audio_device.cc +++ b/test/fake_audio_device.cc @@ -15,7 +15,6 @@ #include "common_audio/wav_file.h" #include "rtc_base/checks.h" -#include "rtc_base/random.h" #include "system_wrappers/include/event_wrapper.h" namespace webrtc { @@ -25,45 +24,6 @@ namespace { constexpr int kFrameLengthMs = 10; constexpr int kFramesPerSecond = 1000 / kFrameLengthMs; -// Assuming 10ms audio packets.. -class PulsedNoiseCapturer final : public test::FakeAudioDevice::Capturer { - public: - PulsedNoiseCapturer(int16_t max_amplitude, int sampling_frequency_in_hz) - : sampling_frequency_in_hz_(sampling_frequency_in_hz), - fill_with_zero_(false), - random_generator_(1), - max_amplitude_(max_amplitude) { - RTC_DCHECK_GT(max_amplitude, 0); - } - - int SamplingFrequency() const override { - return sampling_frequency_in_hz_; - } - - bool Capture(rtc::BufferT* buffer) override { - fill_with_zero_ = !fill_with_zero_; - buffer->SetData( - test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_), - [&](rtc::ArrayView data) { - if (fill_with_zero_) { - std::fill(data.begin(), data.end(), 0); - } else { - std::generate(data.begin(), data.end(), [&]() { - return random_generator_.Rand(-max_amplitude_, max_amplitude_); - }); - } - return data.size(); - }); - return true; - } - - private: - int sampling_frequency_in_hz_; - bool fill_with_zero_; - Random random_generator_; - const int16_t max_amplitude_; -}; - class WavFileReader final : public test::FakeAudioDevice::Capturer { public: WavFileReader(std::string filename, int sampling_frequency_in_hz) @@ -194,14 +154,53 @@ class DiscardRenderer final : public test::FakeAudioDevice::Renderer { } // namespace namespace test { +// Assuming 10ms audio packets. +FakeAudioDevice::PulsedNoiseCapturer::PulsedNoiseCapturer( + int16_t max_amplitude, + int sampling_frequency_in_hz) + : sampling_frequency_in_hz_(sampling_frequency_in_hz), + fill_with_zero_(false), + random_generator_(1), + max_amplitude_(max_amplitude) { + RTC_DCHECK_GT(max_amplitude, 0); +} + +bool FakeAudioDevice::PulsedNoiseCapturer::Capture( + rtc::BufferT* buffer) { + fill_with_zero_ = !fill_with_zero_; + int16_t max_amplitude; + { + rtc::CritScope cs(&lock_); + max_amplitude = max_amplitude_; + } + buffer->SetData(FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_), + [&](rtc::ArrayView data) { + if (fill_with_zero_) { + std::fill(data.begin(), data.end(), 0); + } else { + std::generate(data.begin(), data.end(), [&]() { + return random_generator_.Rand(-max_amplitude, + max_amplitude); + }); + } + return data.size(); + }); + return true; +} + +void FakeAudioDevice::PulsedNoiseCapturer::SetMaxAmplitude(int16_t amplitude) { + rtc::CritScope cs(&lock_); + max_amplitude_ = amplitude; +} + size_t FakeAudioDevice::SamplesPerFrame(int sampling_frequency_in_hz) { return rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond); } -std::unique_ptr - FakeAudioDevice::CreatePulsedNoiseCapturer( - int16_t max_amplitude, int sampling_frequency_in_hz) { - return std::unique_ptr( +std::unique_ptr +FakeAudioDevice::CreatePulsedNoiseCapturer(int16_t max_amplitude, + int sampling_frequency_in_hz) { + return std::unique_ptr( new PulsedNoiseCapturer(max_amplitude, sampling_frequency_in_hz)); } diff --git a/test/fake_audio_device.h b/test/fake_audio_device.h index f71fd016d9..0cc44f0c8d 100644 --- a/test/fake_audio_device.h +++ b/test/fake_audio_device.h @@ -20,6 +20,7 @@ #include "rtc_base/criticalsection.h" #include "rtc_base/event.h" #include "rtc_base/platform_thread.h" +#include "rtc_base/random.h" #include "typedefs.h" // NOLINT(build/include) namespace webrtc { @@ -59,6 +60,26 @@ class FakeAudioDevice : public FakeAudioDeviceModule { virtual bool Render(rtc::ArrayView data) = 0; }; + // A fake capturer that generates pulses with random samples between + // -max_amplitude and +max_amplitude. + class PulsedNoiseCapturer final : public Capturer { + public: + PulsedNoiseCapturer(int16_t max_amplitude, int sampling_frequency_in_hz); + + int SamplingFrequency() const override { return sampling_frequency_in_hz_; } + + bool Capture(rtc::BufferT* buffer) override; + + void SetMaxAmplitude(int16_t amplitude); + + private: + int sampling_frequency_in_hz_; + bool fill_with_zero_; + Random random_generator_; + rtc::CriticalSection lock_; + int16_t max_amplitude_ RTC_GUARDED_BY(lock_); + }; + // Creates a new FakeAudioDevice. When capturing or playing, 10 ms audio // frames will be processed every 10ms / |speed|. // |capturer| is an object that produces audio data. Can be nullptr if this @@ -74,8 +95,9 @@ class FakeAudioDevice : public FakeAudioDeviceModule { // Returns a Capturer instance that generates a signal where every second // frame is zero and every second frame is evenly distributed random noise // with max amplitude |max_amplitude|. - static std::unique_ptr CreatePulsedNoiseCapturer( - int16_t max_amplitude, int sampling_frequency_in_hz); + static std::unique_ptr CreatePulsedNoiseCapturer( + int16_t max_amplitude, + int sampling_frequency_in_hz); // Returns a Capturer instance that gets its data from a file. static std::unique_ptr CreateWavFileReader( diff --git a/test/fake_audio_device_unittest.cc b/test/fake_audio_device_unittest.cc index 02ece3cd85..1529deaa97 100644 --- a/test/fake_audio_device_unittest.cc +++ b/test/fake_audio_device_unittest.cc @@ -127,5 +127,31 @@ TEST(BoundedWavFileWriterTest, EndSilenceCutoff) { RunTest(kInputSamples, kExpectedSamples, 8); } +TEST(PulsedNoiseCapturerTest, SetMaxAmplitude) { + const int16_t kAmplitude = 50; + std::unique_ptr capturer = + FakeAudioDevice::CreatePulsedNoiseCapturer( + kAmplitude, /*sampling_frequency_in_hz=*/8000); + rtc::BufferT recording_buffer; + + // Verify that the capturer doesn't create entries louder than than + // kAmplitude. Since the pulse generator alternates between writing + // zeroes and actual entries, we need to do the capturing twice. + capturer->Capture(&recording_buffer); + capturer->Capture(&recording_buffer); + int16_t max_sample = + *std::max_element(recording_buffer.begin(), recording_buffer.end()); + EXPECT_LE(max_sample, kAmplitude); + + // Increase the amplitude and verify that the samples can now be louder + // than the previous max. + capturer->SetMaxAmplitude(kAmplitude * 2); + capturer->Capture(&recording_buffer); + capturer->Capture(&recording_buffer); + max_sample = + *std::max_element(recording_buffer.begin(), recording_buffer.end()); + EXPECT_GT(max_sample, kAmplitude); +} + } // namespace test } // namespace webrtc