| Index: webrtc/modules/audio_processing/test/fake_recording_device.cc
|
| diff --git a/webrtc/modules/audio_processing/test/fake_recording_device.cc b/webrtc/modules/audio_processing/test/fake_recording_device.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..67ba34a3901e4b5fcd296683d8612625f8b9fbed
|
| --- /dev/null
|
| +++ b/webrtc/modules/audio_processing/test/fake_recording_device.cc
|
| @@ -0,0 +1,165 @@
|
| +/*
|
| + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/modules/audio_processing/test/fake_recording_device.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "webrtc/rtc_base/logging.h"
|
| +#include "webrtc/rtc_base/ptr_util.h"
|
| +
|
| +namespace webrtc {
|
| +namespace test {
|
| +
|
| +namespace {
|
| +
|
| +constexpr int16_t kInt16SampleMin = -32768;
|
| +constexpr int16_t kInt16SampleMax = 32767;
|
| +constexpr float kFloatSampleMin = -32768.f;
|
| +constexpr float kFloatSampleMax = 32767.0f;
|
| +
|
| +} // namespace
|
| +
|
| +// Abstract class for the different fake recording devices.
|
| +class FakeRecordingDeviceWorker {
|
| + public:
|
| + explicit FakeRecordingDeviceWorker(const int initial_mic_level)
|
| + : mic_level_(initial_mic_level) {}
|
| + int mic_level() const { return mic_level_; }
|
| + void set_mic_level(const int level) { mic_level_ = level; }
|
| + void set_undo_mic_level(const rtc::Optional<int> level) {
|
| + undo_mic_level_ = level;
|
| + }
|
| + virtual ~FakeRecordingDeviceWorker() = default;
|
| + virtual void ModifyBufferInt16(AudioFrame* buffer) = 0;
|
| + virtual void ModifyBufferFloat(ChannelBuffer<float>* buffer) = 0;
|
| +
|
| + protected:
|
| + // Mic level to simulate.
|
| + int mic_level_;
|
| + // Optional mic level to undo.
|
| + rtc::Optional<int> undo_mic_level_;
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +// Identity fake recording device. The samples are not modified, which is
|
| +// equivalent to a constant gain curve at 1.0 - only used for testing.
|
| +class FakeRecordingDeviceIdentity final : public FakeRecordingDeviceWorker {
|
| + public:
|
| + explicit FakeRecordingDeviceIdentity(const int initial_mic_level)
|
| + : FakeRecordingDeviceWorker(initial_mic_level) {}
|
| + ~FakeRecordingDeviceIdentity() override = default;
|
| + void ModifyBufferInt16(AudioFrame* buffer) override {}
|
| + void ModifyBufferFloat(ChannelBuffer<float>* buffer) override {}
|
| +};
|
| +
|
| +// Linear fake recording device. The gain curve is a linear function mapping the
|
| +// mic levels range [0, 255] to [0.0, 1.0].
|
| +class FakeRecordingDeviceLinear final : public FakeRecordingDeviceWorker {
|
| + public:
|
| + explicit FakeRecordingDeviceLinear(const int initial_mic_level)
|
| + : FakeRecordingDeviceWorker(initial_mic_level) {}
|
| + ~FakeRecordingDeviceLinear() override = default;
|
| + void ModifyBufferInt16(AudioFrame* buffer) override {
|
| + const size_t number_of_samples =
|
| + buffer->samples_per_channel_ * buffer->num_channels_;
|
| + RTC_DCHECK_LE(number_of_samples, AudioFrame::kMaxDataSizeSamples);
|
| + int16_t* data = buffer->mutable_data();
|
| + for (size_t i = 0; i < number_of_samples; ++i) {
|
| + const float sample_f = data[i];
|
| + if (undo_mic_level_ && *undo_mic_level_ > 0) {
|
| + // Virtually restore the unmodified microphone level.
|
| + data[i] = std::max(kInt16SampleMin,
|
| + std::min(kInt16SampleMax,
|
| + static_cast<int16_t>(sample_f * mic_level_ /
|
| + *undo_mic_level_)));
|
| + } else {
|
| + // Simulate the mic gain only.
|
| + data[i] = std::max(
|
| + kInt16SampleMin,
|
| + std::min(kInt16SampleMax,
|
| + static_cast<int16_t>(sample_f * mic_level_ / 255.0f)));
|
| + }
|
| + }
|
| + }
|
| + void ModifyBufferFloat(ChannelBuffer<float>* buffer) override {
|
| + for (size_t c = 0; c < buffer->num_channels(); ++c) {
|
| + for (size_t i = 0; i < buffer->num_frames(); ++i) {
|
| + if (undo_mic_level_ && *undo_mic_level_ > 0) {
|
| + // Virtually restore the unmodified microphone level.
|
| + buffer->channels()[c][i] = std::max(
|
| + kFloatSampleMin,
|
| + std::min(kFloatSampleMax, buffer->channels()[c][i] * mic_level_ /
|
| + *undo_mic_level_));
|
| + } else {
|
| + // Simulate the mic gain only.
|
| + buffer->channels()[c][i] =
|
| + std::max(kFloatSampleMin,
|
| + std::min(kFloatSampleMax, buffer->channels()[c][i] *
|
| + mic_level_ / 255.0f));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +FakeRecordingDevice::FakeRecordingDevice(int initial_mic_level,
|
| + int device_kind) {
|
| + switch (device_kind) {
|
| + case 0:
|
| + worker_ = rtc::MakeUnique<FakeRecordingDeviceIdentity>(initial_mic_level);
|
| + break;
|
| + case 1:
|
| + worker_ = rtc::MakeUnique<FakeRecordingDeviceLinear>(initial_mic_level);
|
| + break;
|
| + default:
|
| + RTC_NOTREACHED();
|
| + break;
|
| + }
|
| +}
|
| +
|
| +FakeRecordingDevice::~FakeRecordingDevice() = default;
|
| +
|
| +int FakeRecordingDevice::MicLevel() const {
|
| + RTC_DCHECK(worker_);
|
| + return worker_->mic_level();
|
| +}
|
| +
|
| +void FakeRecordingDevice::SetMicLevel(const int level) {
|
| + RTC_DCHECK(worker_);
|
| + if (level != worker_->mic_level())
|
| + LOG(LS_INFO) << "simulate mic level update: " << level;
|
| + worker_->set_mic_level(level);
|
| +}
|
| +
|
| +void FakeRecordingDevice::SetUndoMicLevel(const rtc::Optional<int> level) {
|
| + RTC_DCHECK(worker_);
|
| + // TODO(alessiob): The behavior with undo level equal to zero is not clear yet
|
| + // and will be defined in future CLs once more FakeRecordingDeviceWorker
|
| + // implementations need to be added.
|
| + RTC_CHECK(!level || *level > 0) << "Zero undo mic level is unsupported";
|
| + worker_->set_undo_mic_level(level);
|
| +}
|
| +
|
| +void FakeRecordingDevice::SimulateAnalogGain(AudioFrame* buffer) {
|
| + RTC_DCHECK(worker_);
|
| + worker_->ModifyBufferInt16(buffer);
|
| +}
|
| +
|
| +void FakeRecordingDevice::SimulateAnalogGain(ChannelBuffer<float>* buffer) {
|
| + RTC_DCHECK(worker_);
|
| + worker_->ModifyBufferFloat(buffer);
|
| +}
|
| +
|
| +} // namespace test
|
| +} // namespace webrtc
|
|
|