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
7using namespace openmsx;
8
9TEST_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
19TEST_CASE("WavData, parser")
20{
21 SECTION("empty file") {
22 File file = memory_buffer_file(std::span<const uint8_t>());
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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
100TEST_CASE("WavData, content")
101{
102 SECTION("mono, 8 bit") {
103 // samples get converted 8bit -> 16bit
104 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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 static constexpr auto buffer = std::to_array<uint8_t>({
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}
TEST_CASE("WavData, default constructor")
int16_t getSample(unsigned pos) const
Definition WavData.hh:41
unsigned getSize() const
Definition WavData.hh:40
unsigned getFreq() const
Definition WavData.hh:39
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition Autofire.cc:11
File memory_buffer_file(std::span< const uint8_t > buffer)
constexpr auto xrange(T e)
Definition xrange.hh:132