OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/audio_processing/test/fake_recording_device.h" | |
12 | |
13 #include <algorithm> | |
14 | |
15 #include "webrtc/base/logging.h" | |
16 #include "webrtc/base/ptr_util.h" | |
17 | |
18 namespace webrtc { | |
19 namespace test { | |
20 | |
21 namespace { | |
22 | |
23 constexpr int16_t kInt16SampleMin = -32768; | |
24 constexpr int16_t kInt16SampleMax = 32767; | |
25 constexpr float kFloatSampleMin = -1.0f; | |
26 constexpr float kFloatSampleMax = 1.0f; | |
27 | |
28 int16_t ClipSampleFloatToInt16(float sample) { | |
29 return std::max(std::min(sample, static_cast<float>(kInt16SampleMax)), | |
30 static_cast<float>(kInt16SampleMin)); | |
31 } | |
32 | |
33 float ClipSampleFloatToFloat(float sample) { | |
34 return std::max(std::min(sample, kFloatSampleMax), kFloatSampleMin); | |
35 } | |
AleBzk
2017/07/26 13:42:30
Removed since these functions may confuse the read
| |
36 | |
37 } // namespace | |
38 | |
39 // Abstract class for the different fake recording devices. | |
40 class FakeRecordingDeviceWorker { | |
41 public: | |
42 FakeRecordingDeviceWorker(const int& mic_level, | |
43 const rtc::Optional<int>& undo_mic_level) | |
44 : mic_level_(mic_level), undo_mic_level_(undo_mic_level) {} | |
45 virtual ~FakeRecordingDeviceWorker() = default; | |
46 virtual void ModifyBufferInt16(AudioFrame* buffer) = 0; | |
47 virtual void ModifyBufferFloat(ChannelBuffer<float>* buffer) = 0; | |
48 | |
49 protected: | |
50 const int& mic_level_; | |
51 const rtc::Optional<int>& undo_mic_level_; | |
52 }; | |
53 | |
54 namespace { | |
55 | |
56 // Identity fake recording device. The samples are not modified, which is | |
57 // equivalent to a constant gain curve at 1.0 - only used for testing. | |
58 class FakeRecordingDeviceIdentity final : public FakeRecordingDeviceWorker { | |
59 public: | |
60 FakeRecordingDeviceIdentity(const int& mic_level, | |
61 const rtc::Optional<int>& undo_mic_level) | |
62 : FakeRecordingDeviceWorker(mic_level, undo_mic_level) {} | |
63 ~FakeRecordingDeviceIdentity() override = default; | |
64 void ModifyBufferInt16(AudioFrame* buffer) override {} | |
65 void ModifyBufferFloat(ChannelBuffer<float>* buffer) override {} | |
66 }; | |
67 | |
68 // Linear fake recording device. The gain curve is a linear function mapping the | |
69 // mic levels range [0, 255] to [0.0, 1.0]. | |
70 class FakeRecordingDeviceLinear final : public FakeRecordingDeviceWorker { | |
71 public: | |
72 FakeRecordingDeviceLinear(const int& mic_level, | |
73 const rtc::Optional<int>& undo_mic_level) | |
74 : FakeRecordingDeviceWorker(mic_level, undo_mic_level) {} | |
75 ~FakeRecordingDeviceLinear() override = default; | |
76 void ModifyBufferInt16(AudioFrame* buffer) override { | |
77 const size_t number_of_samples = | |
78 buffer->samples_per_channel_ * buffer->num_channels_; | |
79 RTC_DCHECK_LE(number_of_samples, AudioFrame::kMaxDataSizeSamples); | |
80 int16_t* data = buffer->mutable_data(); | |
81 for (size_t i = 0; i < number_of_samples; ++i) { | |
82 const float sample_f = data[i]; | |
83 if (undo_mic_level_ && *undo_mic_level_ > 0) { | |
84 // Virtually restore the unmodified microphone level. | |
85 data[i] = | |
86 ClipSampleFloatToInt16(sample_f * mic_level_ / *undo_mic_level_); | |
87 } else { | |
88 // Simulate the mic gain only. | |
89 data[i] = ClipSampleFloatToInt16(sample_f * mic_level_ / 255.0f); | |
90 } | |
91 } | |
92 } | |
93 void ModifyBufferFloat(ChannelBuffer<float>* buffer) override { | |
94 for (size_t c = 0; c < buffer->num_channels(); ++c) { | |
95 for (size_t i = 0; i < buffer->num_frames(); ++i) { | |
96 if (undo_mic_level_ && *undo_mic_level_ > 0) { | |
97 // Virtually restore the unmodified microphone level. | |
98 buffer->channels()[c][i] = ClipSampleFloatToFloat( | |
99 buffer->channels()[c][i] * mic_level_ / *undo_mic_level_); | |
100 } else { | |
101 // Simulate the mic gain only. | |
102 buffer->channels()[c][i] = ClipSampleFloatToFloat( | |
103 buffer->channels()[c][i] * mic_level_ / 255.0f); | |
104 } | |
105 } | |
106 } | |
107 } | |
108 }; | |
109 | |
110 } // namespace | |
111 | |
112 FakeRecordingDevice::FakeRecordingDevice(int initial_mic_level, DeviceKind kind) | |
peah-webrtc
2017/06/29 22:04:00
Having seen the usage of the constructor, I defini
| |
113 : mic_level_(initial_mic_level) { | |
114 switch (kind) { | |
115 case FakeRecordingDevice::DeviceKind::IDENTITY: | |
116 worker_ = rtc::MakeUnique<FakeRecordingDeviceIdentity>(mic_level_, | |
117 undo_mic_level_); | |
118 break; | |
119 case FakeRecordingDevice::DeviceKind::LINEAR: | |
120 worker_ = rtc::MakeUnique<FakeRecordingDeviceLinear>(mic_level_, | |
121 undo_mic_level_); | |
122 break; | |
123 default: | |
124 RTC_NOTREACHED(); | |
125 break; | |
126 } | |
127 } | |
128 | |
129 FakeRecordingDevice::~FakeRecordingDevice() = default; | |
130 | |
131 void FakeRecordingDevice::SimulateAnalogGain(AudioFrame* buffer) { | |
132 RTC_DCHECK(worker_); | |
133 worker_->ModifyBufferInt16(buffer); | |
134 } | |
135 | |
136 void FakeRecordingDevice::SimulateAnalogGain(ChannelBuffer<float>* buffer) { | |
137 RTC_DCHECK(worker_); | |
138 worker_->ModifyBufferFloat(buffer); | |
139 } | |
140 | |
141 } // namespace test | |
142 } // namespace webrtc | |
OLD | NEW |