FP Perception 0.1.2
Loading...
Searching...
No Matches
wav.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <fstream>
4#include <vector>
5#include <cstdint>
6#include <string>
7#include <cstring>
8#include <stdexcept>
11
12namespace fp_perception
13{
14
22void writeWavStream(std::ostream& out, const audio_data& data)
23{
24 if (!out)
25 throw fp_perception_exception("Output stream is not valid");
26
27 uint32_t data_size = data.samples.size() * sizeof(int16_t);
28 uint32_t fmt_chunk_size = 16;
29 uint16_t audio_format = 1; // PCM
30 uint16_t bits_per_sample = 16;
31 uint32_t byte_rate = data.sample_rate * data.channels * bits_per_sample / 8;
32 uint16_t block_align = data.channels * bits_per_sample / 8;
33 uint32_t chunk_size = 4 + (8 + fmt_chunk_size) + (8 + data_size);
34
35 // Write WAV header
36 out.write("RIFF", 4);
37 out.write(reinterpret_cast<const char*>(&chunk_size), 4);
38 out.write("WAVE", 4);
39
40 // fmt subchunk
41 out.write("fmt ", 4);
42 out.write(reinterpret_cast<const char*>(&fmt_chunk_size), 4);
43 out.write(reinterpret_cast<const char*>(&audio_format), 2);
44 out.write(reinterpret_cast<const char*>(&data.channels), 2);
45 out.write(reinterpret_cast<const char*>(&data.sample_rate), 4);
46 out.write(reinterpret_cast<const char*>(&byte_rate), 4);
47 out.write(reinterpret_cast<const char*>(&block_align), 2);
48 out.write(reinterpret_cast<const char*>(&bits_per_sample), 2);
49
50 // data subchunk
51 out.write("data", 4);
52 out.write(reinterpret_cast<const char*>(&data_size), 4);
53 out.write(reinterpret_cast<const char*>(data.samples.data()), data_size);
54}
55
63void writeWavFile(const std::string& filename, const audio_data& data)
64{
65 std::ofstream out(filename, std::ios::binary);
66 writeWavStream(out, data);
67 out.close();
68}
69
77audio_data readWavFile(const std::string& filepath)
78{
79 std::ifstream in(filepath, std::ios::binary);
80 if (!in)
81 throw fp_perception_exception("Failed to open WAV file: " + filepath);
82
83 char riff_header[4];
84 in.read(riff_header, 4);
85 if (std::strncmp(riff_header, "RIFF", 4) != 0)
86 throw fp_perception_exception("Invalid WAV file: Missing 'RIFF'");
87
88 in.seekg(20);
89 uint16_t audio_format = 0;
90 in.read(reinterpret_cast<char*>(&audio_format), 2);
91 if (audio_format != 1)
92 throw fp_perception_exception("Unsupported WAV format: Only PCM is supported");
93
94 uint16_t channels = 0;
95 in.read(reinterpret_cast<char*>(&channels), 2);
96
97 uint32_t sample_rate = 0;
98 in.read(reinterpret_cast<char*>(&sample_rate), 4);
99
100 in.seekg(34);
101 uint16_t bits_per_sample = 0;
102 in.read(reinterpret_cast<char*>(&bits_per_sample), 2);
103 if (bits_per_sample != 16)
104 throw fp_perception_exception("Unsupported bit depth: Only 16-bit PCM is supported");
105
106 // Seek to 'data' subchunk
107 char chunk_id[4];
108 uint32_t chunk_size = 0;
109 while (in.read(chunk_id, 4))
110 {
111 in.read(reinterpret_cast<char*>(&chunk_size), 4);
112 if (std::strncmp(chunk_id, "data", 4) == 0)
113 break;
114
115 // Skip other chunks
116 in.seekg(chunk_size, std::ios::cur);
117 }
118
119 if (std::strncmp(chunk_id, "data", 4) != 0)
120 throw fp_perception_exception("Invalid WAV file: Missing 'data' chunk");
121
122 // Read samples
123 std::vector<int16_t> samples(chunk_size / sizeof(int16_t));
124 in.read(reinterpret_cast<char*>(samples.data()), chunk_size);
125
126 audio_data audio;
127 audio.samples = std::move(samples);
128 audio.sample_rate = static_cast<int>(sample_rate);
129 audio.channels = static_cast<int>(channels);
130 audio.chunk_size = 256; // default
131 audio.override = true;
132
133 return audio;
134}
135
143std::vector<char> encodeWavToBytes(const fp_perception::audio_data& data)
144{
145 std::ostringstream oss(std::ios::binary);
146 writeWavStream(oss, data);
147 std::string str = oss.str();
148 return std::vector<char>(str.begin(), str.end());
149}
150
151} // namespace fp_perception
Definition audio_buffer.hpp:16
void writeWavFile(const std::string &filename, const audio_data &data)
Write audio data to a WAV file.
Definition wav.hpp:63
std::vector< char > encodeWavToBytes(const fp_perception::audio_data &data)
Encode audio data to a WAV file and return as a byte vector.
Definition wav.hpp:143
void writeWavStream(std::ostream &out, const audio_data &data)
Write audio data to a WAV file using an output stream.
Definition wav.hpp:22
audio_data readWavFile(const std::string &filepath)
Read audio data from a WAV file.
Definition wav.hpp:77
Struct to hold audio data.
Definition structs.hpp:16
std::vector< int16_t > samples
Audio samples.
Definition structs.hpp:17
int sample_rate
Sample rate in Hz.
Definition structs.hpp:18
int channels
Number of audio channels.
Definition structs.hpp:19
bool override
if the system sample_rate, channels, and chunk_size should be overridden by message data
Definition structs.hpp:22
int chunk_size
Size of each audio chunk in samples.
Definition structs.hpp:20
Base class for driver exceptions.
Definition exceptions.hpp:14