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..2b5b13b71f32cfcff34cf5d753d989522f785b0b |
| --- /dev/null |
| +++ b/webrtc/modules/audio_processing/test/fake_recording_device.cc |
| @@ -0,0 +1,128 @@ |
| +/* |
| + * 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 "webrtc/base/logging.h" |
| + |
| +namespace webrtc { |
| + |
| +FakeRecordingDevice::FakeRecordingDevice(MicrophoneKind mapping_kind) |
| + : mapping_kind_(mapping_kind) { |
| + // Create the analog gain simulatory callback depending on the wanted |
| + // microphone kind. |
| + switch (mapping_kind_) { |
| + case MicrophoneKind::kIdentity: { |
| + simulator_callback_int16_ = AnalogGainSimulatorIdentityInt16(); |
|
peah-webrtc
2017/05/16 12:19:36
These are not used as callbacks, so I don't think
AleBzk
2017/05/17 11:52:23
Acknowledged.
|
| + simulator_callback_float_ = AnalogGainSimulatorIdentityFloat(); |
| + break; |
| + } |
| + case MicrophoneKind::kLinear: { |
| + simulator_callback_int16_ = AnalogGainSimulatorLinearInt16(); |
|
peah-webrtc
2017/05/16 12:19:36
I would rather have an interface with different im
AleBzk
2017/05/17 11:52:23
Perfect. Let's then go for interface + implementat
|
| + simulator_callback_float_ = AnalogGainSimulatorLinearFloat(); |
| + break; |
| + } |
| + default: { RTC_NOTREACHED(); } |
| + } |
| +} |
| + |
| +FakeRecordingDevice::~FakeRecordingDevice() = default; |
| + |
| +void FakeRecordingDevice::SimulateAnalogGain( |
| + int level, rtc::Optional<int> real_device_level, |
| + std::vector<rtc::ArrayView<float>> buffer) { |
| + for (size_t i = 0; i < buffer.size(); ++i) { |
| + std::transform( |
|
peah-webrtc
2017/05/16 12:19:35
I think std::for_each is better suited here.
AleBzk
2017/05/17 11:52:23
Acknowledged.
|
| + buffer[i].begin(), buffer[i].end(), buffer[i].begin(), |
| + [this, level, real_device_level](float x) { |
| + return simulator_callback_float_(x, level, real_device_level); |
|
peah-webrtc
2017/05/16 12:19:36
As you stated offline, this will not scale with me
AleBzk
2017/05/17 11:52:23
Acknowledged.
|
| + }); |
| + } |
| +} |
| + |
| +void FakeRecordingDevice::SimulateAnalogGain( |
|
peah-webrtc
2017/05/16 12:19:36
Why is this needed as a separate method?
AleBzk
2017/05/17 11:52:23
Please, see my answer to a related question of you
|
| + int level, rtc::Optional<int> real_device_level, |
| + ChannelBuffer<float>* buffer) { |
| + std::vector<rtc::ArrayView<float>> buffer_view; |
| + for (size_t i = 0; i < buffer->num_channels(); ++i) { |
| + buffer_view.emplace_back(buffer->channels()[i], buffer->num_frames()); |
| + } |
| + SimulateAnalogGain(level, real_device_level, buffer_view); |
| +} |
| + |
| +void FakeRecordingDevice::SimulateAnalogGain( |
| + int level, rtc::Optional<int> real_device_level, AudioFrame* buffer) { |
| + const size_t number_of_samples = |
| + buffer->samples_per_channel_ * buffer->num_channels_; |
| + RTC_DCHECK_LE(number_of_samples, AudioFrame::kMaxDataSizeSamples); |
| + std::transform( |
|
peah-webrtc
2017/05/16 12:19:36
std::for_each
AleBzk
2017/05/17 11:52:23
Acknowledged.
|
| + buffer->data_, buffer->data_ + number_of_samples, buffer->data_, |
| + [this, level, real_device_level](int16_t x) { |
| + return simulator_callback_int16_(x, level, real_device_level); |
| + }); |
| +} |
| + |
| +SimulatorCallbackInt16 FakeRecordingDevice::AnalogGainSimulatorIdentityInt16() { |
| + return [this](int16_t sample, int level, |
| + rtc::Optional<int> real_device_level) { |
| + return sample; |
| + }; |
| +} |
| + |
| +SimulatorCallbackFloat FakeRecordingDevice::AnalogGainSimulatorIdentityFloat() { |
| + return [this](float sample, int level, rtc::Optional<int> real_device_level) { |
| + return sample; |
| + }; |
| +} |
| + |
| +SimulatorCallbackInt16 FakeRecordingDevice::AnalogGainSimulatorLinearInt16() { |
| + return [this](int16_t sample, int level, |
| + rtc::Optional<int> real_device_level) { |
| + float sample_f = static_cast<float>(sample); |
| + |
| + // Virtually restore the unmodified microphone level. |
| + if (real_device_level) { |
| + RTC_DCHECK_GT(*real_device_level, 0) |
| + << "zero real device level, cannot undo mic level"; |
| + sample_f = ClipSample( |
| + sample_f * 255.0f / static_cast<float>(*real_device_level)); |
| + } |
| + |
| + // Simulate the mic gain. |
| + return ClipSample(sample_f * static_cast<float>(level) / 255.0f); |
| + }; |
| +} |
| + |
| +SimulatorCallbackFloat FakeRecordingDevice::AnalogGainSimulatorLinearFloat() { |
| + return [this](float sample, int level, rtc::Optional<int> real_device_level) { |
| + // Virtually restore the unmodified microphone level. |
| + if (real_device_level) { |
| + RTC_DCHECK_GT(*real_device_level, 0) |
| + << "zero real device level, cannot undo mic level"; |
| + sample = ClipSample( |
| + sample * 255.0f / static_cast<float>(*real_device_level)); |
| + } |
| + |
| + // Simulate the mic gain. |
| + return ClipSample(sample * static_cast<float>(level) / 255.0f); |
| + }; |
| +} |
| + |
| +int16_t FakeRecordingDevice::ClipSample(int16_t sample) { |
| + return sample < kSampleMinInt16 ? |
| + kSampleMinInt16 : (sample > kSampleMaxInt16 ? kSampleMaxInt16 : sample); |
|
peah-webrtc
2017/05/16 12:19:35
Use std::min/std::max instead
peah-webrtc
2017/05/16 12:19:36
Why do you clip the sample value to +-255?
AleBzk
2017/05/17 11:52:23
Done.
AleBzk
2017/05/17 11:52:23
Right, I got confused with the mic level.
|
| +} |
| + |
| +float FakeRecordingDevice::ClipSample(float sample) { |
| + return sample < kSampleMinFloat ? |
|
peah-webrtc
2017/05/16 12:19:36
Use std::min/std::max instead
AleBzk
2017/05/17 11:52:23
Done.
|
| + kSampleMinFloat : (sample > kSampleMaxFloat ? kSampleMaxFloat : sample); |
| +} |
| + |
| +} // namespace webrtc |