blob: 0dc3300c730623b9c783004e1e890e07fb6a3e41 [file] [log] [blame]
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +00001/*
2 * Copyright (c) 2014 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "common_audio/wav_header.h"
12
Raphael Kubo da Costa7ce30912018-04-16 11:17:10 +020013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000015#include <limits>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "test/gtest.h"
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000018
andrew@webrtc.org048c5022014-12-16 20:17:21 +000019namespace webrtc {
20
21// Doesn't take ownership of the buffer.
22class ReadableWavBuffer : public ReadableWav {
23 public:
andrew@webrtc.org048c5022014-12-16 20:17:21 +000024 ReadableWavBuffer(const uint8_t* buf, size_t size, bool check_read_size)
25 : buf_(buf),
26 size_(size),
27 pos_(0),
28 buf_exhausted_(false),
29 check_read_size_(check_read_size) {}
30
Mirko Bonadei91df0912018-07-17 11:08:15 +020031 ~ReadableWavBuffer() override {
andrew@webrtc.org048c5022014-12-16 20:17:21 +000032 // Verify the entire buffer has been read.
33 if (check_read_size_)
34 EXPECT_EQ(size_, pos_);
35 }
36
Mirko Bonadei91df0912018-07-17 11:08:15 +020037 size_t Read(void* buf, size_t num_bytes) override {
andrew@webrtc.org048c5022014-12-16 20:17:21 +000038 EXPECT_FALSE(buf_exhausted_);
39
40 const size_t bytes_remaining = size_ - pos_;
41 if (num_bytes > bytes_remaining) {
42 // The caller is signalled about an exhausted buffer when we return fewer
43 // bytes than requested. There should not be another read attempt after
44 // this point.
45 buf_exhausted_ = true;
46 num_bytes = bytes_remaining;
47 }
48 memcpy(buf, &buf_[pos_], num_bytes);
49 pos_ += num_bytes;
50 return num_bytes;
51 }
52
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +010053 bool SeekForward(uint32_t num_bytes) override {
54 // Verify we don't try to read outside of a properly sized header.
55 if (size_ >= kWavHeaderSize)
56 EXPECT_GE(size_, pos_ + num_bytes);
57 EXPECT_FALSE(buf_exhausted_);
58
59 const size_t bytes_remaining = size_ - pos_;
60 if (num_bytes > bytes_remaining) {
61 // Error: cannot seek beyond EOF.
62 return false;
63 }
64 if (num_bytes == bytes_remaining) {
65 // There should not be another read attempt after this point.
66 buf_exhausted_ = true;
67 }
68 pos_ += num_bytes;
69 return true;
70 }
71
andrew@webrtc.org048c5022014-12-16 20:17:21 +000072 private:
73 const uint8_t* buf_;
74 const size_t size_;
75 size_t pos_;
76 bool buf_exhausted_;
77 const bool check_read_size_;
78};
79
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000080// Try various choices of WAV header parameters, and make sure that the good
81// ones are accepted and the bad ones rejected.
82TEST(WavHeaderTest, CheckWavParameters) {
83 // Try some really stupid values for one parameter at a time.
andrew@webrtc.org048c5022014-12-16 20:17:21 +000084 EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 1, 0));
85 EXPECT_FALSE(CheckWavParameters(0, 8000, kWavFormatPcm, 1, 0));
pkasting25702cb2016-01-08 13:50:27 -080086 EXPECT_FALSE(CheckWavParameters(0x10000, 8000, kWavFormatPcm, 1, 0));
andrew@webrtc.org048c5022014-12-16 20:17:21 +000087 EXPECT_FALSE(CheckWavParameters(1, 0, kWavFormatPcm, 1, 0));
88 EXPECT_FALSE(CheckWavParameters(1, 8000, WavFormat(0), 1, 0));
89 EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 0, 0));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000090
91 // Try invalid format/bytes-per-sample combinations.
andrew@webrtc.org048c5022014-12-16 20:17:21 +000092 EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 2, 0));
93 EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 4, 0));
94 EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatALaw, 2, 0));
95 EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatMuLaw, 2, 0));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000096
97 // Too large values.
andrew@webrtc.org048c5022014-12-16 20:17:21 +000098 EXPECT_FALSE(CheckWavParameters(1 << 20, 1 << 20, kWavFormatPcm, 1, 0));
Yves Gerey665174f2018-06-19 15:03:05 +020099 EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 1,
100 std::numeric_limits<uint32_t>::max()));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000101
102 // Not the same number of samples for each channel.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000103 EXPECT_FALSE(CheckWavParameters(3, 8000, kWavFormatPcm, 1, 5));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000104}
105
andrew@webrtc.orgf866b2d2014-11-03 18:20:06 +0000106TEST(WavHeaderTest, ReadWavHeaderWithErrors) {
Peter Kasting69558702016-01-12 16:26:35 -0800107 size_t num_channels = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000108 int sample_rate = 0;
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000109 WavFormat format = kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800110 size_t bytes_per_sample = 0;
111 size_t num_samples = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000112
113 // Test a few ways the header can be invalid. We start with the valid header
114 // used in WriteAndReadWavHeader, and invalidate one field per test. The
115 // invalid field is indicated in the array name, and in the comments with
116 // *BAD*.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000117 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100118 constexpr uint8_t kBadRiffID[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200119 // clang-format off
120 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000121 'R', 'i', 'f', 'f', // *BAD*
122 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
123 'W', 'A', 'V', 'E',
124 'f', 'm', 't', ' ',
125 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
126 6, 0, // format: A-law (6)
127 17, 0, // channels: 17
128 0x39, 0x30, 0, 0, // sample rate: 12345
129 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
130 17, 0, // block align: NumChannels * BytesPerSample
131 8, 0, // bits per sample: 1 * 8
132 'd', 'a', 't', 'a',
133 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200134 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000135 };
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100136 ReadableWavBuffer r(kBadRiffID, sizeof(kBadRiffID),
137 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200138 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
139 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000140 }
141 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100142 constexpr uint8_t kBadBitsPerSample[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200143 // clang-format off
144 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000145 'R', 'I', 'F', 'F',
146 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
147 'W', 'A', 'V', 'E',
148 'f', 'm', 't', ' ',
149 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
150 6, 0, // format: A-law (6)
151 17, 0, // channels: 17
152 0x39, 0x30, 0, 0, // sample rate: 12345
153 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
154 17, 0, // block align: NumChannels * BytesPerSample
155 1, 0, // bits per sample: *BAD*
156 'd', 'a', 't', 'a',
157 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200158 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000159 };
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100160 ReadableWavBuffer r(kBadBitsPerSample, sizeof(kBadBitsPerSample),
161 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200162 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
163 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000164 }
165 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100166 constexpr uint8_t kBadByteRate[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200167 // clang-format off
168 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000169 'R', 'I', 'F', 'F',
170 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
171 'W', 'A', 'V', 'E',
172 'f', 'm', 't', ' ',
173 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
174 6, 0, // format: A-law (6)
175 17, 0, // channels: 17
176 0x39, 0x30, 0, 0, // sample rate: 12345
177 0x00, 0x33, 0x03, 0, // byte rate: *BAD*
178 17, 0, // block align: NumChannels * BytesPerSample
179 8, 0, // bits per sample: 1 * 8
180 'd', 'a', 't', 'a',
181 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200182 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000183 };
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100184 ReadableWavBuffer r(kBadByteRate, sizeof(kBadByteRate),
185 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200186 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
187 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000188 }
189 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100190 constexpr uint8_t kBadFmtHeaderSize[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200191 // clang-format off
192 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000193 'R', 'I', 'F', 'F',
194 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
195 'W', 'A', 'V', 'E',
196 'f', 'm', 't', ' ',
197 17, 0, 0, 0, // size of fmt block *BAD*. Only 16 and 18 permitted.
198 6, 0, // format: A-law (6)
199 17, 0, // channels: 17
200 0x39, 0x30, 0, 0, // sample rate: 12345
201 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
202 17, 0, // block align: NumChannels * BytesPerSample
203 8, 0, // bits per sample: 1 * 8
204 0, // extra (though invalid) header byte
205 'd', 'a', 't', 'a',
206 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200207 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000208 };
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100209 ReadableWavBuffer r(kBadFmtHeaderSize, sizeof(kBadFmtHeaderSize),
210 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200211 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
212 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000213 }
214 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100215 constexpr uint8_t kNonZeroExtensionField[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200216 // clang-format off
217 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000218 'R', 'I', 'F', 'F',
219 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
220 'W', 'A', 'V', 'E',
221 'f', 'm', 't', ' ',
222 18, 0, 0, 0, // size of fmt block - 8: 24 - 8
223 6, 0, // format: A-law (6)
224 17, 0, // channels: 17
225 0x39, 0x30, 0, 0, // sample rate: 12345
226 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
227 17, 0, // block align: NumChannels * BytesPerSample
228 8, 0, // bits per sample: 1 * 8
229 1, 0, // non-zero extension field *BAD*
230 'd', 'a', 't', 'a',
231 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200232 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000233 };
234 ReadableWavBuffer r(kNonZeroExtensionField, sizeof(kNonZeroExtensionField),
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100235 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200236 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
237 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000238 }
239 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100240 constexpr uint8_t kMissingDataChunk[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200241 // clang-format off
242 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000243 'R', 'I', 'F', 'F',
244 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
245 'W', 'A', 'V', 'E',
246 'f', 'm', 't', ' ',
247 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
248 6, 0, // format: A-law (6)
249 17, 0, // channels: 17
250 0x39, 0x30, 0, 0, // sample rate: 12345
251 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
252 17, 0, // block align: NumChannels * BytesPerSample
253 8, 0, // bits per sample: 1 * 8
Yves Gerey665174f2018-06-19 15:03:05 +0200254 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000255 };
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100256 ReadableWavBuffer r(kMissingDataChunk, sizeof(kMissingDataChunk),
257 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200258 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
259 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000260 }
261 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100262 constexpr uint8_t kMissingFmtAndDataChunks[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200263 // clang-format off
264 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000265 'R', 'I', 'F', 'F',
266 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
267 'W', 'A', 'V', 'E',
Yves Gerey665174f2018-06-19 15:03:05 +0200268 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000269 };
270 ReadableWavBuffer r(kMissingFmtAndDataChunks,
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100271 sizeof(kMissingFmtAndDataChunks),
272 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200273 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
274 &bytes_per_sample, &num_samples));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000275 }
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000276}
277
andrew@webrtc.orgf866b2d2014-11-03 18:20:06 +0000278// Try writing and reading a valid WAV header and make sure it looks OK.
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000279TEST(WavHeaderTest, WriteAndReadWavHeader) {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100280 constexpr int kSize = 4 + kWavHeaderSize + 4;
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000281 uint8_t buf[kSize];
282 memset(buf, 0xa4, sizeof(buf));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000283 WriteWavHeader(buf + 4, 17, 12345, kWavFormatALaw, 1, 123457689);
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100284 constexpr uint8_t kExpectedBuf[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200285 // clang-format off
286 // clang formatting doesn't respect inline comments.
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000287 0xa4, 0xa4, 0xa4, 0xa4, // untouched bytes before header
288 'R', 'I', 'F', 'F',
289 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
290 'W', 'A', 'V', 'E',
291 'f', 'm', 't', ' ',
292 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
293 6, 0, // format: A-law (6)
294 17, 0, // channels: 17
295 0x39, 0x30, 0, 0, // sample rate: 12345
296 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
297 17, 0, // block align: NumChannels * BytesPerSample
298 8, 0, // bits per sample: 1 * 8
299 'd', 'a', 't', 'a',
300 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
301 0xa4, 0xa4, 0xa4, 0xa4, // untouched bytes after header
Yves Gerey665174f2018-06-19 15:03:05 +0200302 // clang-format on
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000303 };
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000304 static_assert(sizeof(kExpectedBuf) == kSize, "buffer size");
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000305 EXPECT_EQ(0, memcmp(kExpectedBuf, buf, kSize));
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000306
Peter Kasting69558702016-01-12 16:26:35 -0800307 size_t num_channels = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000308 int sample_rate = 0;
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000309 WavFormat format = kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800310 size_t bytes_per_sample = 0;
311 size_t num_samples = 0;
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100312 ReadableWavBuffer r(buf + 4, sizeof(buf) - 8,
313 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200314 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
315 &bytes_per_sample, &num_samples));
Peter Kasting69558702016-01-12 16:26:35 -0800316 EXPECT_EQ(17u, num_channels);
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000317 EXPECT_EQ(12345, sample_rate);
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000318 EXPECT_EQ(kWavFormatALaw, format);
pkasting25702cb2016-01-08 13:50:27 -0800319 EXPECT_EQ(1u, bytes_per_sample);
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000320 EXPECT_EQ(123457689u, num_samples);
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000321}
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000322
323// Try reading an atypical but valid WAV header and make sure it's parsed OK.
324TEST(WavHeaderTest, ReadAtypicalWavHeader) {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100325 constexpr uint8_t kBuf[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200326 // clang-format off
327 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000328 'R', 'I', 'F', 'F',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100329 0xbf, 0xd0, 0x5b, 0x07, // Size of whole file - 8 + extra 2 bytes of zero
330 // extension: 123457689 + 44 - 8 + 2 (atypical).
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000331 'W', 'A', 'V', 'E',
332 'f', 'm', 't', ' ',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100333 18, 0, 0, 0, // Size of fmt block (with an atypical extension
334 // size field).
335 6, 0, // Format: A-law (6).
336 17, 0, // Channels: 17.
337 0x39, 0x30, 0, 0, // Sample rate: 12345.
338 0xc9, 0x33, 0x03, 0, // Byte rate: 1 * 17 * 12345.
339 17, 0, // Block align: NumChannels * BytesPerSample.
340 8, 0, // Bits per sample: 1 * 8.
341 0, 0, // Zero extension size field (atypical).
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000342 'd', 'a', 't', 'a',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100343 0x99, 0xd0, 0x5b, 0x07, // Size of payload: 123457689.
Yves Gerey665174f2018-06-19 15:03:05 +0200344 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000345 };
346
Peter Kasting69558702016-01-12 16:26:35 -0800347 size_t num_channels = 0;
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000348 int sample_rate = 0;
349 WavFormat format = kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800350 size_t bytes_per_sample = 0;
351 size_t num_samples = 0;
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100352 ReadableWavBuffer r(kBuf, sizeof(kBuf), /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200353 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
354 &bytes_per_sample, &num_samples));
Peter Kasting69558702016-01-12 16:26:35 -0800355 EXPECT_EQ(17u, num_channels);
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000356 EXPECT_EQ(12345, sample_rate);
357 EXPECT_EQ(kWavFormatALaw, format);
pkasting25702cb2016-01-08 13:50:27 -0800358 EXPECT_EQ(1u, bytes_per_sample);
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000359 EXPECT_EQ(123457689u, num_samples);
360}
361
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100362// Try reading a valid WAV header which contains an optional chunk and make sure
363// it's parsed OK.
364TEST(WavHeaderTest, ReadWavHeaderWithOptionalChunk) {
365 constexpr uint8_t kBuf[] = {
366 // clang-format off
367 // clang formatting doesn't respect inline comments.
368 'R', 'I', 'F', 'F',
369 0xcd, 0xd0, 0x5b, 0x07, // Size of whole file - 8 + an extra 16 bytes of
370 // "metadata" (8 bytes header, 16 bytes payload):
371 // 123457689 + 44 - 8 + 16.
372 'W', 'A', 'V', 'E',
373 'f', 'm', 't', ' ',
374 16, 0, 0, 0, // Size of fmt block.
375 6, 0, // Format: A-law (6).
376 17, 0, // Channels: 17.
377 0x39, 0x30, 0, 0, // Sample rate: 12345.
378 0xc9, 0x33, 0x03, 0, // Byte rate: 1 * 17 * 12345.
379 17, 0, // Block align: NumChannels * BytesPerSample.
380 8, 0, // Bits per sample: 1 * 8.
381 'L', 'I', 'S', 'T', // Metadata chunk ID.
382 16, 0, 0, 0, // Metadata chunk payload size.
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Metadata (16 bytes).
384 'd', 'a', 't', 'a',
385 0x99, 0xd0, 0x5b, 0x07, // Size of payload: 123457689.
386 // clang-format on
387 };
388
389 size_t num_channels = 0;
390 int sample_rate = 0;
391 WavFormat format = kWavFormatPcm;
392 size_t bytes_per_sample = 0;
393 size_t num_samples = 0;
394 ReadableWavBuffer r(kBuf, sizeof(kBuf), /*check_read_size=*/true);
395 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
396 &bytes_per_sample, &num_samples));
397 EXPECT_EQ(17u, num_channels);
398 EXPECT_EQ(12345, sample_rate);
399 EXPECT_EQ(kWavFormatALaw, format);
400 EXPECT_EQ(1u, bytes_per_sample);
401 EXPECT_EQ(123457689u, num_samples);
402}
403
404// Try reading an invalid WAV header which has the the data chunk before the
405// format one and make sure it's not parsed.
406TEST(WavHeaderTest, ReadWavHeaderWithDataBeforeFormat) {
407 constexpr uint8_t kBuf[] = {
408 // clang-format off
409 // clang formatting doesn't respect inline comments.
410 'R', 'I', 'F', 'F',
411 52, 0, 0, 0, // Size of whole file - 8: 16 + 44 - 8.
412 'W', 'A', 'V', 'E',
413 'd', 'a', 't', 'a',
414 16, 0, 0, 0, // Data chunk payload size.
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Data 16 bytes.
416 'f', 'm', 't', ' ',
417 16, 0, 0, 0, // Size of fmt block.
418 6, 0, // Format: A-law (6).
419 1, 0, // Channels: 1.
420 60, 0, 0, 0, // Sample rate: 60.
421 60, 0, 0, 0, // Byte rate: 1 * 1 * 60.
422 1, 0, // Block align: NumChannels * BytesPerSample.
423 8, 0, // Bits per sample: 1 * 8.
424 // clang-format on
425 };
426
427 size_t num_channels = 0;
428 int sample_rate = 0;
429 WavFormat format = kWavFormatPcm;
430 size_t bytes_per_sample = 0;
431 size_t num_samples = 0;
432 ReadableWavBuffer r(kBuf, sizeof(kBuf), /*check_read_size=*/false);
433 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
434 &bytes_per_sample, &num_samples));
435}
436
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000437} // namespace webrtc