openMSX
WavData_test.cc
Go to the documentation of this file.
1 #include "catch.hpp"
2 #include "WavData.hh"
3 #include "MemoryBufferFile.hh"
4 #include "MSXException.hh"
5 #include "xrange.hh"
6 
7 using namespace openmsx;
8 
9 TEST_CASE("WavData, default constructor")
10 {
11  WavData wav;
12  CHECK(wav.getSize() == 0);
13  CHECK(wav.getFreq() == 0);
14  for (auto i : xrange(10)) {
15  CHECK(wav.getSample(i) == 0);
16  }
17 }
18 
19 TEST_CASE("WavData, parser")
20 {
21  SECTION("empty file") {
22  uint8_t buffer[] = {};
23  File file = memory_buffer_file(span<const uint8_t>(buffer, size_t(0)));
24  try {
25  WavData wav(std::move(file));
26  CHECK(false);
27  } catch (MSXException& e) {
28  CHECK(e.getMessage() == "Read beyond end of wav file.");
29  }
30  }
31  SECTION("garbage data") {
32  // length of 'WavHeader' but contains garbage data
33  uint8_t buffer[] = {
34  0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
35  0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
36  0x20,0x21,0x22,0x23,
37  };
38  try {
39  WavData wav(memory_buffer_file(buffer));
40  CHECK(false);
41  } catch (MSXException& e) {
42  CHECK(e.getMessage() == "Invalid WAV file.");
43  }
44  }
45  SECTION("unsupported format") {
46  // header check passes, but format check fails
47  uint8_t buffer[] = {
48  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
49  0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
50  0x20,0x21,0x22,0x23,
51  };
52  try {
53  WavData wav(memory_buffer_file(buffer));
54  CHECK(false);
55  } catch (MSXException& e) {
56  CHECK(e.getMessage() == "WAV format unsupported, must be 8 or 16 bit PCM.");
57  }
58  }
59  SECTION("missing data chunk") {
60  // (almost) correct header, but missing 'data' chunk
61  uint8_t buffer[] = {
62  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
63  0x10,0x00,0x00,0x00, 0x01,0x00,0x01,0x00, 0x44,0xac,0x00,0x00, 0x88,0x58,0x01,0x00,
64  0x02,0x00,0x10,0x00,
65  };
66  try {
67  WavData wav(memory_buffer_file(buffer));
68  CHECK(false);
69  } catch (MSXException& e) {
70  CHECK(e.getMessage() == "Read beyond end of wav file.");
71  }
72  }
73  SECTION("data chunk with incorrect length") {
74  // data-chunk says there are 100 bytes sample data, but those are missing
75  uint8_t buffer[] = {
76  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
77  0x10,0x00,0x00,0x00, 0x01,0x00,0x01,0x00, 0x44,0xac,0x00,0x00, 0x88,0x58,0x01,0x00,
78  0x02,0x00,0x10,0x00, 'd', 'a', 't', 'a', 0x64,0x00,0x00,0x00,
79  };
80  try {
81  WavData wav(memory_buffer_file(buffer));
82  CHECK(false);
83  } catch (MSXException& e) {
84  CHECK(e.getMessage() == "Read beyond end of wav file.");
85  }
86  }
87  SECTION("finally a correct, but empty wav file") {
88  // (correct except for the 'riffSize' field)
89  uint8_t buffer[] = {
90  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
91  0x10,0x00,0x00,0x00, 0x01,0x00,0x01,0x00, 0x44,0xac,0x00,0x00, 0x88,0x58,0x01,0x00,
92  0x02,0x00,0x10,0x00,
93  'd', 'a', 't', 'a', 0x00,0x00,0x00,0x00,
94  };
95  WavData wav(memory_buffer_file(buffer));
96  CHECK(wav.getSize() == 0);
97  CHECK(wav.getFreq() == 44100);
98  }
99 }
100 
101 TEST_CASE("WavData, content")
102 {
103  SECTION("mono, 8 bit") {
104  // samples get converted 8bit -> 16bit
105  uint8_t buffer[] = {
106  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
107  0x10,0x00,0x00,0x00, 0x01,0x00,0x01,0x00, 0x44,0xac,0x00,0x00, 0x44,0xac,0x00,0x00,
108  0x02,0x00,0x08,0x00,
109  'd', 'a', 't', 'a', 0x05,0x00,0x00,0x00,
110  0x00, 0x45, 0x80, 0xbe, 0xff
111  };
112  WavData wav(memory_buffer_file(buffer));
113  CHECK(wav.getSize() == 5);
114  CHECK(wav.getFreq() == 44100);
115  CHECK(wav.getSample(0) == -0x8000);
116  CHECK(wav.getSample(1) == -0x3b00);
117  CHECK(wav.getSample(2) == 0x0000);
118  CHECK(wav.getSample(3) == 0x3e00);
119  CHECK(wav.getSample(4) == 0x7f00);
120  CHECK(wav.getSample(5) == 0); // past end
121  }
122  SECTION("mono, 16 bit") {
123  // samples are unmodified
124  uint8_t buffer[] = {
125  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
126  0x10,0x00,0x00,0x00, 0x01,0x00,0x01,0x00, 0x44,0xac,0x00,0x00, 0x44,0xac,0x00,0x00,
127  0x02,0x00,0x10,0x00,
128  'd', 'a', 't', 'a', 0x08,0x00,0x00,0x00,
129  0x23,0x45, 0x00,0x7e, 0xff,0xff, 0x23,0xc0
130  };
131  WavData wav(memory_buffer_file(buffer));
132  CHECK(wav.getSize() == 4);
133  CHECK(wav.getFreq() == 44100);
134  CHECK(wav.getSample(0) == 0x4523);
135  CHECK(wav.getSample(1) == 0x7e00);
136  CHECK(wav.getSample(2) == -0x0001);
137  CHECK(wav.getSample(3) == -0x3fdd);
138  CHECK(wav.getSample(4) == 0); // past end
139  CHECK(wav.getSample(5) == 0);
140  }
141  SECTION("stereo, 8 bit") {
142  // 1st channel is kept, 2nd channel gets discarded
143  uint8_t buffer[] = {
144  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
145  0x10,0x00,0x00,0x00, 0x01,0x00,0x02,0x00, 0x44,0xac,0x00,0x00, 0x44,0xac,0x00,0x00,
146  0x02,0x00,0x08,0x00,
147  'd', 'a', 't', 'a', 0x08,0x00,0x00,0x00,
148  0x00,0xff, 0x40,0xef, 0x80,0xdf, 0xc0,0xcf
149  };
150  WavData wav(memory_buffer_file(buffer));
151  CHECK(wav.getSize() == 4);
152  CHECK(wav.getFreq() == 44100);
153  CHECK(wav.getSample(0) == -0x8000);
154  CHECK(wav.getSample(1) == -0x4000);
155  CHECK(wav.getSample(2) == 0x0000);
156  CHECK(wav.getSample(3) == 0x4000);
157  CHECK(wav.getSample(4) == 0); // past end
158  }
159  SECTION("stereo, 16 bit") {
160  // 1st channel is kept, 2nd channel gets discarded
161  uint8_t buffer[] = {
162  'R', 'I', 'F', 'F', 0x04,0x05,0x06,0x07, 'W', 'A', 'V', 'E', 'f', 'm', 't' ,' ',
163  0x10,0x00,0x00,0x00, 0x01,0x00,0x02,0x00, 0x44,0xac,0x00,0x00, 0x44,0xac,0x00,0x00,
164  0x02,0x00,0x10,0x00,
165  'd', 'a', 't', 'a', 0x10,0x00,0x00,0x00,
166  0x12,0x34,0xff,0xee, 0x56,0x78,0xdd,0xcc, 0x9a,0xbc,0xbb,0xaa, 0xde,0xf0,0x99,0x88,
167  };
168  WavData wav(memory_buffer_file(buffer));
169  CHECK(wav.getSize() == 4);
170  CHECK(wav.getFreq() == 44100);
171  CHECK(wav.getSample(0) == 0x3412);
172  CHECK(wav.getSample(1) == 0x7856);
173  CHECK(wav.getSample(2) == -0x4366);
174  CHECK(wav.getSample(3) == -0x0f22);
175  CHECK(wav.getSample(4) == 0); // past end
176  }
177 }
TEST_CASE("WavData, default constructor")
Definition: WavData_test.cc:9
const std::string & getMessage() const &
Definition: MSXException.hh:23
int16_t getSample(unsigned pos) const
Definition: WavData.hh:36
unsigned getSize() const
Definition: WavData.hh:35
unsigned getFreq() const
Definition: WavData.hh:34
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition: Autofire.cc:5
File memory_buffer_file(span< const uint8_t > buffer)
constexpr auto xrange(T e)
Definition: xrange.hh:155