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 uint8_t buffer[] = {};
23 File file = memory_buffer_file(std::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
101TEST_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")
int16_t getSample(unsigned pos) const
Definition WavData.hh:38
unsigned getSize() const
Definition WavData.hh:37
unsigned getFreq() const
Definition WavData.hh:36
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition Autofire.cc:9
File memory_buffer_file(std::span< const uint8_t > buffer)
constexpr auto xrange(T e)
Definition xrange.hh:132