| |
| |
| |
| |
| |
|
|
| #pragma once |
|
|
| #include <vector> |
| #include <string> |
| #include <fstream> |
| #include <cstdint> |
| #include <cstring> |
|
|
| class WavWriter { |
| public: |
| |
| |
| |
| |
| |
| |
| |
| |
| static bool Write(const std::string& path, |
| const std::vector<float>& samples, |
| int sample_rate) { |
| std::ofstream file(path, std::ios::binary); |
| if (!file.is_open()) return false; |
|
|
| int num_samples = static_cast<int>(samples.size()); |
| int byte_rate = sample_rate * 2; |
| int data_size = num_samples * 2; |
| int chunk_size = 36 + data_size; |
|
|
| |
| Write4CC(file, "RIFF"); |
| WriteU32LE(file, chunk_size); |
| Write4CC(file, "WAVE"); |
|
|
| |
| Write4CC(file, "fmt "); |
| WriteU32LE(file, 16); |
| WriteU16LE(file, 1); |
| WriteU16LE(file, 1); |
| WriteU32LE(file, sample_rate); |
| WriteU32LE(file, byte_rate); |
| WriteU16LE(file, 2); |
| WriteU16LE(file, 16); |
|
|
| |
| Write4CC(file, "data"); |
| WriteU32LE(file, data_size); |
|
|
| |
| for (float sample : samples) { |
| |
| if (sample > 1.0f) sample = 1.0f; |
| if (sample < -1.0f) sample = -1.0f; |
| int16_t val = static_cast<int16_t>(sample * 32767.0f); |
| WriteU16LE(file, static_cast<uint16_t>(val)); |
| } |
|
|
| file.close(); |
| return true; |
| } |
|
|
| private: |
| static void WriteU16LE(std::ofstream& f, uint16_t v) { |
| f.put(v & 0xFF); |
| f.put((v >> 8) & 0xFF); |
| } |
|
|
| static void WriteU32LE(std::ofstream& f, uint32_t v) { |
| f.put(v & 0xFF); |
| f.put((v >> 8) & 0xFF); |
| f.put((v >> 16) & 0xFF); |
| f.put((v >> 24) & 0xFF); |
| } |
|
|
| static void Write4CC(std::ofstream& f, const char* s) { |
| f.write(s, 4); |
| } |
| }; |
|
|