Make it possible to change the amplitude of the pulses generated by PulsedNoiseCapturer.

This adds a SetCapturer function to testing::FakeAudioDevice::PulsedNoiseCapturer
that can be used to update the volume of the generated audio mid-call. It also modifies
CreatePulsedNoiseCapturer to use PulsedNoiseCapturer's type directly so that its new
function is visible for the callers.

Bug: webrtc:8666
Change-Id: I47726e242ccf221f5511e2797b2954ce035ba371
Reviewed-on: https://webrtc-review.googlesource.com/34650
Reviewed-by: Patrik Höglund <phoglund@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Erik Varga <erikvarga@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21521}
This commit is contained in:
erikvarga@webrtc.org 2017-12-20 15:47:34 +01:00 committed by Commit Bot
parent 6206eef0ee
commit 9a0a17fb7a
3 changed files with 93 additions and 46 deletions

View File

@ -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<int16_t>* buffer) override {
fill_with_zero_ = !fill_with_zero_;
buffer->SetData(
test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
[&](rtc::ArrayView<int16_t> 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<int16_t>* 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<int16_t> 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::Capturer>
FakeAudioDevice::CreatePulsedNoiseCapturer(
int16_t max_amplitude, int sampling_frequency_in_hz) {
return std::unique_ptr<FakeAudioDevice::Capturer>(
std::unique_ptr<FakeAudioDevice::PulsedNoiseCapturer>
FakeAudioDevice::CreatePulsedNoiseCapturer(int16_t max_amplitude,
int sampling_frequency_in_hz) {
return std::unique_ptr<FakeAudioDevice::PulsedNoiseCapturer>(
new PulsedNoiseCapturer(max_amplitude, sampling_frequency_in_hz));
}

View File

@ -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<const int16_t> 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<int16_t>* 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<Capturer> CreatePulsedNoiseCapturer(
int16_t max_amplitude, int sampling_frequency_in_hz);
static std::unique_ptr<PulsedNoiseCapturer> 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<Capturer> CreateWavFileReader(

View File

@ -127,5 +127,31 @@ TEST(BoundedWavFileWriterTest, EndSilenceCutoff) {
RunTest(kInputSamples, kExpectedSamples, 8);
}
TEST(PulsedNoiseCapturerTest, SetMaxAmplitude) {
const int16_t kAmplitude = 50;
std::unique_ptr<FakeAudioDevice::PulsedNoiseCapturer> capturer =
FakeAudioDevice::CreatePulsedNoiseCapturer(
kAmplitude, /*sampling_frequency_in_hz=*/8000);
rtc::BufferT<int16_t> 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