Chromium Code Reviews| 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..599ce6ab875ac1ed325758998d2448f66e279439 |
| --- /dev/null |
| +++ b/webrtc/modules/audio_processing/test/fake_recording_device.cc |
| @@ -0,0 +1,142 @@ |
| +/* |
| + * 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/base/logging.h" |
| +#include "webrtc/base/ptr_util.h" |
| + |
| +namespace webrtc { |
| +namespace test { |
| + |
| +namespace { |
| + |
| +constexpr int16_t kInt16SampleMin = -32768; |
| +constexpr int16_t kInt16SampleMax = 32767; |
| +constexpr float kFloatSampleMin = -1.0f; |
|
peah-webrtc
2017/08/18 04:27:00
The range for the float values inside APM is [-327
|
| +constexpr float kFloatSampleMax = 1.0f; |
| + |
| +} // namespace |
| + |
| +// Abstract class for the different fake recording devices. |
| +class FakeRecordingDeviceWorker { |
| + public: |
| + FakeRecordingDeviceWorker(const int& mic_level, |
| + const rtc::Optional<int>& undo_mic_level) |
| + : mic_level_(mic_level), undo_mic_level_(undo_mic_level) {} |
| + virtual ~FakeRecordingDeviceWorker() = default; |
| + virtual void ModifyBufferInt16(AudioFrame* buffer) = 0; |
| + virtual void ModifyBufferFloat(ChannelBuffer<float>* buffer) = 0; |
| + |
| + protected: |
| + const int& mic_level_; |
| + const rtc::Optional<int>& undo_mic_level_; |
|
peah-webrtc
2017/08/18 04:27:00
As discussed offline, please remove this as a refe
|
| +}; |
| + |
| +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: |
| + FakeRecordingDeviceIdentity(const int& mic_level, |
| + const rtc::Optional<int>& undo_mic_level) |
| + : FakeRecordingDeviceWorker(mic_level, undo_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]. |
|
peah-webrtc
2017/08/18 04:27:00
Since you specify the allowed range for the mic le
|
| +class FakeRecordingDeviceLinear final : public FakeRecordingDeviceWorker { |
| + public: |
| + FakeRecordingDeviceLinear(const int& mic_level, |
| + const rtc::Optional<int>& undo_mic_level) |
| + : FakeRecordingDeviceWorker(mic_level, undo_mic_level) {} |
| + ~FakeRecordingDeviceLinear() override = default; |
| + void ModifyBufferInt16(AudioFrame* buffer) override { |
|
peah-webrtc
2017/08/18 04:27:00
Since you add implementations within the class def
|
| + 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) { |
|
peah-webrtc
2017/08/18 04:27:00
Regarding *undo_mic_level_ > 0, please see comment
|
| + // 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) { |
|
peah-webrtc
2017/08/18 04:27:00
why do you need to check for *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) |
| + : mic_level_(initial_mic_level) { |
| + switch (device_kind) { |
| + case 0: |
| + worker_ = rtc::MakeUnique<FakeRecordingDeviceIdentity>(mic_level_, |
| + undo_mic_level_); |
| + break; |
| + case 1: |
| + worker_ = rtc::MakeUnique<FakeRecordingDeviceLinear>(mic_level_, |
| + undo_mic_level_); |
| + break; |
| + default: |
| + RTC_NOTREACHED(); |
| + break; |
| + } |
| +} |
| + |
| +FakeRecordingDevice::~FakeRecordingDevice() = default; |
| + |
| +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 |