20 void setFreq(
unsigned ) {}
21 uint16_t operator()(uint16_t x)
const {
return x; }
29 template<
typename Filter = NoFilter>
33 template<
typename Filter = NoFilter>
36 [[nodiscard]]
unsigned getFreq()
const {
return freq; }
37 [[nodiscard]]
unsigned getSize()
const {
return length; }
38 [[nodiscard]] int16_t
getSample(
unsigned pos)
const {
39 return (pos < length) ? buffer[pos] : int16_t(0);
44 [[nodiscard]]
static const T* read(std::span<const uint8_t> raw,
size_t offset,
size_t count = 1);
55inline const T* WavData::read(std::span<const uint8_t> raw,
size_t offset,
size_t count)
57 if ((offset +
count *
sizeof(T)) > raw.size()) {
58 throw MSXException(
"Read beyond end of wav file.");
60 return reinterpret_cast<const T*
>(raw.data() + offset);
63template<
typename Filter>
67 auto raw = file.
mmap();
69 std::array<char, 4> riffID;
71 std::array<char, 4> riffType;
72 std::array<char, 4> fmtID;
81 const auto* header = read<WavHeader>(raw, 0);
82 if ((std::string_view{header->riffID.data(), 4} !=
"RIFF") ||
83 (std::string_view{header->riffType.data(), 4} !=
"WAVE") ||
84 (std::string_view{header->fmtID.data(), 4} !=
"fmt ")) {
87 unsigned bits = header->wBitsPerSample;
88 if ((header->wFormatTag != 1) || (bits !=
one_of(8u, 16u))) {
89 throw MSXException(
"WAV format unsupported, must be 8 or 16 bit PCM.");
91 freq = header->dwSamplesPerSec;
92 unsigned channels = header->wChannels;
95 size_t pos = 20 + header->fmtSize;
99 std::array<char, 4> dataID;
102 const DataHeader* dataHeader;
105 dataHeader = read<DataHeader>(raw, pos);
106 pos +=
sizeof(DataHeader);
107 if (std::string_view{dataHeader->dataID.data(), 4} ==
"data")
break;
109 pos += dataHeader->chunkSize;
113 length = dataHeader->chunkSize / ((bits / 8) * channels);
116 auto convertLoop = [&](
const auto* in,
auto convertFunc) {
117 for (
auto i :
xrange(length)) {
118 buffer[i] =
filter(convertFunc(*in));
123 convertLoop(read<uint8_t>(raw, pos,
size_t(length) * channels),
124 [](uint8_t u8) {
return int16_t((int16_t(u8) - 0x80) << 8); });
126 convertLoop(read<Endian::L16>(raw, pos,
size_t(length) * channels),
std::span< const uint8_t > mmap()
Map file in memory.
void resize(size_t size)
Grow or shrink the memory block.
int16_t getSample(unsigned pos) const
WavData(const std::string &filename, Filter filter={})
Construct from .wav file and optional filter.
WavData()=default
Construct empty wav.
ALWAYS_INLINE unsigned count(const uint8_t *pIn, const uint8_t *pMatch, const uint8_t *pInLimit)
This file implemented 3 utility functions:
auto filter(ForwardRange &&range, Predicate pred)
constexpr auto xrange(T e)