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