18 void setFreq(
unsigned ) {}
19 uint16_t operator()(uint16_t
x)
const {
return x; }
27 template<
typename Filter = NoFilter>
31 template<
typename Filter = NoFilter>
32 explicit WavData(File file, Filter filter = {});
34 [[nodiscard]]
unsigned getFreq()
const {
return freq; }
35 [[nodiscard]]
unsigned getSize()
const {
return length; }
36 [[nodiscard]] int16_t
getSample(
unsigned pos)
const {
37 return (pos < length) ? buffer[pos] : 0;
42 [[nodiscard]]
static const T* read(
span<uint8_t> raw,
size_t offset,
size_t count = 1);
55 if ((offset +
count *
sizeof(T)) > raw.
size()) {
56 throw MSXException(
"Read beyond end of wav file.");
58 return reinterpret_cast<const T*
>(raw.
data() + offset);
61 template<
typename Filter>
65 auto raw = file.
mmap();
79 const auto* header = read<WavHeader>(raw, 0);
80 if (memcmp(header->riffID,
"RIFF", 4) ||
81 memcmp(header->riffType,
"WAVE", 4) ||
82 memcmp(header->fmtID,
"fmt ", 4)) {
85 unsigned bits = header->wBitsPerSample;
86 if ((header->wFormatTag != 1) || (bits !=
one_of(8u, 16u))) {
87 throw MSXException(
"WAV format unsupported, must be 8 or 16 bit PCM.");
89 freq = header->dwSamplesPerSec;
90 unsigned channels = header->wChannels;
93 size_t pos = 20 + header->fmtSize;
100 const DataHeader* dataHeader;
103 dataHeader = read<DataHeader>(raw, pos);
104 pos +=
sizeof(DataHeader);
105 if (!memcmp(dataHeader->dataID,
"data", 4))
break;
107 pos += dataHeader->chunkSize;
111 length = dataHeader->chunkSize / ((bits / 8) * channels);
113 filter.setFreq(freq);
114 auto convertLoop = [&](
const auto* in,
auto convertFunc) {
115 for (
auto i :
xrange(length)) {
116 buffer[i] = filter(convertFunc(*in));
121 convertLoop(read<uint8_t>(raw, pos, length * channels),
122 [](uint8_t u8) {
return (int16_t(u8) - 0x80) << 8; });
124 convertLoop(read<Endian::L16>(raw, pos, length * channels),