blob: 95721dac656f7e2a9f4ad7a865dc7edcf6542b1f [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.
Per Åhgren5dca3f12020-01-28 09:08:11 +010022class WavHeaderBufferReader : public WavHeaderReader {
andrew@webrtc.org048c5022014-12-16 20:17:21 +000023 public:
Per Åhgren5dca3f12020-01-28 09:08:11 +010024 WavHeaderBufferReader(const uint8_t* buf, size_t size, bool check_read_size)
andrew@webrtc.org048c5022014-12-16 20:17:21 +000025 : buf_(buf),
26 size_(size),
27 pos_(0),
28 buf_exhausted_(false),
29 check_read_size_(check_read_size) {}
30
Per Åhgren5dca3f12020-01-28 09:08:11 +010031 ~WavHeaderBufferReader() 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.
Per Åhgren5dca3f12020-01-28 09:08:11 +010055 if (size_ >= kPcmWavHeaderSize)
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +010056 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
Per Åhgren5dca3f12020-01-28 09:08:11 +010072 int64_t GetPosition() override { return pos_; }
73
andrew@webrtc.org048c5022014-12-16 20:17:21 +000074 private:
75 const uint8_t* buf_;
76 const size_t size_;
77 size_t pos_;
78 bool buf_exhausted_;
79 const bool check_read_size_;
80};
81
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000082// Try various choices of WAV header parameters, and make sure that the good
83// ones are accepted and the bad ones rejected.
84TEST(WavHeaderTest, CheckWavParameters) {
85 // Try some really stupid values for one parameter at a time.
Per Åhgren5dca3f12020-01-28 09:08:11 +010086 EXPECT_TRUE(CheckWavParameters(1, 8000, WavFormat::kWavFormatPcm, 0));
87 EXPECT_FALSE(CheckWavParameters(0, 8000, WavFormat::kWavFormatPcm, 0));
88 EXPECT_FALSE(CheckWavParameters(0x10000, 8000, WavFormat::kWavFormatPcm, 0));
89 EXPECT_FALSE(CheckWavParameters(1, 0, WavFormat::kWavFormatPcm, 0));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000090
91 // Too large values.
Per Åhgren5dca3f12020-01-28 09:08:11 +010092 EXPECT_FALSE(
93 CheckWavParameters(1 << 20, 1 << 20, WavFormat::kWavFormatPcm, 0));
94 EXPECT_FALSE(CheckWavParameters(1, 8000, WavFormat::kWavFormatPcm,
Yves Gerey665174f2018-06-19 15:03:05 +020095 std::numeric_limits<uint32_t>::max()));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000096
97 // Not the same number of samples for each channel.
Per Åhgren5dca3f12020-01-28 09:08:11 +010098 EXPECT_FALSE(CheckWavParameters(3, 8000, WavFormat::kWavFormatPcm, 5));
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +000099}
100
andrew@webrtc.orgf866b2d2014-11-03 18:20:06 +0000101TEST(WavHeaderTest, ReadWavHeaderWithErrors) {
Peter Kasting69558702016-01-12 16:26:35 -0800102 size_t num_channels = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000103 int sample_rate = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100104 WavFormat format = WavFormat::kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800105 size_t bytes_per_sample = 0;
106 size_t num_samples = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100107 int64_t data_start_pos = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000108
109 // Test a few ways the header can be invalid. We start with the valid header
110 // used in WriteAndReadWavHeader, and invalidate one field per test. The
111 // invalid field is indicated in the array name, and in the comments with
112 // *BAD*.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000113 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100114 constexpr uint8_t kBadRiffID[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200115 // clang-format off
116 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000117 'R', 'i', 'f', 'f', // *BAD*
118 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
119 'W', 'A', 'V', 'E',
120 'f', 'm', 't', ' ',
121 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
Per Åhgren5dca3f12020-01-28 09:08:11 +0100122 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000123 17, 0, // channels: 17
124 0x39, 0x30, 0, 0, // sample rate: 12345
125 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
126 17, 0, // block align: NumChannels * BytesPerSample
127 8, 0, // bits per sample: 1 * 8
128 'd', 'a', 't', 'a',
129 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200130 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000131 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100132 WavHeaderBufferReader r(kBadRiffID, sizeof(kBadRiffID),
133 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200134 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100135 &bytes_per_sample, &num_samples,
136 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000137 }
138 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100139 constexpr uint8_t kBadBitsPerSample[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200140 // clang-format off
141 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000142 'R', 'I', 'F', 'F',
143 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
144 'W', 'A', 'V', 'E',
145 'f', 'm', 't', ' ',
146 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
Per Åhgren5dca3f12020-01-28 09:08:11 +0100147 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000148 17, 0, // channels: 17
149 0x39, 0x30, 0, 0, // sample rate: 12345
150 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
151 17, 0, // block align: NumChannels * BytesPerSample
152 1, 0, // bits per sample: *BAD*
153 'd', 'a', 't', 'a',
154 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200155 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000156 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100157 WavHeaderBufferReader r(kBadBitsPerSample, sizeof(kBadBitsPerSample),
158 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200159 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100160 &bytes_per_sample, &num_samples,
161 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000162 }
163 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100164 constexpr uint8_t kBadByteRate[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200165 // clang-format off
166 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000167 'R', 'I', 'F', 'F',
168 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
169 'W', 'A', 'V', 'E',
170 'f', 'm', 't', ' ',
171 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
Per Åhgren5dca3f12020-01-28 09:08:11 +0100172 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000173 17, 0, // channels: 17
174 0x39, 0x30, 0, 0, // sample rate: 12345
175 0x00, 0x33, 0x03, 0, // byte rate: *BAD*
176 17, 0, // block align: NumChannels * BytesPerSample
177 8, 0, // bits per sample: 1 * 8
178 'd', 'a', 't', 'a',
179 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200180 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000181 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100182 WavHeaderBufferReader r(kBadByteRate, sizeof(kBadByteRate),
183 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200184 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100185 &bytes_per_sample, &num_samples,
186 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000187 }
188 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100189 constexpr uint8_t kBadFmtHeaderSize[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200190 // clang-format off
191 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000192 'R', 'I', 'F', 'F',
193 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
194 'W', 'A', 'V', 'E',
195 'f', 'm', 't', ' ',
196 17, 0, 0, 0, // size of fmt block *BAD*. Only 16 and 18 permitted.
Per Åhgren5dca3f12020-01-28 09:08:11 +0100197 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000198 17, 0, // channels: 17
199 0x39, 0x30, 0, 0, // sample rate: 12345
200 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
201 17, 0, // block align: NumChannels * BytesPerSample
202 8, 0, // bits per sample: 1 * 8
203 0, // extra (though invalid) header byte
204 'd', 'a', 't', 'a',
205 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689
Yves Gerey665174f2018-06-19 15:03:05 +0200206 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000207 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100208 WavHeaderBufferReader r(kBadFmtHeaderSize, sizeof(kBadFmtHeaderSize),
209 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200210 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100211 &bytes_per_sample, &num_samples,
212 &data_start_pos));
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
Per Åhgren5dca3f12020-01-28 09:08:11 +0100223 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000224 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 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100234 WavHeaderBufferReader r(kNonZeroExtensionField,
235 sizeof(kNonZeroExtensionField),
236 /*check_read_size=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200237 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100238 &bytes_per_sample, &num_samples,
239 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000240 }
241 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100242 constexpr uint8_t kMissingDataChunk[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200243 // clang-format off
244 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000245 'R', 'I', 'F', 'F',
246 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
247 'W', 'A', 'V', 'E',
248 'f', 'm', 't', ' ',
249 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
Per Åhgren5dca3f12020-01-28 09:08:11 +0100250 1, 0, // format: PCM (1)
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000251 17, 0, // channels: 17
252 0x39, 0x30, 0, 0, // sample rate: 12345
253 0xc9, 0x33, 0x03, 0, // byte rate: 1 * 17 * 12345
254 17, 0, // block align: NumChannels * BytesPerSample
255 8, 0, // bits per sample: 1 * 8
Yves Gerey665174f2018-06-19 15:03:05 +0200256 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000257 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100258 WavHeaderBufferReader r(kMissingDataChunk, sizeof(kMissingDataChunk),
259 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200260 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100261 &bytes_per_sample, &num_samples,
262 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000263 }
264 {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100265 constexpr uint8_t kMissingFmtAndDataChunks[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200266 // clang-format off
267 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000268 'R', 'I', 'F', 'F',
269 0xbd, 0xd0, 0x5b, 0x07, // size of whole file - 8: 123457689 + 44 - 8
270 'W', 'A', 'V', 'E',
Yves Gerey665174f2018-06-19 15:03:05 +0200271 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000272 };
Per Åhgren5dca3f12020-01-28 09:08:11 +0100273 WavHeaderBufferReader r(kMissingFmtAndDataChunks,
274 sizeof(kMissingFmtAndDataChunks),
275 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200276 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100277 &bytes_per_sample, &num_samples,
278 &data_start_pos));
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000279 }
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000280}
281
andrew@webrtc.orgf866b2d2014-11-03 18:20:06 +0000282// Try writing and reading a valid WAV header and make sure it looks OK.
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000283TEST(WavHeaderTest, WriteAndReadWavHeader) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100284 constexpr int kSize = 4 + kPcmWavHeaderSize + 4;
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000285 uint8_t buf[kSize];
Per Åhgren5dca3f12020-01-28 09:08:11 +0100286 size_t header_size;
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000287 memset(buf, 0xa4, sizeof(buf));
Per Åhgren5dca3f12020-01-28 09:08:11 +0100288 WriteWavHeader(17, 12345, WavFormat::kWavFormatPcm, 123457689, buf + 4,
289 &header_size);
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100290 constexpr uint8_t kExpectedBuf[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200291 // clang-format off
Per Åhgren5dca3f12020-01-28 09:08:11 +0100292 // clang formatting doesn't respect inline comments.
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000293 0xa4, 0xa4, 0xa4, 0xa4, // untouched bytes before header
294 'R', 'I', 'F', 'F',
Per Åhgren5dca3f12020-01-28 09:08:11 +0100295 0x56, 0xa1, 0xb7, 0x0e, // size of whole file - 8: 123457689 + 44 - 8
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000296 'W', 'A', 'V', 'E',
297 'f', 'm', 't', ' ',
298 16, 0, 0, 0, // size of fmt block - 8: 24 - 8
Per Åhgren5dca3f12020-01-28 09:08:11 +0100299 1, 0, // format: PCM (1)
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000300 17, 0, // channels: 17
301 0x39, 0x30, 0, 0, // sample rate: 12345
Per Åhgren5dca3f12020-01-28 09:08:11 +0100302 0x92, 0x67, 0x06, 0, // byte rate: 2 * 17 * 12345
303 34, 0, // block align: NumChannels * BytesPerSample
304 16, 0, // bits per sample: 2 * 8
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000305 'd', 'a', 't', 'a',
Per Åhgren5dca3f12020-01-28 09:08:11 +0100306 0x32, 0xa1, 0xb7, 0x0e, // size of payload: 2 * 123457689
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000307 0xa4, 0xa4, 0xa4, 0xa4, // untouched bytes after header
Yves Gerey665174f2018-06-19 15:03:05 +0200308 // clang-format on
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000309 };
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000310 static_assert(sizeof(kExpectedBuf) == kSize, "buffer size");
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000311 EXPECT_EQ(0, memcmp(kExpectedBuf, buf, kSize));
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000312
Peter Kasting69558702016-01-12 16:26:35 -0800313 size_t num_channels = 0;
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000314 int sample_rate = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100315 WavFormat format = WavFormat::kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800316 size_t bytes_per_sample = 0;
317 size_t num_samples = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100318 int64_t data_start_pos = 0;
319 WavHeaderBufferReader r(buf + 4, sizeof(buf) - 8,
320 /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200321 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100322 &bytes_per_sample, &num_samples, &data_start_pos));
Peter Kasting69558702016-01-12 16:26:35 -0800323 EXPECT_EQ(17u, num_channels);
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000324 EXPECT_EQ(12345, sample_rate);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100325 EXPECT_EQ(WavFormat::kWavFormatPcm, format);
326 EXPECT_EQ(2u, bytes_per_sample);
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000327 EXPECT_EQ(123457689u, num_samples);
kwiberg@webrtc.org877083c2014-08-20 07:42:46 +0000328}
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000329
330// Try reading an atypical but valid WAV header and make sure it's parsed OK.
331TEST(WavHeaderTest, ReadAtypicalWavHeader) {
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100332 constexpr uint8_t kBuf[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200333 // clang-format off
334 // clang formatting doesn't respect inline comments.
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000335 'R', 'I', 'F', 'F',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100336 0xbf, 0xd0, 0x5b, 0x07, // Size of whole file - 8 + extra 2 bytes of zero
337 // extension: 123457689 + 44 - 8 + 2 (atypical).
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000338 'W', 'A', 'V', 'E',
339 'f', 'm', 't', ' ',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100340 18, 0, 0, 0, // Size of fmt block (with an atypical extension
341 // size field).
Per Åhgren5dca3f12020-01-28 09:08:11 +0100342 1, 0, // Format: PCM (1).
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100343 17, 0, // Channels: 17.
344 0x39, 0x30, 0, 0, // Sample rate: 12345.
345 0xc9, 0x33, 0x03, 0, // Byte rate: 1 * 17 * 12345.
346 17, 0, // Block align: NumChannels * BytesPerSample.
347 8, 0, // Bits per sample: 1 * 8.
348 0, 0, // Zero extension size field (atypical).
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000349 'd', 'a', 't', 'a',
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100350 0x99, 0xd0, 0x5b, 0x07, // Size of payload: 123457689.
Yves Gerey665174f2018-06-19 15:03:05 +0200351 // clang-format on
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000352 };
353
Peter Kasting69558702016-01-12 16:26:35 -0800354 size_t num_channels = 0;
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000355 int sample_rate = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100356 WavFormat format = WavFormat::kWavFormatPcm;
pkasting25702cb2016-01-08 13:50:27 -0800357 size_t bytes_per_sample = 0;
358 size_t num_samples = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100359 int64_t data_start_pos = 0;
360 WavHeaderBufferReader r(kBuf, sizeof(kBuf), /*check_read_size=*/true);
Yves Gerey665174f2018-06-19 15:03:05 +0200361 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100362 &bytes_per_sample, &num_samples, &data_start_pos));
Peter Kasting69558702016-01-12 16:26:35 -0800363 EXPECT_EQ(17u, num_channels);
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000364 EXPECT_EQ(12345, sample_rate);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100365 EXPECT_EQ(WavFormat::kWavFormatPcm, format);
pkasting25702cb2016-01-08 13:50:27 -0800366 EXPECT_EQ(1u, bytes_per_sample);
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000367 EXPECT_EQ(123457689u, num_samples);
368}
369
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100370// Try reading a valid WAV header which contains an optional chunk and make sure
371// it's parsed OK.
372TEST(WavHeaderTest, ReadWavHeaderWithOptionalChunk) {
373 constexpr uint8_t kBuf[] = {
374 // clang-format off
375 // clang formatting doesn't respect inline comments.
376 'R', 'I', 'F', 'F',
377 0xcd, 0xd0, 0x5b, 0x07, // Size of whole file - 8 + an extra 16 bytes of
378 // "metadata" (8 bytes header, 16 bytes payload):
379 // 123457689 + 44 - 8 + 16.
380 'W', 'A', 'V', 'E',
381 'f', 'm', 't', ' ',
382 16, 0, 0, 0, // Size of fmt block.
Per Åhgren5dca3f12020-01-28 09:08:11 +0100383 1, 0, // Format: PCM (1).
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100384 17, 0, // Channels: 17.
385 0x39, 0x30, 0, 0, // Sample rate: 12345.
386 0xc9, 0x33, 0x03, 0, // Byte rate: 1 * 17 * 12345.
387 17, 0, // Block align: NumChannels * BytesPerSample.
388 8, 0, // Bits per sample: 1 * 8.
389 'L', 'I', 'S', 'T', // Metadata chunk ID.
390 16, 0, 0, 0, // Metadata chunk payload size.
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Metadata (16 bytes).
392 'd', 'a', 't', 'a',
393 0x99, 0xd0, 0x5b, 0x07, // Size of payload: 123457689.
394 // clang-format on
395 };
396
397 size_t num_channels = 0;
398 int sample_rate = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100399 WavFormat format = WavFormat::kWavFormatPcm;
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100400 size_t bytes_per_sample = 0;
401 size_t num_samples = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100402 int64_t data_start_pos = 0;
403 WavHeaderBufferReader r(kBuf, sizeof(kBuf), /*check_read_size=*/true);
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100404 EXPECT_TRUE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100405 &bytes_per_sample, &num_samples, &data_start_pos));
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100406 EXPECT_EQ(17u, num_channels);
407 EXPECT_EQ(12345, sample_rate);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100408 EXPECT_EQ(WavFormat::kWavFormatPcm, format);
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100409 EXPECT_EQ(1u, bytes_per_sample);
410 EXPECT_EQ(123457689u, num_samples);
411}
412
413// Try reading an invalid WAV header which has the the data chunk before the
414// format one and make sure it's not parsed.
415TEST(WavHeaderTest, ReadWavHeaderWithDataBeforeFormat) {
416 constexpr uint8_t kBuf[] = {
417 // clang-format off
418 // clang formatting doesn't respect inline comments.
419 'R', 'I', 'F', 'F',
420 52, 0, 0, 0, // Size of whole file - 8: 16 + 44 - 8.
421 'W', 'A', 'V', 'E',
422 'd', 'a', 't', 'a',
423 16, 0, 0, 0, // Data chunk payload size.
424 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Data 16 bytes.
425 'f', 'm', 't', ' ',
426 16, 0, 0, 0, // Size of fmt block.
Per Åhgren5dca3f12020-01-28 09:08:11 +0100427 1, 0, // Format: Pcm (1).
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100428 1, 0, // Channels: 1.
429 60, 0, 0, 0, // Sample rate: 60.
430 60, 0, 0, 0, // Byte rate: 1 * 1 * 60.
431 1, 0, // Block align: NumChannels * BytesPerSample.
432 8, 0, // Bits per sample: 1 * 8.
433 // clang-format on
434 };
435
436 size_t num_channels = 0;
437 int sample_rate = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100438 WavFormat format = WavFormat::kWavFormatPcm;
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100439 size_t bytes_per_sample = 0;
440 size_t num_samples = 0;
Per Åhgren5dca3f12020-01-28 09:08:11 +0100441 int64_t data_start_pos = 0;
442 WavHeaderBufferReader r(kBuf, sizeof(kBuf), /*check_read_size=*/false);
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100443 EXPECT_FALSE(ReadWavHeader(&r, &num_channels, &sample_rate, &format,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100444 &bytes_per_sample, &num_samples, &data_start_pos));
Alessio Bazzicaa33c7af2018-11-08 12:16:11 +0100445}
446
andrew@webrtc.org048c5022014-12-16 20:17:21 +0000447} // namespace webrtc