Remove libasound dependency. We're using OSS.
[aftubes.git] / wavefile.c
blob82cbb1ad5fef6f8b8e83105f11e83410d7561b3a
1 #include "wavefile.h"
2 #include "stdint.h"
3 #include "assert.h"
4 #include "string.h"
6 struct wavehdr
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
15 uint16_t n_channels;
16 uint32_t srate;
17 uint32_t bytes_per_second;
18 uint16_t block_align;
19 uint16_t bits_per_sample;
22 struct chunkhdr
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)
30 struct wavehdr whdr;
31 struct chunkhdr chdr;
33 // read wave header
34 if (fread(&whdr, sizeof whdr, 1, wav->f) < 1){
35 return 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
43 return 1;
46 // make sure it's in PCM format
47 if (whdr.wave_fmt_type != 1){
48 return 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;
56 // read chunk headers
57 for (;;){
58 if (fread(&chdr, sizeof chdr, 1, wav->f) < 1){
59 // read failure
60 return 1;
62 if (!strncmp(chdr.name, "data", 4)){
63 // found the data chunk
64 break;
65 } else {
66 // this is not the data.
67 // Next chunk!
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);
74 return 0;
77 int wavefile_open(struct wavefile *wav, const char *filename)
79 // open the wave file
80 wav->f = fopen(filename, "r");
81 if (!wav->f){
82 return 1;
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
93 return 1;
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);
98 return 0;