1 /* $NetBSD: wav.c,v 1.8 2008/05/29 14:51:27 mrg Exp $ */
4 * Copyright (c) 2002, 2009 Matthew R. Green
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * WAV support for the audio tools; thanks go to the sox utility for
31 * clearing up issues with WAV files.
33 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: wav.c,v 1.8 2008/05/29 14:51:27 mrg Exp $");
40 #include <sys/types.h>
41 #include <sys/audioio.h>
42 #include <sys/ioctl.h>
58 { WAVE_FORMAT_UNKNOWN
, "Microsoft Official Unknown" },
59 { WAVE_FORMAT_PCM
, "Microsoft PCM" },
60 { WAVE_FORMAT_ADPCM
, "Microsoft ADPCM" },
61 { WAVE_FORMAT_ALAW
, "Microsoft A-law" },
62 { WAVE_FORMAT_MULAW
, "Microsoft mu-law" },
63 { WAVE_FORMAT_OKI_ADPCM
,"OKI ADPCM" },
64 { WAVE_FORMAT_DIGISTD
, "Digistd format" },
65 { WAVE_FORMAT_DIGIFIX
, "Digifix format" },
70 wav_enc_from_val(int encoding
)
74 for (i
= 0; wavencs
[i
].wenc
!= -1; i
++)
75 if (wavencs
[i
].wenc
== encoding
)
77 return (wavencs
[i
].wname
);
85 * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@
92 * find a .wav header, etc. returns header length on success
95 audio_wav_parse_hdr(hdr
, sz
, enc
, prec
, sample
, channels
, datasize
)
104 char *where
= hdr
, *owhere
;
105 wav_audioheaderpart part
;
106 wav_audioheaderfmt fmt
;
107 wav_audiohdrextensible ext
;
108 char *end
= (((char *)hdr
) + sz
);
109 u_int newenc
, newprec
;
118 return (AUDIO_ENOENT
);
120 if (strncmp(where
, strRIFF
, sizeof strRIFF
))
121 return (AUDIO_ENOENT
);
123 if (strncmp(where
, strWAVE
, sizeof strWAVE
))
124 return (AUDIO_ENOENT
);
128 memcpy(&part
, where
, sizeof part
);
130 where
+= getle32(part
.len
) + 8;
131 } while (where
< end
&& strncmp(part
.name
, strfmt
, sizeof strfmt
));
134 if (where
+ sizeof fmt
> end
)
135 return (AUDIO_ESHORTHDR
);
137 memcpy(&fmt
, (owhere
+ 8), sizeof fmt
);
139 fmttag
= getle16(fmt
.tag
);
141 printf("WAVE format tag: %x\n", fmttag
);
143 if (fmttag
== WAVE_FORMAT_EXTENSIBLE
) {
144 if ((uintptr_t)(where
- owhere
) < sizeof(fmt
) + sizeof(ext
))
145 return (AUDIO_ESHORTHDR
);
146 memcpy(&ext
, owhere
+ sizeof fmt
, sizeof ext
);
147 if (getle16(ext
.len
) < sizeof(ext
) - sizeof(ext
.len
))
148 return (AUDIO_ESHORTHDR
);
149 fmttag
= ext
.sub_tag
;
151 printf("WAVE extensible sub tag: %x\n", fmttag
);
155 case WAVE_FORMAT_UNKNOWN
:
156 case IBM_FORMAT_MULAW
:
157 case IBM_FORMAT_ALAW
:
158 case IBM_FORMAT_ADPCM
:
160 return (AUDIO_EWAVUNSUPP
);
162 case WAVE_FORMAT_PCM
:
163 case WAVE_FORMAT_ADPCM
:
164 case WAVE_FORMAT_OKI_ADPCM
:
165 case WAVE_FORMAT_IMA_ADPCM
:
166 case WAVE_FORMAT_DIGIFIX
:
167 case WAVE_FORMAT_DIGISTD
:
168 switch (getle16(fmt
.bits_per_sample
)) {
182 return (AUDIO_EWAVBADPCM
);
185 newenc
= AUDIO_ENCODING_ULINEAR_LE
;
187 newenc
= AUDIO_ENCODING_SLINEAR_LE
;
189 case WAVE_FORMAT_ALAW
:
190 newenc
= AUDIO_ENCODING_ALAW
;
193 case WAVE_FORMAT_MULAW
:
194 newenc
= AUDIO_ENCODING_ULAW
;
200 memcpy(&part
, where
, sizeof part
);
202 where
+= (getle32(part
.len
) + 8);
203 } while (where
< end
&& strncmp(part
.name
, strdata
, sizeof strdata
));
205 if ((where
- getle32(part
.len
)) <= end
) {
207 *channels
= (u_int
)getle16(fmt
.channels
);
209 *sample
= getle32(fmt
.sample_rate
);
215 *datasize
= (size_t)getle32(part
.len
);
216 return (owhere
- (char *)hdr
+ 8);
218 return (AUDIO_EWAVNODATA
);