1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/lib/wav/wav_io.h"
17
18 #include <string>
19
20 #include "tensorflow/core/lib/core/status_test_util.h"
21 #include "tensorflow/core/lib/strings/str_util.h"
22 #include "tensorflow/core/platform/test.h"
23 #include "tensorflow/core/platform/types.h"
24 #include "tensorflow/core/protobuf/error_codes.pb.h"
25
26 namespace tensorflow {
27 namespace wav {
28
29 // These are defined in wav_io.cc, and the signatures are here so we don't have
30 // to expose them in the public header.
31 Status ExpectText(const string& data, const string& expected_text, int* offset);
32 Status ReadString(const string& data, int expected_length, string* value,
33 int* offset);
34
TEST(WavIO,BadArguments)35 TEST(WavIO, BadArguments) {
36 float audio[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f};
37 tstring result;
38
39 EXPECT_EQ(error::INVALID_ARGUMENT,
40 EncodeAudioAsS16LEWav(nullptr, 44100, 2, 3, &result).code());
41 TF_EXPECT_OK(EncodeAudioAsS16LEWav(nullptr, 44100, 2, 0, &result));
42
43 EXPECT_EQ(
44 error::INVALID_ARGUMENT,
45 EncodeAudioAsS16LEWav(audio, 44100, 2, 3, (tstring*)nullptr).code());
46
47 const size_t kuint32max_plus_one = static_cast<size_t>(kuint32max) + 1;
48 const size_t kuint16max_plus_one = static_cast<size_t>(kuint16max) + 1;
49
50 // Zero values are invalid.
51 EXPECT_EQ(error::INVALID_ARGUMENT,
52 EncodeAudioAsS16LEWav(audio, 0, 2, 3, &result).code());
53 EXPECT_EQ(error::INVALID_ARGUMENT,
54 EncodeAudioAsS16LEWav(audio, 44100, 0, 3, &result).code());
55
56 // Sample rates 2^32 and greater are invalid.
57 EXPECT_EQ(
58 error::INVALID_ARGUMENT,
59 EncodeAudioAsS16LEWav(audio, kuint32max_plus_one, 2, 3, &result).code());
60
61 // Channels 2^16 and greater are invalid.
62 EXPECT_EQ(error::INVALID_ARGUMENT,
63 EncodeAudioAsS16LEWav(audio, 44100, kuint16max_plus_one, 3, &result)
64 .code());
65
66 // Frames that push the file size above 2^32 are invalid.
67 EXPECT_EQ(error::INVALID_ARGUMENT,
68 EncodeAudioAsS16LEWav(audio, 44100, 2, 1073741813, &result).code());
69 }
70
TEST(WavIO,BasicEven)71 TEST(WavIO, BasicEven) {
72 float audio[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f};
73 string result;
74 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 44100, 2, 3, &result));
75 EXPECT_EQ(56, result.size());
76 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 22050, 1, 6, &result));
77 EXPECT_EQ(56, result.size());
78 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 8000, 1, 6, &result));
79 EXPECT_EQ(56, result.size());
80 }
81
TEST(WavIO,BasicOdd)82 TEST(WavIO, BasicOdd) {
83 float audio[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f};
84 string result;
85 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 22050, 1, 5, &result));
86 EXPECT_EQ(54, result.size());
87 }
88
TEST(WavIO,EncodeThenDecode)89 TEST(WavIO, EncodeThenDecode) {
90 float audio[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f};
91 string wav_data;
92 TF_ASSERT_OK(EncodeAudioAsS16LEWav(audio, 44100, 2, 3, &wav_data));
93 std::vector<float> decoded_audio;
94 uint32 decoded_sample_count;
95 uint16 decoded_channel_count;
96 uint32 decoded_sample_rate;
97 TF_ASSERT_OK(DecodeLin16WaveAsFloatVector(
98 wav_data, &decoded_audio, &decoded_sample_count, &decoded_channel_count,
99 &decoded_sample_rate));
100 EXPECT_EQ(2, decoded_channel_count);
101 EXPECT_EQ(3, decoded_sample_count);
102 EXPECT_EQ(44100, decoded_sample_rate);
103 for (int i = 0; i < 6; ++i) {
104 EXPECT_NEAR(audio[i], decoded_audio[i], 1e-4f) << "i=" << i;
105 }
106 }
107
TEST(WavIO,BasicMono)108 TEST(WavIO, BasicMono) {
109 std::vector<uint8> wav_data = {
110 'R', 'I', 'F', 'F', // ChunkID
111 44, 0, 0, 0, // ChunkSize: 36 + SubChunk2Size
112 'W', 'A', 'V', 'E', // Format
113 'f', 'm', 't', ' ', // Subchunk1ID
114 16, 0, 0, 0, // Subchunk1Size
115 1, 0, // AudioFormat: 1=PCM
116 1, 0, // NumChannels
117 0x44, 0xac, 0, 0, // SampleRate: 44100
118 0x88, 0x58, 0x1, 0, // BytesPerSecond: SampleRate * NumChannels *
119 // BitsPerSample/8
120 2, 0, // BytesPerSample: NumChannels * BitsPerSample/8
121 16, 0, // BitsPerSample
122 'd', 'a', 't', 'a', // Subchunk2ID
123 8, 0, 0, 0, // Subchunk2Size: NumSamples * NumChannels *
124 // BitsPerSample/8
125 0, 0, // Sample 1: 0
126 0xff, 0x7f, // Sample 2: 32767 (saturated)
127 0, 0, // Sample 3: 0
128 0x00, 0x80, // Sample 4: -32768 (saturated)
129 };
130 string expected(wav_data.begin(), wav_data.end());
131 float audio[] = {0.0f, 1.0f, 0.0f, -1.0f};
132 string result;
133 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 44100, 1, 4, &result));
134 EXPECT_EQ(expected, result);
135 }
136
TEST(WavIO,BasicStereo)137 TEST(WavIO, BasicStereo) {
138 std::vector<uint8> wav_data = {
139 'R', 'I', 'F', 'F', // ChunkID
140 44, 0, 0, 0, // ChunkSize: 36 + SubChunk2Size
141 'W', 'A', 'V', 'E', // Format
142 'f', 'm', 't', ' ', // Subchunk1ID
143 16, 0, 0, 0, // Subchunk1Size
144 1, 0, // AudioFormat: 1=PCM
145 2, 0, // NumChannels
146 0x44, 0xac, 0, 0, // SampleRate: 44100
147 0x10, 0xb1, 0x2, 0, // BytesPerSecond: SampleRate * NumChannels *
148 // BitsPerSample/8
149 4, 0, // BytesPerSample: NumChannels * BitsPerSample/8
150 16, 0, // BitsPerSample
151 'd', 'a', 't', 'a', // Subchunk2ID
152 8, 0, 0, 0, // Subchunk2Size: NumSamples * NumChannels *
153 // BitsPerSample/8
154 0, 0, // Sample 1: 0
155 0xff, 0x7f, // Sample 2: 32767 (saturated)
156 0, 0, // Sample 3: 0
157 0x00, 0x80, // Sample 4: -32768 (saturated)
158 };
159 string expected(wav_data.begin(), wav_data.end());
160 float audio[] = {0.0f, 1.0f, 0.0f, -1.0f};
161 string result;
162 TF_EXPECT_OK(EncodeAudioAsS16LEWav(audio, 44100, 2, 2, &result));
163 EXPECT_EQ(expected, result);
164 }
165
166 // Test how chunk sizes larger than 2GB are handled, since they're stored as
167 // unsigned int32s, so there are lots of ways for conversions to confuse the
168 // decoding logic. The expected behavior is to fail with an error, since such
169 // large WAV files are not common, and are unsupported by many readers.
170 // See b/72655902.
TEST(WavIO,ChunkSizeOverflow)171 TEST(WavIO, ChunkSizeOverflow) {
172 std::vector<uint8> wav_data = {
173 'R', 'I', 'F', 'F', // ChunkID
174 60, 0, 0, 0, // ChunkSize: 36 + SubChunk2Size
175 'W', 'A', 'V', 'E', // Format
176 'f', 'm', 't', ' ', // Subchunk1ID
177 16, 0, 0, 0, // Subchunk1Size
178 1, 0, // AudioFormat: 1=PCM
179 1, 0, // NumChannels
180 0x44, 0xac, 0, 0, // SampleRate: 44100
181 0x88, 0x58, 0x1, 0, // BytesPerSecond: SampleRate * NumChannels *
182 // BitsPerSample/8
183 2, 0, // BytesPerSample: NumChannels * BitsPerSample/8
184 16, 0, // BitsPerSample
185 'd', 'a', 't', 'a', // Subchunk2ID
186 8, 0, 0, 0, // Subchunk2Size: NumSamples * NumChannels *
187 // BitsPerSample/8
188 0, 0, // Sample 1: 0
189 0xff, 0x7f, // Sample 2: 32767 (saturated)
190 0, 0, // Sample 3: 0
191 0x00, 0x80, // Sample 4: -32768 (saturated)
192 'f', 'o', 'o', 'o', // Subchunk2ID
193 0xff, 0xff, 0xff, 0xf8, // Chunk size that could cause an infinite loop.
194 0, 0, // Sample 1: 0
195 0xff, 0x7f, // Sample 2: 32767 (saturated)
196 0, 0, // Sample 3: 0
197 0x00, 0x80, // Sample 4: -32768 (saturated)
198 };
199 string wav_data_string(wav_data.begin(), wav_data.end());
200 std::vector<float> decoded_audio;
201 uint32 decoded_sample_count;
202 uint16 decoded_channel_count;
203 uint32 decoded_sample_rate;
204 Status decode_status = DecodeLin16WaveAsFloatVector(
205 wav_data_string, &decoded_audio, &decoded_sample_count,
206 &decoded_channel_count, &decoded_sample_rate);
207 EXPECT_FALSE(decode_status.ok());
208 EXPECT_TRUE(absl::StrContains(decode_status.error_message(), "too large"))
209 << decode_status.error_message();
210 }
211
TEST(WavIO,IncrementOffset)212 TEST(WavIO, IncrementOffset) {
213 int new_offset = -1;
214 TF_EXPECT_OK(IncrementOffset(0, 10, 20, &new_offset));
215 EXPECT_EQ(10, new_offset);
216
217 new_offset = -1;
218 TF_EXPECT_OK(IncrementOffset(10, 4, 20, &new_offset));
219 EXPECT_EQ(14, new_offset);
220
221 new_offset = -1;
222 TF_EXPECT_OK(IncrementOffset(99, 1, 100, &new_offset));
223 EXPECT_EQ(100, new_offset);
224
225 new_offset = -1;
226 EXPECT_FALSE(IncrementOffset(-1, 1, 100, &new_offset).ok());
227
228 new_offset = -1;
229 EXPECT_FALSE(IncrementOffset(0, -1, 100, &new_offset).ok());
230
231 new_offset = -1;
232 EXPECT_FALSE(IncrementOffset(std::numeric_limits<int>::max(), 1,
233 std::numeric_limits<int>::max(), &new_offset)
234 .ok());
235
236 new_offset = -1;
237 EXPECT_FALSE(IncrementOffset(101, 1, 100, &new_offset).ok());
238 }
239
TEST(WavIO,ExpectText)240 TEST(WavIO, ExpectText) {
241 std::vector<uint8> test_data = {
242 'E', 'x', 'p', 'e', 'c', 't', 'e', 'd',
243 };
244 string test_string(test_data.begin(), test_data.end());
245
246 int offset = 0;
247 TF_EXPECT_OK(ExpectText(test_string, "Expected", &offset));
248 EXPECT_EQ(8, offset);
249
250 offset = 0;
251 Status expect_status = ExpectText(test_string, "Unexpected", &offset);
252 EXPECT_FALSE(expect_status.ok());
253
254 offset = 0;
255 TF_EXPECT_OK(ExpectText(test_string, "Exp", &offset));
256 EXPECT_EQ(3, offset);
257 TF_EXPECT_OK(ExpectText(test_string, "ected", &offset));
258 EXPECT_EQ(8, offset);
259 expect_status = ExpectText(test_string, "foo", &offset);
260 EXPECT_FALSE(expect_status.ok());
261 }
262
TEST(WavIO,ReadString)263 TEST(WavIO, ReadString) {
264 std::vector<uint8> test_data = {
265 'E', 'x', 'p', 'e', 'c', 't', 'e', 'd',
266 };
267 string test_string(test_data.begin(), test_data.end());
268
269 int offset = 0;
270 string read_value;
271 TF_EXPECT_OK(ReadString(test_string, 2, &read_value, &offset));
272 EXPECT_EQ("Ex", read_value);
273 EXPECT_EQ(2, offset);
274
275 TF_EXPECT_OK(ReadString(test_string, 6, &read_value, &offset));
276 EXPECT_EQ("pected", read_value);
277 EXPECT_EQ(8, offset);
278
279 Status read_status = ReadString(test_string, 3, &read_value, &offset);
280 EXPECT_FALSE(read_status.ok());
281 }
282
TEST(WavIO,ReadValueInt8)283 TEST(WavIO, ReadValueInt8) {
284 std::vector<uint8> test_data = {0x00, 0x05, 0xff, 0x80};
285 string test_string(test_data.begin(), test_data.end());
286
287 int offset = 0;
288 int8_t read_value;
289 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
290 EXPECT_EQ(0, read_value);
291 EXPECT_EQ(1, offset);
292
293 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
294 EXPECT_EQ(5, read_value);
295 EXPECT_EQ(2, offset);
296
297 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
298 EXPECT_EQ(-1, read_value);
299 EXPECT_EQ(3, offset);
300
301 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
302 EXPECT_EQ(-128, read_value);
303 EXPECT_EQ(4, offset);
304
305 Status read_status = ReadValue(test_string, &read_value, &offset);
306 EXPECT_FALSE(read_status.ok());
307 }
308
TEST(WavIO,ReadValueUInt8)309 TEST(WavIO, ReadValueUInt8) {
310 std::vector<uint8> test_data = {0x00, 0x05, 0xff, 0x80};
311 string test_string(test_data.begin(), test_data.end());
312
313 int offset = 0;
314 uint8 read_value;
315 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
316 EXPECT_EQ(0, read_value);
317 EXPECT_EQ(1, offset);
318
319 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
320 EXPECT_EQ(5, read_value);
321 EXPECT_EQ(2, offset);
322
323 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
324 EXPECT_EQ(255, read_value);
325 EXPECT_EQ(3, offset);
326
327 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
328 EXPECT_EQ(128, read_value);
329 EXPECT_EQ(4, offset);
330
331 Status read_status = ReadValue(test_string, &read_value, &offset);
332 EXPECT_FALSE(read_status.ok());
333 }
334
TEST(WavIO,ReadValueInt16)335 TEST(WavIO, ReadValueInt16) {
336 std::vector<uint8> test_data = {
337 0x00, 0x00, // 0
338 0xff, 0x00, // 255
339 0x00, 0x01, // 256
340 0xff, 0xff, // -1
341 0x00, 0x80, // -32768
342 };
343 string test_string(test_data.begin(), test_data.end());
344
345 int offset = 0;
346 int16_t read_value;
347 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
348 EXPECT_EQ(0, read_value);
349 EXPECT_EQ(2, offset);
350
351 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
352 EXPECT_EQ(255, read_value);
353 EXPECT_EQ(4, offset);
354
355 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
356 EXPECT_EQ(256, read_value);
357 EXPECT_EQ(6, offset);
358
359 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
360 EXPECT_EQ(-1, read_value);
361 EXPECT_EQ(8, offset);
362
363 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
364 EXPECT_EQ(-32768, read_value);
365 EXPECT_EQ(10, offset);
366
367 Status read_status = ReadValue(test_string, &read_value, &offset);
368 EXPECT_FALSE(read_status.ok());
369 }
370
TEST(WavIO,ReadValueUInt16)371 TEST(WavIO, ReadValueUInt16) {
372 std::vector<uint8> test_data = {
373 0x00, 0x00, // 0
374 0xff, 0x00, // 255
375 0x00, 0x01, // 256
376 0xff, 0xff, // 65535
377 0x00, 0x80, // 32768
378 };
379 string test_string(test_data.begin(), test_data.end());
380
381 int offset = 0;
382 uint16 read_value;
383 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
384 EXPECT_EQ(0, read_value);
385 EXPECT_EQ(2, offset);
386
387 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
388 EXPECT_EQ(255, read_value);
389 EXPECT_EQ(4, offset);
390
391 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
392 EXPECT_EQ(256, read_value);
393 EXPECT_EQ(6, offset);
394
395 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
396 EXPECT_EQ(65535, read_value);
397 EXPECT_EQ(8, offset);
398
399 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
400 EXPECT_EQ(32768, read_value);
401 EXPECT_EQ(10, offset);
402
403 Status read_status = ReadValue(test_string, &read_value, &offset);
404 EXPECT_FALSE(read_status.ok());
405 }
406
TEST(WavIO,ReadValueInt32)407 TEST(WavIO, ReadValueInt32) {
408 std::vector<uint8> test_data = {
409 0x00, 0x00, 0x00, 0x00, // 0
410 0xff, 0x00, 0x00, 0x00, // 255
411 0x00, 0xff, 0x00, 0x00, // 65280
412 0x00, 0x00, 0xff, 0x00, // 16,711,680
413 0xff, 0xff, 0xff, 0xff, // -1
414 };
415 string test_string(test_data.begin(), test_data.end());
416
417 int offset = 0;
418 int32_t read_value;
419 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
420 EXPECT_EQ(0, read_value);
421 EXPECT_EQ(4, offset);
422
423 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
424 EXPECT_EQ(255, read_value);
425 EXPECT_EQ(8, offset);
426
427 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
428 EXPECT_EQ(65280, read_value);
429 EXPECT_EQ(12, offset);
430
431 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
432 EXPECT_EQ(16711680, read_value);
433 EXPECT_EQ(16, offset);
434
435 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
436 EXPECT_EQ(-1, read_value);
437 EXPECT_EQ(20, offset);
438
439 Status read_status = ReadValue(test_string, &read_value, &offset);
440 EXPECT_FALSE(read_status.ok());
441 }
442
TEST(WavIO,ReadValueUInt32)443 TEST(WavIO, ReadValueUInt32) {
444 std::vector<uint8> test_data = {
445 0x00, 0x00, 0x00, 0x00, // 0
446 0xff, 0x00, 0x00, 0x00, // 255
447 0x00, 0xff, 0x00, 0x00, // 65280
448 0x00, 0x00, 0xff, 0x00, // 16,711,680
449 0xff, 0xff, 0xff, 0xff, // 4,294,967,295
450 };
451 string test_string(test_data.begin(), test_data.end());
452
453 int offset = 0;
454 uint32 read_value;
455 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
456 EXPECT_EQ(0, read_value);
457 EXPECT_EQ(4, offset);
458
459 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
460 EXPECT_EQ(255, read_value);
461 EXPECT_EQ(8, offset);
462
463 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
464 EXPECT_EQ(65280, read_value);
465 EXPECT_EQ(12, offset);
466
467 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
468 EXPECT_EQ(16711680, read_value);
469 EXPECT_EQ(16, offset);
470
471 TF_EXPECT_OK(ReadValue(test_string, &read_value, &offset));
472 EXPECT_EQ(4294967295, read_value);
473 EXPECT_EQ(20, offset);
474
475 Status read_status = ReadValue(test_string, &read_value, &offset);
476 EXPECT_FALSE(read_status.ok());
477 }
478
479 } // namespace wav
480 } // namespace tensorflow
481