1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android-base/macros.h>
18 #include <audio_utils/primitives.h>
19 #include <audio_utils/sndfile.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <math.h>
24 #include <media/AudioBufferProvider.h>
25 #include <media/AudioResampler.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/mman.h>
32 #include <sys/stat.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <utils/Vector.h>
36
37 #include "libaudioprocessing_fuzz_utils.h"
38
39 #include <memory>
40
41 using namespace android;
42
43 const int MAX_FRAMES = 10;
44 const int MIN_FREQ = 1e3;
45 const int MAX_FREQ = 100e3;
46
47 const AudioResampler::src_quality qualities[] = {
48 AudioResampler::DEFAULT_QUALITY,
49 AudioResampler::LOW_QUALITY,
50 AudioResampler::MED_QUALITY,
51 AudioResampler::HIGH_QUALITY,
52 AudioResampler::VERY_HIGH_QUALITY,
53 AudioResampler::DYN_LOW_QUALITY,
54 AudioResampler::DYN_MED_QUALITY,
55 AudioResampler::DYN_HIGH_QUALITY,
56 };
57
chooseFormat(AudioResampler::src_quality quality,uint8_t input_byte)58 audio_format_t chooseFormat(AudioResampler::src_quality quality,
59 uint8_t input_byte) {
60 switch (quality) {
61 case AudioResampler::DYN_LOW_QUALITY:
62 case AudioResampler::DYN_MED_QUALITY:
63 case AudioResampler::DYN_HIGH_QUALITY:
64 if (input_byte % 2) {
65 return AUDIO_FORMAT_PCM_FLOAT;
66 }
67 FALLTHROUGH_INTENDED;
68 default:
69 return AUDIO_FORMAT_PCM_16_BIT;
70 }
71 }
72
parseValue(const uint8_t * src,int index,void * dst,size_t size)73 int parseValue(const uint8_t* src, int index, void* dst, size_t size) {
74 memcpy(dst, &src[index], size);
75 return size;
76 }
77
validFreq(int freq)78 bool validFreq(int freq) { return freq > MIN_FREQ && freq < MAX_FREQ; }
79
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)80 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
81 int input_freq = 0;
82 int output_freq = 0;
83 int input_channels = 0;
84
85 float left_volume = 0;
86 float right_volume = 0;
87
88 size_t metadata_size = 2 + 3 * sizeof(int) + 2 * sizeof(float);
89 if (size < metadata_size) {
90 // not enough data to set options
91 return 0;
92 }
93
94 AudioResampler::src_quality quality = qualities[data[0] % 8];
95 audio_format_t format = chooseFormat(quality, data[1]);
96
97 int index = 2;
98
99 index += parseValue(data, index, &input_freq, sizeof(int));
100 index += parseValue(data, index, &output_freq, sizeof(int));
101 index += parseValue(data, index, &input_channels, sizeof(int));
102
103 index += parseValue(data, index, &left_volume, sizeof(float));
104 index += parseValue(data, index, &right_volume, sizeof(float));
105
106 if (!validFreq(input_freq) || !validFreq(output_freq)) {
107 // sampling frequencies must be reasonable
108 return 0;
109 }
110
111 if (input_channels < 1 ||
112 input_channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
113 // invalid number of input channels
114 return 0;
115 }
116
117 size_t single_channel_size =
118 format == AUDIO_FORMAT_PCM_FLOAT ? sizeof(float) : sizeof(int16_t);
119 size_t input_frame_size = single_channel_size * input_channels;
120 size_t input_size = size - metadata_size;
121 uint8_t input_data[input_size];
122 memcpy(input_data, &data[metadata_size], input_size);
123
124 size_t input_frames = input_size / input_frame_size;
125 if (input_frames > MAX_FRAMES) {
126 return 0;
127 }
128
129 Provider provider(input_data, input_frames, input_frame_size);
130
131 std::unique_ptr<AudioResampler> resampler(
132 AudioResampler::create(format, input_channels, output_freq, quality));
133
134 resampler->setSampleRate(input_freq);
135 resampler->setVolume(left_volume, right_volume);
136
137 // output is at least stereo samples
138 int output_channels = input_channels > 2 ? input_channels : 2;
139 size_t output_frame_size = output_channels * sizeof(int32_t);
140 size_t output_frames = (input_frames * output_freq) / input_freq;
141 size_t output_size = output_frames * output_frame_size;
142
143 uint8_t output_data[output_size];
144 for (size_t i = 0; i < output_frames; i++) {
145 memset(output_data, 0, output_size);
146 resampler->resample((int*)output_data, i, &provider);
147 }
148
149 return 0;
150 }
151