blob: 868532632fa8db7178359adac32e4b8e3e72a5f9 [file] [log] [blame]
Alex Loikoab20a602018-01-16 12:50:34 +01001/*
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 "test/fuzzers/audio_processing_fuzzer_helper.h"
12
13#include <algorithm>
14#include <array>
15#include <cmath>
16#include <limits>
17
18#include "modules/audio_processing/include/audio_processing.h"
19#include "modules/include/module_common_types.h"
20#include "rtc_base/checks.h"
21
22namespace webrtc {
23namespace {
24void GenerateFloatFrame(test::FuzzDataHelper* fuzz_data,
25 size_t input_rate,
26 size_t num_channels,
27 float* const* float_frames) {
28 const size_t samples_per_input_channel =
29 rtc::CheckedDivExact(input_rate, 100ul);
30 RTC_DCHECK_LE(samples_per_input_channel, 480);
31 for (size_t i = 0; i < num_channels; ++i) {
32 for (size_t j = 0; j < samples_per_input_channel; ++j) {
33 float_frames[i][j] =
34 static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0)) /
35 static_cast<float>(std::numeric_limits<int16_t>::max());
36 }
37 }
38}
39
40void GenerateFixedFrame(test::FuzzDataHelper* fuzz_data,
41 size_t input_rate,
42 size_t num_channels,
43 AudioFrame* fixed_frame) {
44 const size_t samples_per_input_channel =
45 rtc::CheckedDivExact(input_rate, 100ul);
46 fixed_frame->samples_per_channel_ = samples_per_input_channel;
47 fixed_frame->sample_rate_hz_ = input_rate;
48 fixed_frame->num_channels_ = num_channels;
49
50 RTC_DCHECK_LE(samples_per_input_channel * num_channels,
51 AudioFrame::kMaxDataSizeSamples);
52 for (size_t i = 0; i < samples_per_input_channel * num_channels; ++i) {
Alex Loiko38c15d32018-03-02 13:53:09 +010053 fixed_frame->mutable_data()[i] = fuzz_data->ReadOrDefaultValue<int16_t>(0);
Alex Loikoab20a602018-01-16 12:50:34 +010054 }
55}
56} // namespace
57
58void FuzzAudioProcessing(test::FuzzDataHelper* fuzz_data,
59 std::unique_ptr<AudioProcessing> apm) {
60 AudioFrame fixed_frame;
61 std::array<float, 480> float_frame1;
62 std::array<float, 480> float_frame2;
63 std::array<float* const, 2> float_frame_ptrs = {
64 &float_frame1[0], &float_frame2[0],
65 };
66 float* const* ptr_to_float_frames = &float_frame_ptrs[0];
67
68 using Rate = AudioProcessing::NativeRate;
69 const Rate rate_kinds[] = {Rate::kSampleRate8kHz, Rate::kSampleRate16kHz,
70 Rate::kSampleRate32kHz, Rate::kSampleRate48kHz};
71
72 // We may run out of fuzz data in the middle of a loop iteration. In
73 // that case, default values will be used for the rest of that
74 // iteration.
75 while (fuzz_data->CanReadBytes(1)) {
76 const bool is_float = fuzz_data->ReadOrDefaultValue(true);
77 // Decide input/output rate for this iteration.
78 const auto input_rate =
79 static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
80 const auto output_rate =
81 static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
82
83 const bool num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
Alex Loiko38c15d32018-03-02 13:53:09 +010084 const uint8_t stream_delay = fuzz_data->ReadOrDefaultValue<uint8_t>(0);
Alex Loikoab20a602018-01-16 12:50:34 +010085
86 // API call needed for AEC-2 and AEC-m to run.
87 apm->set_stream_delay_ms(stream_delay);
88
89 // Make the APM call depending on capture/render mode and float /
90 // fix interface.
91 const bool is_capture = fuzz_data->ReadOrDefaultValue(true);
92
93 // Fill the arrays with audio samples from the data.
94 int apm_return_code = AudioProcessing::Error::kNoError;
95 if (is_float) {
96 GenerateFloatFrame(fuzz_data, input_rate, num_channels,
97 ptr_to_float_frames);
98 if (is_capture) {
99 apm_return_code = apm->ProcessStream(
100 ptr_to_float_frames, StreamConfig(input_rate, num_channels),
101 StreamConfig(output_rate, num_channels), ptr_to_float_frames);
102 } else {
103 apm_return_code = apm->ProcessReverseStream(
104 ptr_to_float_frames, StreamConfig(input_rate, 1),
105 StreamConfig(output_rate, 1), ptr_to_float_frames);
106 }
107 } else {
108 GenerateFixedFrame(fuzz_data, input_rate, num_channels, &fixed_frame);
109
110 if (is_capture) {
111 apm_return_code = apm->ProcessStream(&fixed_frame);
112 } else {
113 apm_return_code = apm->ProcessReverseStream(&fixed_frame);
114 }
115 }
116
Alex Loiko9df3cf32018-04-10 12:18:02 +0200117 // Make calls to stats gathering functions to cover these
118 // codeways.
119 static_cast<void>(apm->GetStatistics());
120 static_cast<void>(apm->GetStatistics(true));
121
Alex Loikoab20a602018-01-16 12:50:34 +0100122 RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
123 }
124}
125} // namespace webrtc