1 /*
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 
11 #include <limits>
12 
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/common_audio/wav_header.h"
15 
16 namespace webrtc {
17 
18 // Doesn't take ownership of the buffer.
19 class ReadableWavBuffer : public ReadableWav {
20  public:
ReadableWavBuffer(const uint8_t * buf,size_t size)21   ReadableWavBuffer(const uint8_t* buf, size_t size)
22       : buf_(buf),
23         size_(size),
24         pos_(0),
25         buf_exhausted_(false),
26         check_read_size_(true) {}
ReadableWavBuffer(const uint8_t * buf,size_t size,bool check_read_size)27   ReadableWavBuffer(const uint8_t* buf, size_t size, bool check_read_size)
28       : buf_(buf),
29         size_(size),
30         pos_(0),
31         buf_exhausted_(false),
32         check_read_size_(check_read_size) {}
33 
~ReadableWavBuffer()34   virtual ~ReadableWavBuffer() {
35     // Verify the entire buffer has been read.
36     if (check_read_size_)
37       EXPECT_EQ(size_, pos_);
38   }
39 
Read(void * buf,size_t num_bytes)40   virtual size_t Read(void* buf, size_t num_bytes) {
41     // Verify we don't try to read outside of a properly sized header.
42     if (size_ >= kWavHeaderSize)
43       EXPECT_GE(size_, pos_ + num_bytes);
44     EXPECT_FALSE(buf_exhausted_);
45 
46     const size_t bytes_remaining = size_ - pos_;
47     if (num_bytes > bytes_remaining) {
48       // The caller is signalled about an exhausted buffer when we return fewer
49       // bytes than requested. There should not be another read attempt after
50       // this point.
51       buf_exhausted_ = true;
52       num_bytes = bytes_remaining;
53     }
54     memcpy(buf, &buf_[pos_], num_bytes);
55     pos_ += num_bytes;
56     return num_bytes;
57   }
58 
59  private:
60   const uint8_t* buf_;
61   const size_t size_;
62   size_t pos_;
63   bool buf_exhausted_;
64   const bool check_read_size_;
65 };
66 
67 // Try various choices of WAV header parameters, and make sure that the good
68 // ones are accepted and the bad ones rejected.
TEST(WavHeaderTest,CheckWavParameters)69 TEST(WavHeaderTest, CheckWavParameters) {
70   // Try some really stupid values for one parameter at a time.
71   EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 1, 0));
72   EXPECT_FALSE(CheckWavParameters(0, 8000, kWavFormatPcm, 1, 0));
73   EXPECT_FALSE(CheckWavParameters(-1, 8000, kWavFormatPcm, 1, 0));
74   EXPECT_FALSE(CheckWavParameters(1, 0, kWavFormatPcm, 1, 0));
75   EXPECT_FALSE(CheckWavParameters(1, 8000, WavFormat(0), 1, 0));
76   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 0, 0));
77 
78   // Try invalid format/bytes-per-sample combinations.
79   EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 2, 0));
80   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 4, 0));
81   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatALaw, 2, 0));
82   EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatMuLaw, 2, 0));
83 
84   // Too large values.
85   EXPECT_FALSE(CheckWavParameters(1 << 20, 1 << 20, kWavFormatPcm, 1, 0));
86   EXPECT_FALSE(CheckWavParameters(
87       1, 8000, kWavFormatPcm, 1, std::numeric_limits<uint32_t>::max()));
88 
89   // Not the same number of samples for each channel.
90   EXPECT_FALSE(CheckWavParameters(3, 8000, kWavFormatPcm, 1, 5));
91 }
92 
TEST(WavHeaderTest,ReadWavHeaderWithErrors)93 TEST(WavHeaderTest, ReadWavHeaderWithErrors) {
94   int num_channels = 0;
95   int sample_rate = 0;
96   WavFormat format = kWavFormatPcm;
97   int bytes_per_sample = 0;
98   uint32_t num_samples = 0;
99 
100   // Test a few ways the header can be invalid. We start with the valid header
101   // used in WriteAndReadWavHeader, and invalidate one field per test. The
102   // invalid field is indicated in the array name, and in the comments with
103   // *BAD*.
104   {
105     static const uint8_t kBadRiffID[] = {
106       'R', 'i', 'f', 'f',  // *BAD*
107       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
108       'W', 'A', 'V', 'E',
109       'f', 'm', 't', ' ',
110       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
111       6, 0,  // format: A-law (6)
112       17, 0,  // channels: 17
113       0x39, 0x30, 0, 0,  // sample rate: 12345
114       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
115       17, 0,  // block align: NumChannels * BytesPerSample
116       8, 0,  // bits per sample: 1 * 8
117       'd', 'a', 't', 'a',
118       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
119     };
120     ReadableWavBuffer r(kBadRiffID, sizeof(kBadRiffID));
121     EXPECT_FALSE(
122         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
123                       &bytes_per_sample, &num_samples));
124   }
125   {
126     static const uint8_t kBadBitsPerSample[] = {
127       'R', 'I', 'F', 'F',
128       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
129       'W', 'A', 'V', 'E',
130       'f', 'm', 't', ' ',
131       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
132       6, 0,  // format: A-law (6)
133       17, 0,  // channels: 17
134       0x39, 0x30, 0, 0,  // sample rate: 12345
135       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
136       17, 0,  // block align: NumChannels * BytesPerSample
137       1, 0,  // bits per sample: *BAD*
138       'd', 'a', 't', 'a',
139       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
140     };
141     ReadableWavBuffer r(kBadBitsPerSample, sizeof(kBadBitsPerSample));
142     EXPECT_FALSE(
143         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
144                       &bytes_per_sample, &num_samples));
145   }
146   {
147     static const uint8_t kBadByteRate[] = {
148       'R', 'I', 'F', 'F',
149       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
150       'W', 'A', 'V', 'E',
151       'f', 'm', 't', ' ',
152       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
153       6, 0,  // format: A-law (6)
154       17, 0,  // channels: 17
155       0x39, 0x30, 0, 0,  // sample rate: 12345
156       0x00, 0x33, 0x03, 0,  // byte rate: *BAD*
157       17, 0,  // block align: NumChannels * BytesPerSample
158       8, 0,  // bits per sample: 1 * 8
159       'd', 'a', 't', 'a',
160       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
161     };
162     ReadableWavBuffer r(kBadByteRate, sizeof(kBadByteRate));
163     EXPECT_FALSE(
164         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
165                       &bytes_per_sample, &num_samples));
166   }
167   {
168     static const uint8_t kBadFmtHeaderSize[] = {
169       '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       17, 0, 0, 0,  // size of fmt block *BAD*. Only 16 and 18 permitted.
174       6, 0,  // format: A-law (6)
175       17, 0,  // channels: 17
176       0x39, 0x30, 0, 0,  // sample rate: 12345
177       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
178       17, 0,  // block align: NumChannels * BytesPerSample
179       8, 0,  // bits per sample: 1 * 8
180       0,  // extra (though invalid) header byte
181       'd', 'a', 't', 'a',
182       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
183     };
184     ReadableWavBuffer r(kBadFmtHeaderSize, sizeof(kBadFmtHeaderSize), false);
185     EXPECT_FALSE(
186         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
187                       &bytes_per_sample, &num_samples));
188   }
189   {
190     static const uint8_t kNonZeroExtensionField[] = {
191       'R', 'I', 'F', 'F',
192       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
193       'W', 'A', 'V', 'E',
194       'f', 'm', 't', ' ',
195       18, 0, 0, 0,  // size of fmt block - 8: 24 - 8
196       6, 0,  // format: A-law (6)
197       17, 0,  // channels: 17
198       0x39, 0x30, 0, 0,  // sample rate: 12345
199       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
200       17, 0,  // block align: NumChannels * BytesPerSample
201       8, 0,  // bits per sample: 1 * 8
202       1, 0,  // non-zero extension field *BAD*
203       'd', 'a', 't', 'a',
204       0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
205     };
206     ReadableWavBuffer r(kNonZeroExtensionField, sizeof(kNonZeroExtensionField),
207                         false);
208     EXPECT_FALSE(
209         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
210                       &bytes_per_sample, &num_samples));
211   }
212   {
213     static const uint8_t kMissingDataChunk[] = {
214       'R', 'I', 'F', 'F',
215       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
216       'W', 'A', 'V', 'E',
217       'f', 'm', 't', ' ',
218       16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
219       6, 0,  // format: A-law (6)
220       17, 0,  // channels: 17
221       0x39, 0x30, 0, 0,  // sample rate: 12345
222       0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
223       17, 0,  // block align: NumChannels * BytesPerSample
224       8, 0,  // bits per sample: 1 * 8
225     };
226     ReadableWavBuffer r(kMissingDataChunk, sizeof(kMissingDataChunk));
227     EXPECT_FALSE(
228         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
229                       &bytes_per_sample, &num_samples));
230   }
231   {
232     static const uint8_t kMissingFmtAndDataChunks[] = {
233       'R', 'I', 'F', 'F',
234       0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
235       'W', 'A', 'V', 'E',
236     };
237     ReadableWavBuffer r(kMissingFmtAndDataChunks,
238                         sizeof(kMissingFmtAndDataChunks));
239     EXPECT_FALSE(
240         ReadWavHeader(&r, &num_channels, &sample_rate, &format,
241                       &bytes_per_sample, &num_samples));
242   }
243 }
244 
245 // Try writing and reading a valid WAV header and make sure it looks OK.
TEST(WavHeaderTest,WriteAndReadWavHeader)246 TEST(WavHeaderTest, WriteAndReadWavHeader) {
247   static const int kSize = 4 + kWavHeaderSize + 4;
248   uint8_t buf[kSize];
249   memset(buf, 0xa4, sizeof(buf));
250   WriteWavHeader(buf + 4, 17, 12345, kWavFormatALaw, 1, 123457689);
251   static const uint8_t kExpectedBuf[] = {
252     0xa4, 0xa4, 0xa4, 0xa4,  // untouched bytes before header
253     'R', 'I', 'F', 'F',
254     0xbd, 0xd0, 0x5b, 0x07,  // size of whole file - 8: 123457689 + 44 - 8
255     'W', 'A', 'V', 'E',
256     'f', 'm', 't', ' ',
257     16, 0, 0, 0,  // size of fmt block - 8: 24 - 8
258     6, 0,  // format: A-law (6)
259     17, 0,  // channels: 17
260     0x39, 0x30, 0, 0,  // sample rate: 12345
261     0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
262     17, 0,  // block align: NumChannels * BytesPerSample
263     8, 0,  // bits per sample: 1 * 8
264     'd', 'a', 't', 'a',
265     0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
266     0xa4, 0xa4, 0xa4, 0xa4,  // untouched bytes after header
267   };
268   static_assert(sizeof(kExpectedBuf) == kSize, "buffer size");
269   EXPECT_EQ(0, memcmp(kExpectedBuf, buf, kSize));
270 
271   int num_channels = 0;
272   int sample_rate = 0;
273   WavFormat format = kWavFormatPcm;
274   int bytes_per_sample = 0;
275   uint32_t num_samples = 0;
276   ReadableWavBuffer r(buf + 4, sizeof(buf) - 8);
277   EXPECT_TRUE(
278       ReadWavHeader(&r, &num_channels, &sample_rate, &format,
279                     &bytes_per_sample, &num_samples));
280   EXPECT_EQ(17, num_channels);
281   EXPECT_EQ(12345, sample_rate);
282   EXPECT_EQ(kWavFormatALaw, format);
283   EXPECT_EQ(1, bytes_per_sample);
284   EXPECT_EQ(123457689u, num_samples);
285 }
286 
287 // Try reading an atypical but valid WAV header and make sure it's parsed OK.
TEST(WavHeaderTest,ReadAtypicalWavHeader)288 TEST(WavHeaderTest, ReadAtypicalWavHeader) {
289   static const uint8_t kBuf[] = {
290     'R', 'I', 'F', 'F',
291     0x3d, 0xd1, 0x5b, 0x07,  // size of whole file - 8 + an extra 128 bytes of
292                              // "metadata": 123457689 + 44 - 8 + 128. (atypical)
293     'W', 'A', 'V', 'E',
294     'f', 'm', 't', ' ',
295     18, 0, 0, 0,  // size of fmt block (with an atypical extension size field)
296     6, 0,  // format: A-law (6)
297     17, 0,  // channels: 17
298     0x39, 0x30, 0, 0,  // sample rate: 12345
299     0xc9, 0x33, 0x03, 0,  // byte rate: 1 * 17 * 12345
300     17, 0,  // block align: NumChannels * BytesPerSample
301     8, 0,  // bits per sample: 1 * 8
302     0, 0,  // zero extension size field (atypical)
303     'd', 'a', 't', 'a',
304     0x99, 0xd0, 0x5b, 0x07,  // size of payload: 123457689
305   };
306 
307   int num_channels = 0;
308   int sample_rate = 0;
309   WavFormat format = kWavFormatPcm;
310   int bytes_per_sample = 0;
311   uint32_t num_samples = 0;
312   ReadableWavBuffer r(kBuf, sizeof(kBuf));
313   EXPECT_TRUE(
314       ReadWavHeader(&r, &num_channels, &sample_rate, &format,
315                     &bytes_per_sample, &num_samples));
316   EXPECT_EQ(17, num_channels);
317   EXPECT_EQ(12345, sample_rate);
318   EXPECT_EQ(kWavFormatALaw, format);
319   EXPECT_EQ(1, bytes_per_sample);
320   EXPECT_EQ(123457689u, num_samples);
321 }
322 
323 }  // namespace webrtc
324