Sherpa-ONNX-KWS.AXERA / cpp /src /wav_reader.hpp
HY-2012's picture
First commit
dc79b9f verified
Raw
History Blame Contribute Delete
2.45 kB
#pragma once
#include <cstdint>
#include <cstring>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
struct PcmWav {
int sample_rate = 0;
std::vector<int16_t> samples;
};
inline uint16_t ReadLe16(std::istream &input) {
uint8_t bytes[2]{};
input.read(reinterpret_cast<char *>(bytes), 2);
return static_cast<uint16_t>(bytes[0]) |
(static_cast<uint16_t>(bytes[1]) << 8);
}
inline uint32_t ReadLe32(std::istream &input) {
uint8_t bytes[4]{};
input.read(reinterpret_cast<char *>(bytes), 4);
return static_cast<uint32_t>(bytes[0]) |
(static_cast<uint32_t>(bytes[1]) << 8) |
(static_cast<uint32_t>(bytes[2]) << 16) |
(static_cast<uint32_t>(bytes[3]) << 24);
}
inline PcmWav ReadPcmWav(const std::string &path) {
std::ifstream input(path, std::ios::binary);
if (!input) throw std::runtime_error("Cannot open WAV: " + path);
char riff[4]{};
char wave[4]{};
input.read(riff, 4);
ReadLe32(input);
input.read(wave, 4);
if (std::memcmp(riff, "RIFF", 4) != 0 ||
std::memcmp(wave, "WAVE", 4) != 0) {
throw std::runtime_error("Invalid RIFF/WAVE file: " + path);
}
uint16_t format = 0;
uint16_t channels = 0;
uint16_t bits = 0;
uint32_t sample_rate = 0;
std::vector<uint8_t> data;
while (input && (!format || data.empty())) {
char id[4]{};
input.read(id, 4);
if (!input) break;
const uint32_t size = ReadLe32(input);
if (std::memcmp(id, "fmt ", 4) == 0) {
if (size < 16) throw std::runtime_error("Invalid WAV fmt chunk");
format = ReadLe16(input);
channels = ReadLe16(input);
sample_rate = ReadLe32(input);
ReadLe32(input);
ReadLe16(input);
bits = ReadLe16(input);
input.seekg(size - 16, std::ios::cur);
} else if (std::memcmp(id, "data", 4) == 0) {
data.resize(size);
input.read(reinterpret_cast<char *>(data.data()), size);
} else {
input.seekg(size, std::ios::cur);
}
if (size & 1U) input.seekg(1, std::ios::cur);
}
if (format != 1 || channels != 1 || bits != 16 || sample_rate == 0 ||
data.empty() || data.size() % sizeof(int16_t) != 0) {
throw std::runtime_error("Expected mono 16-bit PCM WAV: " + path);
}
PcmWav result;
result.sample_rate = static_cast<int>(sample_rate);
result.samples.resize(data.size() / sizeof(int16_t));
std::memcpy(result.samples.data(), data.data(), data.size());
return result;
}