8 // http://mathmatrix.narod.ru/Wavefmt.html
9 char magic
[4]; // "RIFF"
10 uint32_t size
; // size of file
11 char wave_magic
[4]; // "WAVE"
12 char fmt_magic
[4]; // "fmt "
13 uint32_t wave_section_chunk_size
;
14 uint16_t wave_fmt_type
; // 1 = linear quantization
17 uint32_t bytes_per_second
;
19 uint16_t bits_per_sample
;
24 char name
[4]; // name of chunk
25 uint32_t size
; // size (bytes) of chunk (excluding header)
28 static int read_header(struct wavefile
*wav
)
34 if (fread(&whdr
, sizeof whdr
, 1, wav
->f
) < 1){
38 // check wave magic strings
39 if (strncmp(whdr
.magic
, "RIFF", 4)
40 || strncmp(whdr
.wave_magic
, "WAVE", 4)
41 || strncmp(whdr
.fmt_magic
, "fmt ", 4)){
42 // invalid file format
46 // make sure it's in PCM format
47 if (whdr
.wave_fmt_type
!= 1){
51 // store format information
52 wav
->format
.srate
= whdr
.srate
;
53 wav
->format
.bits
= whdr
.bits_per_sample
;
54 wav
->format
.channels
= whdr
.n_channels
;
58 if (fread(&chdr
, sizeof chdr
, 1, wav
->f
) < 1){
62 if (!strncmp(chdr
.name
, "data", 4)){
63 // found the data chunk
66 // this is not the data.
68 fseek(wav
->f
, chdr
.size
, SEEK_CUR
);
72 wav
->length
= chdr
.size
/ ((wav
->format
.bits
/ 8) * wav
->format
.channels
);
73 wav
->pcm_start
= ftell(wav
->f
);
77 int wavefile_open(struct wavefile
*wav
, const char *filename
)
80 wav
->f
= fopen(filename
, "r");
85 // read wave file header
86 return read_header(wav
);
89 int wavefile_read_at(struct wavefile
*wav
, off_t sample_start
, void *buf
, size_t n_samples
)
91 if (sample_start
+ n_samples
> wav
->length
){
92 // past the end of file
96 fseek(wav
->f
, wav
->pcm_start
+ sample_start
* aformat_get_sample_size(&wav
->format
), SEEK_SET
);
97 fread(buf
, 1, n_samples
* aformat_get_sample_size(&wav
->format
), wav
->f
);