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