1 /*
2 * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12 #include "iamf/cli/wav_writer.h"
13
14 #include <cstddef>
15 #include <cstdint>
16 #include <filesystem>
17 #include <numeric>
18 #include <string>
19 #include <system_error>
20 #include <utility>
21 #include <vector>
22
23 #include "absl/status/status_matchers.h"
24 #include "absl/types/span.h"
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "iamf/cli/tests/cli_test_utils.h"
28 #include "iamf/cli/wav_reader.h"
29
30 using ::absl_testing::IsOk;
31
32 namespace iamf_tools {
33 namespace {
34
35 constexpr int kNumChannels = 1;
36 constexpr int kTwoChannels = 2;
37 constexpr int kSampleRateHz = 16000;
38 constexpr int kBitDepth16 = 16;
39 constexpr int kBitDepth24 = 24;
40 constexpr int kBitDepth32 = 32;
41 constexpr size_t kMaxInputSamplesPerFrame = 960;
42
43 constexpr int32_t kSampleValue = 0x00000000;
44
TEST(WavWriterTest,Construct16BitWavWriter)45 TEST(WavWriterTest, Construct16BitWavWriter) {
46 auto wav_writer =
47 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
48 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
49 ASSERT_NE(wav_writer, nullptr);
50 EXPECT_EQ(wav_writer->bit_depth(), kBitDepth16);
51 }
52
TEST(WavWriterTest,Construct16BitWavWriterWithoutHeader)53 TEST(WavWriterTest, Construct16BitWavWriterWithoutHeader) {
54 auto wav_writer =
55 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
56 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame,
57 /*write_header=*/false);
58 ASSERT_NE(wav_writer, nullptr);
59 EXPECT_EQ(wav_writer->bit_depth(), kBitDepth16);
60 }
61
TEST(WavWriterTest,Construct24BitWavWriter)62 TEST(WavWriterTest, Construct24BitWavWriter) {
63 auto wav_writer =
64 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
65 kSampleRateHz, kBitDepth24, kMaxInputSamplesPerFrame);
66 ASSERT_NE(wav_writer, nullptr);
67 EXPECT_EQ(wav_writer->bit_depth(), kBitDepth24);
68 }
69
TEST(WavWriterTest,Construct32BitWavWriter)70 TEST(WavWriterTest, Construct32BitWavWriter) {
71 auto wav_writer =
72 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
73 kSampleRateHz, kBitDepth32, kMaxInputSamplesPerFrame);
74 ASSERT_NE(wav_writer, nullptr);
75 EXPECT_EQ(wav_writer->bit_depth(), kBitDepth32);
76 }
77
TEST(WavWriterTest,InvalidBitDepthFailsAtCreation)78 TEST(WavWriterTest, InvalidBitDepthFailsAtCreation) {
79 const int kInvalidBitDepth = 13;
80 auto wav_writer = WavWriter::Create(
81 GetAndCleanupOutputFileName(".wav"), kNumChannels, kSampleRateHz,
82 kInvalidBitDepth, kMaxInputSamplesPerFrame);
83 EXPECT_EQ(wav_writer, nullptr);
84 }
85
TEST(DeprecatedWritePcmSamples,WriteEmptySamplesSucceeds)86 TEST(DeprecatedWritePcmSamples, WriteEmptySamplesSucceeds) {
87 auto wav_writer =
88 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
89 kSampleRateHz, kBitDepth24, kMaxInputSamplesPerFrame);
90 ASSERT_NE(wav_writer, nullptr);
91
92 const std::vector<uint8_t> kEmptySamples;
93 EXPECT_THAT(wav_writer->WritePcmSamples(kEmptySamples), IsOk());
94 }
95
TEST(PushFrame,WriteEmptySamplesSucceeds)96 TEST(PushFrame, WriteEmptySamplesSucceeds) {
97 auto wav_writer =
98 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
99 kSampleRateHz, kBitDepth24, kMaxInputSamplesPerFrame);
100 ASSERT_NE(wav_writer, nullptr);
101
102 const std::vector<std::vector<int32_t>> kEmptySamples;
103 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kEmptySamples)),
104 IsOk());
105 }
106
TEST(DeprecatedWritePcmSamples,WriteIntegerSamplesSucceeds)107 TEST(DeprecatedWritePcmSamples, WriteIntegerSamplesSucceeds) {
108 auto wav_writer =
109 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
110 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
111 ASSERT_NE(wav_writer, nullptr);
112
113 // Bit depth = 16, and writing 6 bytes = 48 bits = 3 samples succeeds.
114 std::vector<uint8_t> samples(6, 0);
115 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
116 }
117
TEST(PushFrame,WriteIntegerSamplesSucceeds)118 TEST(PushFrame, WriteIntegerSamplesSucceeds) {
119 auto wav_writer =
120 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
121 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
122 ASSERT_NE(wav_writer, nullptr);
123
124 constexpr int kNumSamples = 3;
125 const std::vector<std::vector<int32_t>> samples(
126 kNumSamples, std::vector<int32_t>(kNumChannels, kSampleValue));
127 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(samples)), IsOk());
128 }
129
TEST(PushFrame,WriteManyChannelsSucceeds)130 TEST(PushFrame, WriteManyChannelsSucceeds) {
131 // The wav writer samples supports many channels. For example, it could
132 // represent a 9.1.6 channel layout using 16 channels.
133 constexpr int kNumChannels = 16;
134 auto wav_writer =
135 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
136 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
137 ASSERT_NE(wav_writer, nullptr);
138
139 constexpr int kNumSamples = 3;
140 const std::vector<std::vector<int32_t>> samples(
141 kNumSamples, std::vector<int32_t>(kNumChannels, kSampleValue));
142 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(samples)), IsOk());
143 }
144
TEST(DeprecatedWritePcmSamples,WriteMoreSamplesThanConfiguredFails)145 TEST(DeprecatedWritePcmSamples, WriteMoreSamplesThanConfiguredFails) {
146 constexpr size_t kMaxOneInputSample = 1;
147 auto wav_writer =
148 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
149 kSampleRateHz, kBitDepth16, kMaxOneInputSample);
150 ASSERT_NE(wav_writer, nullptr);
151
152 // Bit depth = 16, and writing 4 bytes = 32 bits = 2 samples fails.
153 std::vector<uint8_t> samples(4, 0);
154 EXPECT_FALSE(wav_writer->WritePcmSamples(samples).ok());
155 }
156
TEST(PushFrame,WriteMoreSamplesThanConfiguredFails)157 TEST(PushFrame, WriteMoreSamplesThanConfiguredFails) {
158 constexpr size_t kMaxOneInputSample = 1;
159 auto wav_writer =
160 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
161 kSampleRateHz, kBitDepth16, kMaxOneInputSample);
162 ASSERT_NE(wav_writer, nullptr);
163
164 constexpr int kTooManySamples = 2;
165 std::vector<std::vector<int32_t>> samples(
166 kNumChannels, std::vector<int32_t>(kTooManySamples, kSampleValue));
167 EXPECT_FALSE(wav_writer->PushFrame(samples).ok());
168 }
169
TEST(DeprecatedWritePcmSamples,DeprecatedWriteNonIntegerNumberOfSamplesFails)170 TEST(DeprecatedWritePcmSamples, DeprecatedWriteNonIntegerNumberOfSamplesFails) {
171 auto wav_writer =
172 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
173 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
174 ASSERT_NE(wav_writer, nullptr);
175
176 // Bit depth = 16, and writing 3 bytes = 24 bits = 1.5 samples fails.
177 std::vector<uint8_t> samples(3, 0);
178 EXPECT_FALSE(wav_writer->WritePcmSamples(samples).ok());
179 }
180
TEST(PushFrame,WriteChannelWithTooFewSamplesFails)181 TEST(PushFrame, WriteChannelWithTooFewSamplesFails) {
182 auto wav_writer =
183 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kTwoChannels,
184 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
185 ASSERT_NE(wav_writer, nullptr);
186
187 // The second tick is missing a channel.
188 const std::vector<std::vector<int32_t>> samples = {
189 {kSampleValue, kSampleValue}, {kSampleValue}};
190 EXPECT_FALSE(wav_writer->PushFrame(absl::MakeConstSpan(samples)).ok());
191 }
192
TEST(PushFrame,ConsumesInputSamples)193 TEST(PushFrame, ConsumesInputSamples) {
194 auto wav_writer =
195 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
196 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
197 ASSERT_NE(wav_writer, nullptr);
198 constexpr int kNumSamples = 3;
199 const std::vector<std::vector<int32_t>> samples(
200 kNumSamples, std::vector<int32_t>(kNumChannels, kSampleValue));
201
202 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(samples)), IsOk());
203
204 // The writer consumes all input samples, so
205 // `SampleProcessorBase::GetOutputSamplesAsSpan` will always return an empty
206 // span.
207 EXPECT_TRUE(wav_writer->GetOutputSamplesAsSpan().empty());
208 }
209
TEST(DeprecatedWritePcmSamples,DeprecatedWriteIntegerSamplesSucceedsWithoutHeader)210 TEST(DeprecatedWritePcmSamples,
211 DeprecatedWriteIntegerSamplesSucceedsWithoutHeader) {
212 auto wav_writer =
213 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
214 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame,
215 /*write_header=*/false);
216 ASSERT_NE(wav_writer, nullptr);
217
218 // Bit depth = 16, and writing 6 bytes = 48 bits = 3 samples succeeds.
219 std::vector<uint8_t> samples(6, 0);
220 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
221 }
222
TEST(DeprecatedWritePcmSamples,DeprecatedWrite24BitSamplesSucceeds)223 TEST(DeprecatedWritePcmSamples, DeprecatedWrite24BitSamplesSucceeds) {
224 auto wav_writer =
225 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
226 kSampleRateHz, kBitDepth24, kMaxInputSamplesPerFrame);
227 ASSERT_NE(wav_writer, nullptr);
228
229 // Bit depth = 24, and writing 6 bytes = 48 bits = 2 samples succeeds.
230 std::vector<uint8_t> samples(6, 0);
231 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
232 }
233
TEST(DeprecatedWritePcmSamples,DeprecatedWrite32BitSamplesSucceeds)234 TEST(DeprecatedWritePcmSamples, DeprecatedWrite32BitSamplesSucceeds) {
235 auto wav_writer =
236 WavWriter::Create(GetAndCleanupOutputFileName(".wav"), kNumChannels,
237 kSampleRateHz, kBitDepth32, kMaxInputSamplesPerFrame);
238 ASSERT_NE(wav_writer, nullptr);
239
240 // Bit depth = 32, and writing 8 bytes = 64 bits = 2 samples succeeds.
241 std::vector<uint8_t> samples = {1, 0, 0, 0, 2, 0, 0, 0};
242 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
243 }
244
TEST(DeprecatedWritePcmSamples,FileExistsAndHasNonZeroSizeWithHeader)245 TEST(DeprecatedWritePcmSamples, FileExistsAndHasNonZeroSizeWithHeader) {
246 const std::filesystem::path output_file_path(
247 GetAndCleanupOutputFileName(".wav"));
248 {
249 // Create the writer in a small scope. It should be destroyed before
250 // checking the results.
251 auto wav_writer =
252 WavWriter::Create(output_file_path.string(), kNumChannels,
253 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame);
254 }
255
256 EXPECT_TRUE(std::filesystem::exists(output_file_path));
257 std::error_code error_code;
258 EXPECT_NE(std::filesystem::file_size(output_file_path, error_code), 0);
259 EXPECT_FALSE(error_code);
260 }
261
TEST(WavWriterTest,EmptyFileExistsAndHasZeroSizeWithoutHeader)262 TEST(WavWriterTest, EmptyFileExistsAndHasZeroSizeWithoutHeader) {
263 const std::filesystem::path output_file_path(
264 GetAndCleanupOutputFileName(".wav"));
265 {
266 // Create the writer in a small scope. It should be destroyed before
267 // checking the results.
268 auto wav_writer =
269 WavWriter::Create(output_file_path.string(), kNumChannels,
270 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame,
271 /*write_header=*/false);
272 }
273
274 EXPECT_TRUE(std::filesystem::exists(output_file_path));
275
276 std::error_code error_code;
277 EXPECT_EQ(std::filesystem::file_size(output_file_path, error_code), 0)
278 << output_file_path;
279 EXPECT_FALSE(error_code);
280 }
281
TEST(WavWriterTest,OutputFileHasCorrectSizeWithoutHeader)282 TEST(WavWriterTest, OutputFileHasCorrectSizeWithoutHeader) {
283 const std::filesystem::path output_file_path(
284 GetAndCleanupOutputFileName(".wav"));
285 const int kInputBytes = 10;
286 {
287 // Create the writer in a small scope. It should be destroyed before
288 // checking the results.
289 auto wav_writer =
290 WavWriter::Create(output_file_path.string(), kNumChannels,
291 kSampleRateHz, kBitDepth16, kMaxInputSamplesPerFrame,
292 /*write_header=*/false);
293 ASSERT_NE(wav_writer, nullptr);
294 std::vector<uint8_t> samples(kInputBytes, 0);
295 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
296 }
297
298 std::error_code error_code;
299 EXPECT_EQ(std::filesystem::file_size(output_file_path, error_code),
300 kInputBytes);
301 EXPECT_FALSE(error_code);
302 }
303
TEST(WavWriterTest,Output16BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples)304 TEST(WavWriterTest,
305 Output16BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples) {
306 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
307 const std::vector<std::vector<int32_t>> kExpectedSamples = {
308 {0x01000000}, {0x03020000}, {0x05040000},
309 {0x07060000}, {0x09080000}, {0x0b0a0000}};
310 constexpr int kNumSamplesPerFrame = 6;
311 const int kInputBytes = kNumSamplesPerFrame * 2;
312 {
313 // Create the writer in a small scope. It should be destroyed before
314 // checking the results.
315 auto wav_writer =
316 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
317 kBitDepth16, kMaxInputSamplesPerFrame);
318 ASSERT_NE(wav_writer, nullptr);
319 std::vector<uint8_t> samples(kInputBytes, 0);
320 std::iota(samples.begin(), samples.end(), 0);
321 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
322 }
323
324 auto wav_reader =
325 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
326 EXPECT_EQ(wav_reader.remaining_samples(), kNumSamplesPerFrame);
327 EXPECT_TRUE(wav_reader.ReadFrame());
328 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
329 }
330
TEST(WavWriterTest,Output16BitWavFileHasCorrectDataWithPushFrameAfterDestruction)331 TEST(WavWriterTest,
332 Output16BitWavFileHasCorrectDataWithPushFrameAfterDestruction) {
333 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
334 const std::vector<std::vector<int32_t>> kExpectedSamples = {
335 {0x01000000}, {0x03020000}, {0x05040000},
336 {0x07060000}, {0x09080000}, {0x0b0a0000}};
337 constexpr int kNumSamplesPerFrame = 6;
338 {
339 // Create the writer in a small scope. The user can safely omit the call the
340 // `Flush()` method, but then they must wait until the writer is destroyed,
341 // to read the finalized header.
342 auto wav_writer =
343 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
344 kBitDepth16, kMaxInputSamplesPerFrame);
345 ASSERT_NE(wav_writer, nullptr);
346 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kExpectedSamples)),
347 IsOk());
348 }
349
350 auto wav_reader =
351 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
352 EXPECT_EQ(wav_reader.remaining_samples(), kNumSamplesPerFrame);
353 EXPECT_TRUE(wav_reader.ReadFrame());
354 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
355 }
356
TEST(WavWriterTest,Output16BitWavFileHasCorrectDataWithPushFrameAfterFlush)357 TEST(WavWriterTest, Output16BitWavFileHasCorrectDataWithPushFrameAfterFlush) {
358 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
359 const std::vector<std::vector<int32_t>> kExpectedSamples = {
360 {0x01000000}, {0x03020000}, {0x05040000},
361 {0x07060000}, {0x09080000}, {0x0b0a0000}};
362 constexpr int kNumSamplesPerFrame = 6;
363
364 auto wav_writer =
365 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
366 kBitDepth16, kMaxInputSamplesPerFrame);
367 ASSERT_NE(wav_writer, nullptr);
368 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kExpectedSamples)),
369 IsOk());
370 // Instead of waiting for the destructor to call `Flush()`, the user can call
371 // `Flush()` explicitly, to signal the wav header (including the total number
372 // of samples) to be finalized.
373 EXPECT_THAT(wav_writer->Flush(), IsOk());
374
375 auto wav_reader =
376 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
377 EXPECT_EQ(wav_reader.remaining_samples(), kNumSamplesPerFrame);
378 EXPECT_TRUE(wav_reader.ReadFrame());
379 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
380 }
381
TEST(WavWriterTest,Output24BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples)382 TEST(WavWriterTest,
383 Output24BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples) {
384 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
385 const std::vector<std::vector<int32_t>> kExpectedSamples = {
386 {0x02010000}, {0x05040300}, {0x08070600}, {0x0b0a0900}};
387 constexpr int kNumSamplesPerFrame = 4;
388 constexpr int kInputBytes = kNumSamplesPerFrame * 3;
389 {
390 // Create the writer in a small scope. It should be destroyed before
391 // checking the results.
392 auto wav_writer =
393 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
394 kBitDepth24, kMaxInputSamplesPerFrame);
395 ASSERT_NE(wav_writer, nullptr);
396 std::vector<uint8_t> samples(kInputBytes, 0);
397 std::iota(samples.begin(), samples.end(), 0);
398 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
399 }
400
401 auto wav_reader =
402 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
403 EXPECT_EQ(wav_reader.remaining_samples(), kNumSamplesPerFrame);
404 EXPECT_TRUE(wav_reader.ReadFrame());
405 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
406 }
407
TEST(WavWriterTest,Output24BitWavFileHasCorrectData)408 TEST(WavWriterTest, Output24BitWavFileHasCorrectData) {
409 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
410 const std::vector<std::vector<int32_t>> kExpectedSamples = {
411 {0x02010000}, {0x05040300}, {0x08070600}, {0x0b0a0900}};
412 constexpr int kNumSamplesPerFrame = 4;
413 {
414 // Create the writer in a small scope. It should be destroyed before
415 // checking the results.
416 auto wav_writer =
417 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
418 kBitDepth24, kMaxInputSamplesPerFrame);
419 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kExpectedSamples)),
420 IsOk());
421 }
422
423 auto wav_reader =
424 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
425 EXPECT_EQ(wav_reader.remaining_samples(), kNumSamplesPerFrame);
426 EXPECT_TRUE(wav_reader.ReadFrame());
427 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
428 }
429
TEST(WavWriterTest,Output32BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples)430 TEST(WavWriterTest,
431 Output32BitWavFileHasCorrectDataWithDeprecatedWritePcmSamples) {
432 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
433 const std::vector<std::vector<int32_t>> kExpectedSamples = {
434 {0x03020100}, {0x07060504}, {0x0b0a0908}};
435 constexpr int kNumSamplesPerFrame = 3;
436 constexpr int kInputBytes = kNumSamplesPerFrame * 4;
437 {
438 // Create the writer in a small scope. It should be destroyed before
439 // checking the results.
440 auto wav_writer =
441 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
442 kBitDepth32, kMaxInputSamplesPerFrame);
443 ASSERT_NE(wav_writer, nullptr);
444 std::vector<uint8_t> samples(kInputBytes, 0);
445 std::iota(samples.begin(), samples.end(), 0);
446 EXPECT_THAT(wav_writer->WritePcmSamples(samples), IsOk());
447 }
448
449 auto wav_reader =
450 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
451 EXPECT_EQ(wav_reader.remaining_samples(), 3);
452 EXPECT_TRUE(wav_reader.ReadFrame());
453 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
454 }
455
TEST(WavWriterTest,Output32BitWavFileHasCorrectData)456 TEST(WavWriterTest, Output32BitWavFileHasCorrectData) {
457 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
458 const std::vector<std::vector<int32_t>> kExpectedSamples = {
459 {0x03020100}, {0x07060504}, {0x0b0a0908}};
460 constexpr int kNumSamplesPerFrame = 3;
461 {
462 // Create the writer in a small scope. It should be destroyed before
463 // checking the results.
464 auto wav_writer =
465 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
466 kBitDepth32, kMaxInputSamplesPerFrame);
467 ASSERT_NE(wav_writer, nullptr);
468 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kExpectedSamples)),
469 IsOk());
470 }
471
472 auto wav_reader =
473 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
474 EXPECT_EQ(wav_reader.remaining_samples(), 3);
475 EXPECT_TRUE(wav_reader.ReadFrame());
476 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
477 }
478
TEST(WavWriterTest,OutputWithManyChannelsHasCorrectData)479 TEST(WavWriterTest, OutputWithManyChannelsHasCorrectData) {
480 constexpr int kNumChannels = 6;
481 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
482 const std::vector<std::vector<int32_t>> kExpectedSamples = {
483 {0x01010101, 0x02010101, 0x03010101, 0x04010101, 0x05010101, 0x06010101},
484 {0x01020202, 0x02020202, 0x03020202, 0x04020202, 0x05020202, 0x06020202}};
485 constexpr int kNumSamplesPerFrame = 2;
486 {
487 // Create the writer in a small scope. It should be destroyed before
488 // checking the results.
489 auto wav_writer =
490 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
491 kBitDepth32, kMaxInputSamplesPerFrame);
492 ASSERT_NE(wav_writer, nullptr);
493 EXPECT_THAT(wav_writer->PushFrame(absl::MakeConstSpan(kExpectedSamples)),
494 IsOk());
495 }
496
497 auto wav_reader =
498 CreateWavReaderExpectOk(output_file_path, kNumSamplesPerFrame);
499 EXPECT_EQ(wav_reader.remaining_samples(), 12);
500 EXPECT_TRUE(wav_reader.ReadFrame());
501 EXPECT_EQ(wav_reader.buffers_, kExpectedSamples);
502 }
503
TEST(WavWriterTest,OutputWavFileHasCorrectProperties)504 TEST(WavWriterTest, OutputWavFileHasCorrectProperties) {
505 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
506 {
507 // Create the writer in a small scope. It should be destroyed before
508 // checking the results.
509 auto wav_writer =
510 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
511 kBitDepth32, kMaxInputSamplesPerFrame);
512 ASSERT_NE(wav_writer, nullptr);
513 }
514
515 auto wav_reader = CreateWavReaderExpectOk(output_file_path);
516 EXPECT_EQ(wav_reader.sample_rate_hz(), kSampleRateHz);
517 EXPECT_EQ(wav_reader.num_channels(), kNumChannels);
518 EXPECT_EQ(wav_reader.bit_depth(), kBitDepth32);
519 }
520
TEST(WavWriterTest,OutputWavFileHasCorrectPropertiesAfterMoving)521 TEST(WavWriterTest, OutputWavFileHasCorrectPropertiesAfterMoving) {
522 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
523 {
524 auto wav_writer =
525 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
526 kBitDepth32, kMaxInputSamplesPerFrame);
527 ASSERT_NE(wav_writer, nullptr);
528
529 // Create the writer in a small scope. It should be destroyed before
530 // checking the results.
531 auto new_wav_writer = std::move(wav_writer);
532 ASSERT_NE(new_wav_writer, nullptr);
533 }
534
535 const auto wav_reader = CreateWavReaderExpectOk(output_file_path);
536 EXPECT_EQ(wav_reader.sample_rate_hz(), kSampleRateHz);
537 EXPECT_EQ(wav_reader.num_channels(), kNumChannels);
538 EXPECT_EQ(wav_reader.bit_depth(), kBitDepth32);
539 }
540
TEST(WavWriterTest,AbortDeletesOutputFile)541 TEST(WavWriterTest, AbortDeletesOutputFile) {
542 const std::string output_file_path(GetAndCleanupOutputFileName(".wav"));
543 auto wav_writer =
544 WavWriter::Create(output_file_path, kNumChannels, kSampleRateHz,
545 kBitDepth16, kMaxInputSamplesPerFrame);
546 ASSERT_NE(wav_writer, nullptr);
547 wav_writer->Abort();
548
549 // Expect that the output file is deleted.
550 EXPECT_FALSE(
551 std::filesystem::exists(std::filesystem::path(output_file_path)));
552 }
553
554 } // namespace
555 } // namespace iamf_tools
556