-
Notifications
You must be signed in to change notification settings - Fork 78
/
wav.h
170 lines (155 loc) · 5.26 KB
/
wav.h
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Created on 2016-08-15
* Author: Zhang Binbin
*/
#ifndef WAV_H_
#define WAV_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct WavHeader {
char riff[4]; // "riff"
unsigned int size;
char wav[4]; // "WAVE"
char fmt[4]; // "fmt "
unsigned int fmt_size; //
unsigned short format; //
unsigned short channels;
unsigned int sample_rate;
unsigned int bytes_per_second; //
unsigned short block_size;
unsigned short bit; //
char data[4]; // "data"
unsigned int data_size; //
};
class WavReader {
public:
WavReader(const char *filename) {
FILE *fp = fopen(filename, "r");
if (NULL == fp) {
perror(filename);
exit(1);
}
WavHeader header;
fread(&header, 1, sizeof(header), fp);
if (header.fmt_size < 16) {
printf("WaveData: expect PCM format data to have fmt chunk of at least size 16.\n");
exit(1);
}
else if (header.fmt_size > 16) {
int offset = 44 - 8 + header.fmt_size - 16;
fseek(fp, offset, SEEK_SET);
fread(header.data, 8, sizeof(char), fp);
}
// check "riff" "WAVE" "fmt " "data"
// only support one sub data chunk
num_channel_ = header.channels;
sample_rate_ = header.sample_rate;
bits_per_sample_ = header.bit;
int num_data = header.data_size / (bits_per_sample_ / 8);
data_ = new float[num_data];
num_sample_ = num_data / num_channel_;
for (int i = 0; i < num_data; i++) {
switch (bits_per_sample_) {
case 8: {
char sample;
fread(&sample, 1, sizeof(char), fp);
data_[i] = (float)sample;
break;
}
case 16: {
short sample;
fread(&sample, 1, sizeof(short), fp);
data_[i] = (float)sample;
break;
}
case 32: {
int sample;
fread(&sample, 1, sizeof(int), fp);
data_[i] = (float)sample;
break;
}
default:
fprintf(stderr, "unsupported quantization bits");
exit(1);
}
}
fclose(fp);
}
int NumChannel() const { return num_channel_; }
int SampleRate() const { return sample_rate_; }
int BitsPerSample() const { return bits_per_sample_; }
int NumSample() const { return num_sample_; }
~WavReader() {
if (data_ != NULL) delete data_;
}
const float *Data() const { return data_; }
private:
int num_channel_;
int sample_rate_;
int bits_per_sample_;
int num_sample_; // sample points per channel
float *data_;
};
class WavWriter {
public:
WavWriter(const float *data, int num_sample,
int num_channel, int sample_rate,
int bits_per_sample):
data_(data), num_sample_(num_sample),
num_channel_(num_channel),
sample_rate_(sample_rate),
bits_per_sample_(bits_per_sample) {}
void Write(const char *filename) {
FILE *fp = fopen(filename, "w");
// init char 'riff' 'WAVE' 'fmt ' 'data'
WavHeader header;
char wav_header[44] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61,
0x00, 0x00, 0x00, 0x00
};
memcpy(&header, wav_header, sizeof(header));
header.channels = num_channel_;
header.bit = bits_per_sample_;
header.sample_rate = sample_rate_;
header.data_size = num_sample_ * num_channel_ * (bits_per_sample_ / 8);
header.size = sizeof(header) - 8 + header.data_size;
header.bytes_per_second = sample_rate_ * num_channel_ *
(bits_per_sample_ / 8);
header.block_size = num_channel_ * (bits_per_sample_ / 8);
fwrite(&header, 1, sizeof(header), fp);
for (int i = 0; i < num_sample_; i++) {
for (int j = 0; j < num_channel_; j++) {
switch (bits_per_sample_) {
case 8: {
char sample = (char)data_[i * num_channel_ + j];
fwrite(&sample, 1, sizeof(sample), fp);
break;
}
case 16: {
short sample = (short)data_[i * num_channel_ + j];
fwrite(&sample, 1, sizeof(sample), fp);
break;
}
case 32: {
int sample = (int)data_[i * num_channel_ + j];
fwrite(&sample, 1, sizeof(sample), fp);
break;
}
}
}
}
fclose(fp);
}
private:
const float *data_;
int num_sample_; // total float points in data_
int num_channel_;
int sample_rate_;
int bits_per_sample_;
};
#endif