File size: 1,620 Bytes
de996a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
54
#include "wav_writer.h"

#include <algorithm>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <stdexcept>

namespace {

void write_le32(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_le16(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_stereo(const std::string& path, const std::vector<float>& waveform,
                      int sample_rate) {
    if (waveform.empty()) {
        throw std::runtime_error("empty waveform");
    }
    const uint32_t samples = static_cast<uint32_t>(waveform.size());
    const uint32_t data_bytes = samples * sizeof(int16_t);
    std::ofstream f(path, std::ios::binary);
    if (!f) {
        throw std::runtime_error("failed to open " + path);
    }
    f.write("RIFF", 4);
    write_le32(f, 36 + data_bytes);
    f.write("WAVE", 4);
    f.write("fmt ", 4);
    write_le32(f, 16);
    write_le16(f, 1);
    write_le16(f, 2);  // 双声道
    write_le32(f, static_cast<uint32_t>(sample_rate));
    write_le32(f, static_cast<uint32_t>(sample_rate) * 2 * 2);
    write_le16(f, 4);
    write_le16(f, 16);
    f.write("data", 4);
    write_le32(f, data_bytes);
    for (float v : waveform) {
        v = std::max(-1.0f, std::min(1.0f, v));
        write_le16(f, static_cast<uint16_t>(static_cast<int16_t>(std::round(v * 32767.0f))));
    }
}