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