1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include <memory>
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/audio_buffer.h"
14*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/gain_control_impl.h"
15*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_minmax.h"
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h"
18*d9f75844SAndroid Build Coastguard Worker #include "test/fuzzers/fuzz_data_helper.h"
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
21*d9f75844SAndroid Build Coastguard Worker namespace {
22*d9f75844SAndroid Build Coastguard Worker
FillAudioBuffer(size_t sample_rate_hz,test::FuzzDataHelper * fuzz_data,AudioBuffer * buffer)23*d9f75844SAndroid Build Coastguard Worker void FillAudioBuffer(size_t sample_rate_hz,
24*d9f75844SAndroid Build Coastguard Worker test::FuzzDataHelper* fuzz_data,
25*d9f75844SAndroid Build Coastguard Worker AudioBuffer* buffer) {
26*d9f75844SAndroid Build Coastguard Worker float* const* channels = buffer->channels_f();
27*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < buffer->num_channels(); ++i) {
28*d9f75844SAndroid Build Coastguard Worker for (size_t j = 0; j < buffer->num_frames(); ++j) {
29*d9f75844SAndroid Build Coastguard Worker channels[i][j] =
30*d9f75844SAndroid Build Coastguard Worker static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0));
31*d9f75844SAndroid Build Coastguard Worker }
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker if (sample_rate_hz != 16000) {
35*d9f75844SAndroid Build Coastguard Worker buffer->SplitIntoFrequencyBands();
36*d9f75844SAndroid Build Coastguard Worker }
37*d9f75844SAndroid Build Coastguard Worker }
38*d9f75844SAndroid Build Coastguard Worker
39*d9f75844SAndroid Build Coastguard Worker // This function calls the GainControl functions that are overriden as private
40*d9f75844SAndroid Build Coastguard Worker // in GainControlInterface.
FuzzGainControllerConfig(test::FuzzDataHelper * fuzz_data,GainControl * gc)41*d9f75844SAndroid Build Coastguard Worker void FuzzGainControllerConfig(test::FuzzDataHelper* fuzz_data,
42*d9f75844SAndroid Build Coastguard Worker GainControl* gc) {
43*d9f75844SAndroid Build Coastguard Worker GainControl::Mode modes[] = {GainControl::Mode::kAdaptiveAnalog,
44*d9f75844SAndroid Build Coastguard Worker GainControl::Mode::kAdaptiveDigital,
45*d9f75844SAndroid Build Coastguard Worker GainControl::Mode::kFixedDigital};
46*d9f75844SAndroid Build Coastguard Worker GainControl::Mode mode = fuzz_data->SelectOneOf(modes);
47*d9f75844SAndroid Build Coastguard Worker const bool enable_limiter = fuzz_data->ReadOrDefaultValue(true);
48*d9f75844SAndroid Build Coastguard Worker // The values are capped to comply with the API of webrtc::GainControl.
49*d9f75844SAndroid Build Coastguard Worker const int analog_level_min =
50*d9f75844SAndroid Build Coastguard Worker rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(0), 0, 65534);
51*d9f75844SAndroid Build Coastguard Worker const int analog_level_max =
52*d9f75844SAndroid Build Coastguard Worker rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(65535),
53*d9f75844SAndroid Build Coastguard Worker analog_level_min + 1, 65535);
54*d9f75844SAndroid Build Coastguard Worker const int stream_analog_level =
55*d9f75844SAndroid Build Coastguard Worker rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(30000),
56*d9f75844SAndroid Build Coastguard Worker analog_level_min, analog_level_max);
57*d9f75844SAndroid Build Coastguard Worker const int gain =
58*d9f75844SAndroid Build Coastguard Worker rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(30), -1, 100);
59*d9f75844SAndroid Build Coastguard Worker const int target_level_dbfs =
60*d9f75844SAndroid Build Coastguard Worker rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(15), -1, 35);
61*d9f75844SAndroid Build Coastguard Worker
62*d9f75844SAndroid Build Coastguard Worker gc->set_mode(mode);
63*d9f75844SAndroid Build Coastguard Worker gc->enable_limiter(enable_limiter);
64*d9f75844SAndroid Build Coastguard Worker if (mode == GainControl::Mode::kAdaptiveAnalog) {
65*d9f75844SAndroid Build Coastguard Worker gc->set_analog_level_limits(analog_level_min, analog_level_max);
66*d9f75844SAndroid Build Coastguard Worker gc->set_stream_analog_level(stream_analog_level);
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker gc->set_compression_gain_db(gain);
69*d9f75844SAndroid Build Coastguard Worker gc->set_target_level_dbfs(target_level_dbfs);
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->mode());
72*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->analog_level_minimum());
73*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->analog_level_maximum());
74*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->stream_analog_level());
75*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->compression_gain_db());
76*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->stream_is_saturated());
77*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->target_level_dbfs());
78*d9f75844SAndroid Build Coastguard Worker static_cast<void>(gc->is_limiter_enabled());
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker
FuzzGainController(test::FuzzDataHelper * fuzz_data,GainControlImpl * gci)81*d9f75844SAndroid Build Coastguard Worker void FuzzGainController(test::FuzzDataHelper* fuzz_data, GainControlImpl* gci) {
82*d9f75844SAndroid Build Coastguard Worker using Rate = ::webrtc::AudioProcessing::NativeRate;
83*d9f75844SAndroid Build Coastguard Worker const Rate rate_kinds[] = {Rate::kSampleRate16kHz, Rate::kSampleRate32kHz,
84*d9f75844SAndroid Build Coastguard Worker Rate::kSampleRate48kHz};
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker const auto sample_rate_hz =
87*d9f75844SAndroid Build Coastguard Worker static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
88*d9f75844SAndroid Build Coastguard Worker const size_t samples_per_frame = sample_rate_hz / 100;
89*d9f75844SAndroid Build Coastguard Worker const size_t num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
90*d9f75844SAndroid Build Coastguard Worker
91*d9f75844SAndroid Build Coastguard Worker gci->Initialize(num_channels, sample_rate_hz);
92*d9f75844SAndroid Build Coastguard Worker FuzzGainControllerConfig(fuzz_data, gci);
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker // The audio buffer is used for both capture and render.
95*d9f75844SAndroid Build Coastguard Worker AudioBuffer audio(sample_rate_hz, num_channels, sample_rate_hz,
96*d9f75844SAndroid Build Coastguard Worker num_channels, sample_rate_hz, num_channels);
97*d9f75844SAndroid Build Coastguard Worker
98*d9f75844SAndroid Build Coastguard Worker std::vector<int16_t> packed_render_audio(samples_per_frame);
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker while (fuzz_data->CanReadBytes(1)) {
101*d9f75844SAndroid Build Coastguard Worker FillAudioBuffer(sample_rate_hz, fuzz_data, &audio);
102*d9f75844SAndroid Build Coastguard Worker
103*d9f75844SAndroid Build Coastguard Worker const bool stream_has_echo = fuzz_data->ReadOrDefaultValue(true);
104*d9f75844SAndroid Build Coastguard Worker gci->AnalyzeCaptureAudio(audio);
105*d9f75844SAndroid Build Coastguard Worker gci->ProcessCaptureAudio(&audio, stream_has_echo);
106*d9f75844SAndroid Build Coastguard Worker
107*d9f75844SAndroid Build Coastguard Worker FillAudioBuffer(sample_rate_hz, fuzz_data, &audio);
108*d9f75844SAndroid Build Coastguard Worker
109*d9f75844SAndroid Build Coastguard Worker gci->PackRenderAudioBuffer(audio, &packed_render_audio);
110*d9f75844SAndroid Build Coastguard Worker gci->ProcessRenderAudio(packed_render_audio);
111*d9f75844SAndroid Build Coastguard Worker }
112*d9f75844SAndroid Build Coastguard Worker }
113*d9f75844SAndroid Build Coastguard Worker
114*d9f75844SAndroid Build Coastguard Worker } // namespace
115*d9f75844SAndroid Build Coastguard Worker
FuzzOneInput(const uint8_t * data,size_t size)116*d9f75844SAndroid Build Coastguard Worker void FuzzOneInput(const uint8_t* data, size_t size) {
117*d9f75844SAndroid Build Coastguard Worker if (size > 200000) {
118*d9f75844SAndroid Build Coastguard Worker return;
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker test::FuzzDataHelper fuzz_data(rtc::ArrayView<const uint8_t>(data, size));
121*d9f75844SAndroid Build Coastguard Worker auto gci = std::make_unique<GainControlImpl>();
122*d9f75844SAndroid Build Coastguard Worker FuzzGainController(&fuzz_data, gci.get());
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
125