10 if ((offset +
count *
sizeof(T)) > raw.size()) {
11 throw MSXException(
"Read beyond end of wav file.");
13 return reinterpret_cast<const T*
>(raw.data() + offset);
19 auto raw = file.
mmap();
33 const auto* header = read<WavHeader>(raw, 0);
34 if (memcmp(header->riffID,
"RIFF", 4) ||
35 memcmp(header->riffType,
"WAVE", 4) ||
36 memcmp(header->fmtID,
"fmt ", 4)) {
39 unsigned bits = header->wBitsPerSample;
40 if ((header->wFormatTag != 1) || ((bits != 8) && (bits != 16))) {
41 throw MSXException(
"WAV format unsupported, must be 8 or 16 bit PCM.");
43 freq = header->dwSamplesPerSec;
44 unsigned channels = header->wChannels;
47 size_t pos = 20 + header->fmtSize;
54 const DataHeader* dataHeader;
57 dataHeader = read<DataHeader>(raw, pos);
58 pos +=
sizeof(DataHeader);
59 if (!memcmp(dataHeader->dataID,
"data", 4))
break;
61 pos += dataHeader->chunkSize;
65 length = dataHeader->chunkSize / ((bits / 8) * channels);
66 buffer.resize(length);
67 auto convertLoop = [&](
const auto* in,
auto convertFunc) {
68 for (
unsigned i = 0; i < length; ++i) {
69 buffer[i] = convertFunc(*in);
74 convertLoop(read<uint8_t>(raw, pos, length * channels),
75 [](uint8_t u8) {
return (int16_t(u8) - 0x80) << 8; });
77 convertLoop(read<Endian::L16>(raw, pos, length * channels),
Thanks to enen for testing this on a real cartridge:
WavData()=default
Construct empty wav.
auto count(InputRange &&range, const T &value)
span< uint8_t > mmap()
Map file in memory.