• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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