blob: 4d97a2df23d21e7055c4bac1e5458ff592eff46a [file] [log] [blame]
Sam Zackrissonf341f3f2018-06-21 14:09:16 +02001/*
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
Mirko Bonadei317a1f02019-09-17 17:06:18 +020011#include <memory>
12
Sam Zackrissonf341f3f2018-06-21 14:09:16 +020013#include "modules/audio_processing/audio_buffer.h"
14#include "modules/audio_processing/gain_control_impl.h"
15#include "modules/audio_processing/include/audio_processing.h"
16#include "rtc_base/numerics/safe_minmax.h"
Sam Zackrissonf341f3f2018-06-21 14:09:16 +020017#include "rtc_base/thread_annotations.h"
18#include "test/fuzzers/fuzz_data_helper.h"
19
20namespace webrtc {
21namespace {
22
23void FillAudioBuffer(test::FuzzDataHelper* fuzz_data, AudioBuffer* buffer) {
24 float* const* channels = buffer->channels_f();
25 for (size_t i = 0; i < buffer->num_channels(); ++i) {
26 for (size_t j = 0; j < buffer->num_frames(); ++j) {
27 channels[i][j] =
28 static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0));
29 }
30 }
31}
32
33// This function calls the GainControl functions that are overriden as private
34// in GainControlInterface.
35void FuzzGainControllerConfig(test::FuzzDataHelper* fuzz_data,
36 GainControl* gc) {
37 GainControl::Mode modes[] = {GainControl::Mode::kAdaptiveAnalog,
38 GainControl::Mode::kAdaptiveDigital,
39 GainControl::Mode::kFixedDigital};
40 GainControl::Mode mode = fuzz_data->SelectOneOf(modes);
41 const bool enable_limiter = fuzz_data->ReadOrDefaultValue(true);
42 // The values are capped to comply with the API of webrtc::GainControl.
43 const int analog_level_min =
44 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(0), 0, 65534);
45 const int analog_level_max =
46 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(65535),
47 analog_level_min + 1, 65535);
48 const int stream_analog_level =
49 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(30000),
50 analog_level_min, analog_level_max);
51 const int gain =
52 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(30), -1, 100);
53 const int target_level_dbfs =
54 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(15), -1, 35);
55
56 gc->set_mode(mode);
57 gc->enable_limiter(enable_limiter);
58 if (mode == GainControl::Mode::kAdaptiveAnalog) {
59 gc->set_analog_level_limits(analog_level_min, analog_level_max);
60 gc->set_stream_analog_level(stream_analog_level);
61 }
62 gc->set_compression_gain_db(gain);
63 gc->set_target_level_dbfs(target_level_dbfs);
64 gc->Enable(true);
65
66 static_cast<void>(gc->is_enabled());
67 static_cast<void>(gc->mode());
68 static_cast<void>(gc->analog_level_minimum());
69 static_cast<void>(gc->analog_level_maximum());
70 static_cast<void>(gc->stream_analog_level());
71 static_cast<void>(gc->compression_gain_db());
72 static_cast<void>(gc->stream_is_saturated());
73 static_cast<void>(gc->target_level_dbfs());
74 static_cast<void>(gc->is_limiter_enabled());
75}
76
77void FuzzGainController(test::FuzzDataHelper* fuzz_data, GainControlImpl* gci) {
78 using Rate = ::webrtc::AudioProcessing::NativeRate;
79 const Rate rate_kinds[] = {Rate::kSampleRate8kHz, Rate::kSampleRate16kHz,
80 Rate::kSampleRate32kHz, Rate::kSampleRate48kHz};
81
82 const auto sample_rate_hz =
83 static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
84 const size_t samples_per_frame = sample_rate_hz / 100;
Mirko Bonadei1e915512019-09-30 15:59:35 +020085 const size_t num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
Sam Zackrissonf341f3f2018-06-21 14:09:16 +020086
87 gci->Initialize(num_channels, sample_rate_hz);
88 FuzzGainControllerConfig(fuzz_data, gci);
89
90 // The audio buffer is used for both capture and render.
91 AudioBuffer audio(samples_per_frame, num_channels, samples_per_frame,
92 num_channels, samples_per_frame);
93
94 std::vector<int16_t> packed_render_audio(samples_per_frame);
95
96 while (fuzz_data->CanReadBytes(1)) {
97 FillAudioBuffer(fuzz_data, &audio);
98
99 const bool stream_has_echo = fuzz_data->ReadOrDefaultValue(true);
100 gci->AnalyzeCaptureAudio(&audio);
101 gci->ProcessCaptureAudio(&audio, stream_has_echo);
102
103 FillAudioBuffer(fuzz_data, &audio);
104
105 gci->PackRenderAudioBuffer(&audio, &packed_render_audio);
106 gci->ProcessRenderAudio(packed_render_audio);
107 }
108}
109
110} // namespace
111
112void FuzzOneInput(const uint8_t* data, size_t size) {
Sam Zackrisson26204702018-10-25 13:46:26 +0200113 if (size > 200000) {
114 return;
115 }
Sam Zackrissonf341f3f2018-06-21 14:09:16 +0200116 test::FuzzDataHelper fuzz_data(rtc::ArrayView<const uint8_t>(data, size));
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200117 auto gci = std::make_unique<GainControlImpl>();
Sam Zackrissonf341f3f2018-06-21 14:09:16 +0200118 FuzzGainController(&fuzz_data, gci.get());
119}
120} // namespace webrtc