2 * This file is part of DisOrder
3 * Copyright (C) 2007 Richard Kettlewell
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @brief WAV file support
21 * This is used by the WAV file suppoort in the tracklength plugin and
22 * by disorder-decode (see @ref server/decode.c).
27 * http://www.technology.niagarac.on.ca/courses/comp530/WavFileFormat.html
28 * http://www.borg.com/~jglatt/tech/wave.htm
29 * http://www.borg.com/~jglatt/tech/aboutiff.htm
31 * These files consists of a header followed by chunks.
32 * Multibyte values are little-endian.
34 * 12 byte file header:
37 * 04 4 length of rest of file
40 * The length includes 'WAVE' but excludes the 1st 8 bytes.
44 * 04 4 length of rest of chunk
46 * The stated length may be odd, if so then there is an implicit padding byte
47 * appended to the chunk to make it up to an even length (someone wasn't
48 * think about 32/64-bit worlds).
50 * Also some files seem to have extra stuff at the end of chunks that nobody
51 * I know of documents. Go figure, but check the length field rather than
52 * deducing the length from the ID.
56 * 04 4 length of rest of chunk
57 * 08 2 compression (1 = none)
58 * 0a 2 number of channels
60 * 10 4 average bytes/second, = (samples/sec) * (bytes/sample)
62 * 16 2 bits/sample point
64 * 'sample' means 'sample frame' above, i.e. a sample point for each channel.
68 * 04 4 length of rest of chunk
71 * There is only allowed to be one data chunk. Some people violate this; we
72 * shall encourage people to fix their broken WAV files by not supporting
73 * this violation and because it's easier.
75 * As to the encoding of the data:
77 * Firstly, samples up to 8 bits in size are unsigned, larger samples are
80 * Secondly sample points are stored rounded up to a multiple of 8 bits in
81 * size. Marginally saner.
83 * Written as a single word (of 8, 16, 24, whatever bits) the padding to
84 * implement this happens at the right hand (least significant) end.
85 * e.g. assuming a 9 bit sample:
87 * | padded sample word |
88 * | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
89 * | 8 7 6 5 4 3 2 1 0 - - - - - - - |
91 * But this is a little-endian file format so the least significant byte is
92 * the first, which means that the padding is "between" the bits if you
93 * imagine them in their usual order:
95 * | first byte | second byte |
96 * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
97 * | 0 - - - - - - - | 8 7 6 5 4 3 2 1 |
99 * Sample points are grouped into sample frames, consisting of as many
100 * samples points as their are channels. It seems that there are standard
101 * orderings of different channels.
113 static inline uint16_t get16(const char *ptr
) {
114 return (uint8_t)ptr
[0] + 256 * (uint8_t)ptr
[1];
117 static inline uint32_t get32(const char *ptr
) {
118 return (uint8_t)ptr
[0] + 256 * (uint8_t)ptr
[1]
119 + 65536 * (uint8_t)ptr
[2] + 16777216 * (uint8_t)ptr
[3];
122 /** @brief Open a WAV file
123 * @return 0 on success, an errno value on error
125 int wav_init(struct wavfile
*f
, const char *path
) {
130 memset(f
, 0, sizeof *f
);
132 if(hreader_init(path
, f
->input
)) goto error_errno
;
133 /* Read the file header
135 * offset size meaning
137 * 04 4 length of rest of file
140 if((n
= hreader_pread(f
->input
, header
, 12, 0)) < 0) goto error_errno
;
141 else if(n
< 12) goto einval
;
142 if(strncmp(header
, "RIFF", 4) || strncmp(header
+ 8, "WAVE", 4))
144 f
->length
= 8 + get32(header
+ 4);
145 /* Visit all the chunks */
146 for(where
= 12; where
+ 8 <= f
->length
;) {
147 /* Read the chunk header
149 * offset size meaning
151 * 04 4 length of rest of chunk
153 if((n
= hreader_pread(f
->input
, header
, 8, where
)) < 0) goto error_errno
;
154 else if(n
< 8) goto einval
;
155 if(!strncmp(header
,"fmt ", 4)) {
156 /* This is the format chunk
158 * offset size meaning
160 * 04 4 length of rest of chunk
161 * 08 2 compression (1 = none)
162 * 0a 2 number of channels
163 * 0c 4 samples/second
164 * 10 4 average bytes/second, = (samples/sec) * (bytes/sample)
166 * 16 2 bits/sample point
167 * 18 ? extra undocumented rubbish
169 if(get32(header
+ 4) < 16) goto einval
;
170 if((n
= hreader_pread(f
->input
, header
+ 8, 16, where
+ 8)) < 0)
172 else if(n
< 16) goto einval
;
173 f
->channels
= get16(header
+ 0x0A);
174 f
->rate
= get32(header
+ 0x0C);
175 f
->bits
= get16(header
+ 0x16);
176 } else if(!strncmp(header
, "data", 4)) {
177 /* Remember where the data chunk was and how big it is */
179 f
->datasize
= get32(header
+ 4);
181 where
+= 8 + get32(header
+ 4);
183 /* There had better have been a format chunk */
184 if(f
->rate
== 0) goto einval
;
185 /* There had better have been a data chunk */
186 if(f
->data
== -1) goto einval
;
198 /** @brief Close a WAV file */
199 void wav_destroy(struct wavfile
*f
) {
200 hreader_close(f
->input
);
203 /** @brief Visit all the data in a WAV file
204 * @param f WAV file handle
205 * @param callback Called for successive blocks of data
208 * @p callback will only ever be passed whole frames.
210 int wav_data(struct wavfile
*f
,
211 wav_data_callback
*callback
,
213 off_t left
= f
->datasize
;
214 off_t where
= f
->data
+ 8;
218 const size_t bytes_per_frame
= f
->channels
* ((f
->bits
+ 7) / 8);
221 size_t want
= (off_t
)sizeof buffer
> left ?
(size_t)left
: sizeof buffer
;
223 want
-= want
% bytes_per_frame
;
224 if((n
= hreader_pread(f
->input
, buffer
, want
, where
)) < 0) return errno
;
225 if((size_t)n
< want
) return EINVAL
;
226 if((err
= callback(f
, buffer
, n
, u
))) return err
;