2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
17 #include "wav_reader.h"
19 #define RIFF_FOURCC(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24))
21 typedef struct wav_reader_t
{
22 pcm_reader_vtbl_t
*vtbl
;
23 pcm_sample_description_t sample_format
;
31 static const uint8_t WAV_GUID_PCM
[] = {
32 1, 0, 0, 0, 0, 0, 0x10, 0, 0x80, 0, 0, 0xaa, 0, 0x38, 0x9b, 0x71
34 static const uint8_t WAV_GUID_FLOAT
[] = {
35 3, 0, 0, 0, 0, 0, 0x10, 0, 0x80, 0, 0, 0xaa, 0, 0x38, 0x9b, 0x71
38 static const pcm_sample_description_t
*wav_get_format(pcm_reader_t
*reader
)
40 return &((wav_reader_t
*)reader
)->sample_format
;
43 static int64_t wav_get_length(pcm_reader_t
*reader
)
45 return ((wav_reader_t
*)reader
)->length
;
48 static int64_t wav_get_position(pcm_reader_t
*reader
)
50 return ((wav_reader_t
*)reader
)->position
;
53 static void wav_teardown(pcm_reader_t
**reader
)
60 uint32_t riff_next_chunk(wav_reader_t
*reader
, uint32_t *chunk_size
)
63 return (pcm_scanl(&reader
->io
, "LL", &fcc
, chunk_size
) == 2) ? fcc
: 0;
67 int wav_read_frames(pcm_reader_t
*preader
, void *buffer
, unsigned nframes
)
71 wav_reader_t
*reader
= (wav_reader_t
*)preader
;
73 if (!reader
->ignore_length
&& nframes
> reader
->length
- reader
->position
)
74 nframes
= reader
->length
- reader
->position
;
75 nbytes
= nframes
* reader
->sample_format
.bytes_per_frame
;
77 if ((rc
= pcm_read(&reader
->io
, buffer
, nbytes
)) < 0)
79 nframes
= rc
/ reader
->sample_format
.bytes_per_frame
;
80 reader
->position
+= nframes
;
86 int riff_ds64(wav_reader_t
*reader
, int64_t *length
)
88 uint32_t fcc
, chunk_size
, table_size
;
89 uint64_t riff_size
, sample_count
;
91 fcc
= riff_next_chunk(reader
, &chunk_size
);
92 ENSURE(fcc
== RIFF_FOURCC('d','s','6','4') && chunk_size
>= 28);
93 TRY_IO(pcm_scanl(&reader
->io
, "QQQL",
94 &riff_size
, length
, &sample_count
, &table_size
) != 4);
95 TRY_IO(pcm_skip(&reader
->io
, (chunk_size
- 27) & ~1));
101 int wav_fmt(wav_reader_t
*reader
, uint32_t size
)
103 uint16_t wFormatTag
, nChannels
, nBlockAlign
, wBitsPerSample
, cbSize
;
104 uint32_t nSamplesPerSec
, nAvgBytesPerSec
, dwChannelMask
= 0;
105 uint16_t wValidBitsPerSample
;
110 TRY_IO(pcm_scanl(&reader
->io
, "SSLLSS", &wFormatTag
, &nChannels
,
111 &nSamplesPerSec
, &nAvgBytesPerSec
, &nBlockAlign
,
112 &wBitsPerSample
) != 6);
113 wValidBitsPerSample
= wBitsPerSample
;
115 ENSURE(wFormatTag
== 1 || wFormatTag
== 3 || wFormatTag
== 0xfffe);
116 ENSURE(nChannels
&& nSamplesPerSec
&& nAvgBytesPerSec
&&
117 nBlockAlign
&& wBitsPerSample
&& !(wBitsPerSample
& 7) &&
118 nBlockAlign
== nChannels
* wBitsPerSample
/ 8);
123 if (wFormatTag
!= 0xfffe)
124 TRY_IO(pcm_skip(&reader
->io
, (size
- 15) & ~1));
127 TRY_IO(pcm_scanl(&reader
->io
, "SSL",
128 &cbSize
, &wValidBitsPerSample
, &dwChannelMask
) != 3);
129 TRY_IO(pcm_read(&reader
->io
, guid
, 16) != 16);
131 if (memcmp(guid
, WAV_GUID_FLOAT
, 16) == 0)
133 else if (memcmp(guid
, WAV_GUID_PCM
, 16) != 0)
135 ENSURE(wValidBitsPerSample
&& wValidBitsPerSample
<= wBitsPerSample
);
136 TRY_IO(pcm_skip(&reader
->io
, (size
- 39) & ~1));
138 reader
->sample_format
.sample_rate
= nSamplesPerSec
;
139 reader
->sample_format
.bits_per_channel
= wValidBitsPerSample
;
140 reader
->sample_format
.bytes_per_frame
= nBlockAlign
;
141 reader
->sample_format
.channels_per_frame
= nChannels
;
142 reader
->sample_format
.channel_mask
= dwChannelMask
;
144 reader
->sample_format
.sample_type
= PCM_TYPE_FLOAT
;
145 else if (wBitsPerSample
== 8)
146 reader
->sample_format
.sample_type
= PCM_TYPE_UINT
;
148 reader
->sample_format
.sample_type
= PCM_TYPE_SINT
;
155 int wav_parse(wav_reader_t
*reader
, int64_t *data_length
)
157 uint32_t container
, fcc
, chunk_size
;
160 container
= riff_next_chunk(reader
, &chunk_size
);
161 ENSURE(container
== RIFF_FOURCC('R','I','F','F') ||
162 container
== RIFF_FOURCC('R','F','6','4'));
163 TRY_IO(pcm_read32le(&reader
->io
, &fcc
));
164 ENSURE(fcc
== RIFF_FOURCC('W','A','V','E'));
166 if (container
== RIFF_FOURCC('R','F','6','4'))
167 riff_ds64(reader
, data_length
);
168 while ((fcc
= riff_next_chunk(reader
, &chunk_size
)) != 0) {
169 if (fcc
== RIFF_FOURCC('f','m','t',' ')) {
170 if (wav_fmt(reader
, chunk_size
) < 0)
172 } else if (fcc
== RIFF_FOURCC('d','a','t','a')) {
173 if (container
== RIFF_FOURCC('R','I','F','F'))
174 *data_length
= chunk_size
;
175 reader
->data_offset
= pcm_tell(&reader
->io
);
178 TRY_IO(pcm_skip(&reader
->io
, (chunk_size
+ 1) & ~1));
181 if (fcc
== RIFF_FOURCC('d','a','t','a'))
187 static pcm_reader_vtbl_t wav_vtable
= {
195 pcm_reader_t
*wav_open(pcm_io_context_t
*io
, int ignore_length
)
197 wav_reader_t
*reader
= 0;
201 if ((reader
= calloc(1, sizeof(wav_reader_t
))) == 0)
203 memcpy(&reader
->io
, io
, sizeof(pcm_io_context_t
));
204 reader
->ignore_length
= ignore_length
;
205 if (wav_parse(reader
, &data_length
) < 0) {
209 bpf
= reader
->sample_format
.bytes_per_frame
;
210 if (ignore_length
|| !data_length
|| data_length
% bpf
)
211 reader
->length
= INT64_MAX
;
213 reader
->length
= data_length
/ bpf
;
215 if (reader
->length
== INT64_MAX
) {
216 if (pcm_seek(&reader
->io
, 0, SEEK_END
) >= 0) {
217 int64_t size
= pcm_tell(&reader
->io
);
219 reader
->length
= (size
- reader
->data_offset
) / bpf
;
220 pcm_seek(&reader
->io
, reader
->data_offset
, SEEK_SET
);
223 reader
->vtbl
= &wav_vtable
;
224 return (pcm_reader_t
*)reader
;
227 pcm_reader_t
*raw_open(pcm_io_context_t
*io
,
228 const pcm_sample_description_t
*desc
)
230 wav_reader_t
*reader
= 0;
232 if ((reader
= calloc(1, sizeof(wav_reader_t
))) == 0)
234 memcpy(&reader
->io
, io
, sizeof(pcm_io_context_t
));
235 memcpy(&reader
->sample_format
, desc
, sizeof(pcm_sample_description_t
));
236 if (pcm_seek(&reader
->io
, 0, SEEK_END
) >= 0) {
237 int64_t size
= pcm_tell(&reader
->io
);
239 reader
->length
= size
/ reader
->sample_format
.bytes_per_frame
;
240 pcm_seek(&reader
->io
, 0, SEEK_SET
);
242 reader
->length
= INT64_MAX
;
243 reader
->vtbl
= &wav_vtable
;
244 return (pcm_reader_t
*)reader
;