File size: 1,668 Bytes
5eee449 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include "wav_writer.h"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <fstream>
#include <stdexcept>
namespace {
void write_u32(std::ofstream& f, uint32_t v) {
char b[4] = {static_cast<char>(v & 0xff), static_cast<char>((v >> 8) & 0xff),
static_cast<char>((v >> 16) & 0xff), static_cast<char>((v >> 24) & 0xff)};
f.write(b, 4);
}
void write_u16(std::ofstream& f, uint16_t v) {
char b[2] = {static_cast<char>(v & 0xff), static_cast<char>((v >> 8) & 0xff)};
f.write(b, 2);
}
} // namespace
void write_wav(const std::string& path, const std::vector<float>& waveform,
int sample_rate) {
std::ofstream f(path, std::ios::binary);
if (!f) {
throw std::runtime_error("failed to open " + path);
}
const uint32_t data_bytes = static_cast<uint32_t>(waveform.size() * 2);
f.write("RIFF", 4);
write_u32(f, 36 + data_bytes);
f.write("WAVE", 4);
f.write("fmt ", 4);
write_u32(f, 16); // PCM chunk size
write_u16(f, 1); // PCM format
write_u16(f, 1); // mono
write_u32(f, static_cast<uint32_t>(sample_rate));
write_u32(f, static_cast<uint32_t>(sample_rate * 2)); // byte rate
write_u16(f, 2); // block align
write_u16(f, 16); // bits per sample
f.write("data", 4);
write_u32(f, data_bytes);
for (float v : waveform) {
v = std::min(1.0f, std::max(-1.0f, v));
write_u16(f, static_cast<uint16_t>(
static_cast<int16_t>(std::lround(v * 32767.0f))));
}
if (!f) {
throw std::runtime_error("failed while writing " + path);
}
}
|