-
Notifications
You must be signed in to change notification settings - Fork 0
/
wav.cpp
129 lines (95 loc) · 2.53 KB
/
wav.cpp
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "wav.hpp"
TL_PACKED_STRUCT(WavHeader)
u32 riff_hdr;
u32 rounded_size; // this is - 8
u32 wave_hdr;
u32 fmt_hdr;
u32 dummy0;
u16 dummy1;
u16 dummy2;
u32 sample_rate;
u32 bytes_per_second;
u16 bytes_per_frame;
u16 sample_bits;
u32 data_hdr;
u32 data_size;
TL_PACKED_STRUCT_END();
#define CHECK(c) if(!(c)) goto fail
using tl::read_le;
inline u32 quad(char a, char b, char c, char d) {
return (u32)a + ((u32)b << 8) + ((u32)c << 16) + ((u32)d << 24);
}
inline i16 sample8_to_sample16(u8 s) {
return (i16(s) - 128) * 30;
}
namespace tl {
int write_wav(Sink& dest, VecSlice<u8 const>& sound) {
WavHeader header;
header.riff_hdr = quad('R', 'I', 'F', 'F');
header.wave_hdr = quad('W', 'A', 'V', 'E');
header.fmt_hdr = quad('f', 'm', 't', ' ');
header.dummy0 = 16;
header.dummy1 = 1;
header.dummy2 = 1;
header.sample_rate = 22050;
header.bytes_per_second = 22050 * 1 * 1;
header.bytes_per_frame = 1 * 1;
header.sample_bits = 8;
header.data_hdr = quad('d', 'a', 't', 'a');
header.data_size = sound.size() * 1 * 1;
auto rounded_size = (sound.size() + 1) & ~1;
CHECK(!dest.put_raw<WavHeader>(header));
{
auto w = dest.window(rounded_size);
CHECK(!w.empty());
u8* destp = w.begin();
for (usize i = 0; i < sound.size(); ++i) {
*destp++ = u8(sound[i] + 128);
}
if (rounded_size != sound.size()) {
*destp++ = 0;
}
}
return 0;
fail:
return 1;
}
int read_wav(
tl::Source src,
tl::Vec<i16>& sound) {
auto hdr = src.window(sizeof(WavHeader));
CHECK(!hdr.empty());
WavHeader const* header = (WavHeader const*)hdr.begin();
CHECK(read_le(header->riff_hdr) == quad('R', 'I', 'F', 'F'));
CHECK(read_le(header->wave_hdr) == quad('W', 'A', 'V', 'E'));
CHECK(read_le(header->dummy0) == 16);
CHECK(read_le(header->dummy1) == 1);
CHECK(read_le(header->dummy2) == 1);
CHECK(read_le(header->sample_rate) == 22050);
CHECK(read_le(header->bytes_per_second) == 22050 * 1 * 1);
CHECK(read_le(header->bytes_per_frame) == 1 * 1);
CHECK(read_le(header->sample_bits) == 8);
CHECK(read_le(header->data_hdr) == quad('d', 'a', 't', 'a'));
u32 data_size = header->data_size;
{
auto data = src.window(data_size);
CHECK(!data.empty());
sound.clear();
sound.reserve(data_size * 2);
i16 prev = sample8_to_sample16(data[0]);
i16* dest = sound.begin();
*dest++ = prev;
for (u32 i = 1; i < data_size; ++i) {
i16 cur = sample8_to_sample16(data[i]);
*dest++ = (prev + cur) / 2;
*dest++ = cur;
prev = cur;
}
sound.unsafe_set_size(data_size * 2);
*dest++ = prev;
}
return 0;
fail:
return 1;
}
}