File: agc_fuzzer.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (128 lines) | stat: -rw-r--r-- 4,904 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

#include "api/array_view.h"
#include "api/audio/audio_processing.h"
#include "modules/audio_processing/agc/gain_control.h"
#include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_processing/gain_control_impl.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "test/fuzzers/fuzz_data_helper.h"

namespace webrtc {
namespace {

void FillAudioBuffer(size_t sample_rate_hz,
                     test::FuzzDataHelper* fuzz_data,
                     AudioBuffer* buffer) {
  float* const* channels = buffer->channels_f();
  for (size_t i = 0; i < buffer->num_channels(); ++i) {
    for (size_t j = 0; j < buffer->num_frames(); ++j) {
      channels[i][j] =
          static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0));
    }
  }

  if (sample_rate_hz != 16000) {
    buffer->SplitIntoFrequencyBands();
  }
}

// This function calls the GainControl functions that are overriden as private
// in GainControlInterface.
void FuzzGainControllerConfig(test::FuzzDataHelper* fuzz_data,
                              GainControl* gc) {
  GainControl::Mode modes[] = {GainControl::Mode::kAdaptiveAnalog,
                               GainControl::Mode::kAdaptiveDigital,
                               GainControl::Mode::kFixedDigital};
  GainControl::Mode mode = fuzz_data->SelectOneOf(modes);
  const bool enable_limiter = fuzz_data->ReadOrDefaultValue(true);
  // The values are capped to comply with the API of webrtc::GainControl.
  const int analog_level_min = webrtc::SafeClamp<int>(
      fuzz_data->ReadOrDefaultValue<uint16_t>(0), 0, 65534);
  const int analog_level_max =
      webrtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(65535),
                             analog_level_min + 1, 65535);
  const int stream_analog_level =
      webrtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<uint16_t>(30000),
                             analog_level_min, analog_level_max);
  const int gain = webrtc::SafeClamp<int>(
      fuzz_data->ReadOrDefaultValue<int8_t>(30), -1, 100);
  const int target_level_dbfs =
      webrtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(15), -1, 35);

  gc->set_mode(mode);
  gc->enable_limiter(enable_limiter);
  if (mode == GainControl::Mode::kAdaptiveAnalog) {
    gc->set_analog_level_limits(analog_level_min, analog_level_max);
    gc->set_stream_analog_level(stream_analog_level);
  }
  gc->set_compression_gain_db(gain);
  gc->set_target_level_dbfs(target_level_dbfs);

  static_cast<void>(gc->mode());
  static_cast<void>(gc->analog_level_minimum());
  static_cast<void>(gc->analog_level_maximum());
  static_cast<void>(gc->stream_analog_level());
  static_cast<void>(gc->compression_gain_db());
  static_cast<void>(gc->stream_is_saturated());
  static_cast<void>(gc->target_level_dbfs());
  static_cast<void>(gc->is_limiter_enabled());
}

void FuzzGainController(test::FuzzDataHelper* fuzz_data, GainControlImpl* gci) {
  using Rate = ::webrtc::AudioProcessing::NativeRate;
  const Rate rate_kinds[] = {Rate::kSampleRate16kHz, Rate::kSampleRate32kHz,
                             Rate::kSampleRate48kHz};

  const auto sample_rate_hz =
      static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
  const size_t samples_per_frame = sample_rate_hz / 100;
  const size_t num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;

  gci->Initialize(num_channels, sample_rate_hz);
  FuzzGainControllerConfig(fuzz_data, gci);

  // The audio buffer is used for both capture and render.
  AudioBuffer audio(sample_rate_hz, num_channels, sample_rate_hz, num_channels,
                    sample_rate_hz, num_channels);

  std::vector<int16_t> packed_render_audio(samples_per_frame);

  while (fuzz_data->CanReadBytes(1)) {
    FillAudioBuffer(sample_rate_hz, fuzz_data, &audio);

    const bool stream_has_echo = fuzz_data->ReadOrDefaultValue(true);
    gci->AnalyzeCaptureAudio(audio);
    gci->ProcessCaptureAudio(&audio, stream_has_echo);

    FillAudioBuffer(sample_rate_hz, fuzz_data, &audio);

    gci->PackRenderAudioBuffer(audio, &packed_render_audio);
    gci->ProcessRenderAudio(packed_render_audio);
  }
}

}  // namespace

void FuzzOneInput(const uint8_t* data, size_t size) {
  if (size > 200000) {
    return;
  }
  test::FuzzDataHelper fuzz_data(webrtc::ArrayView<const uint8_t>(data, size));
  auto gci = std::make_unique<GainControlImpl>();
  FuzzGainController(&fuzz_data, gci.get());
}
}  // namespace webrtc