16inline bool write_wav(
const char* path,
const float* data,
int samples,
int sample_rate,
int channels) {
17 FILE* f = fopen(path,
"wb");
20 const int bytes_per_sample = 3;
21 const int data_size = samples * channels * bytes_per_sample;
22 const int fmt_chunk_size = 16;
24 fwrite(
"RIFF", 1, 4, f);
25 const uint32_t file_size = 36 +
static_cast<uint32_t
>(data_size);
26 fwrite(&file_size, 4, 1, f);
27 fwrite(
"WAVE", 1, 4, f);
29 fwrite(
"fmt ", 1, 4, f);
30 fwrite(&fmt_chunk_size, 4, 1, f);
31 const uint16_t audio_format = 1;
32 fwrite(&audio_format, 2, 1, f);
33 const uint16_t num_channels =
static_cast<uint16_t
>(channels);
34 fwrite(&num_channels, 2, 1, f);
35 const uint32_t sr =
static_cast<uint32_t
>(sample_rate);
37 const uint32_t byte_rate = sr * num_channels * bytes_per_sample;
38 fwrite(&byte_rate, 4, 1, f);
39 const uint16_t block_align =
static_cast<uint16_t
>(num_channels * bytes_per_sample);
40 fwrite(&block_align, 2, 1, f);
41 const uint16_t bits_per_sample = 24;
42 fwrite(&bits_per_sample, 2, 1, f);
44 fwrite(
"data", 1, 4, f);
45 const uint32_t ds =
static_cast<uint32_t
>(data_size);
48 constexpr float SCALE = 8388607.0f;
49 for (
int i = 0; i < samples * channels; ++i) {
50 float clamped = data[i];
51 if (clamped > 1.0f) clamped = 1.0f;
52 if (clamped < -1.0f) clamped = -1.0f;
53 const int32_t s =
static_cast<int32_t
>(clamped * SCALE);
54 const uint8_t bytes[3] = {
55 static_cast<uint8_t
>(s & 0xFF),
56 static_cast<uint8_t
>((s >> 8) & 0xFF),
57 static_cast<uint8_t
>((s >> 16) & 0xFF),
59 fwrite(bytes, 1, 3, f);