audio.c revision 1.1 1 1.1 mrg #include <sys/types.h>
2 1.1 mrg #include <sys/audioio.h>
3 1.1 mrg #include <sys/ioctl.h>
4 1.1 mrg #include <sys/time.h>
5 1.1 mrg
6 1.1 mrg #include <ctype.h>
7 1.1 mrg #include <err.h>
8 1.1 mrg #include <stdio.h>
9 1.1 mrg #include <stdlib.h>
10 1.1 mrg #include <string.h>
11 1.1 mrg
12 1.1 mrg #include "libaudio.h"
13 1.1 mrg
14 1.1 mrg /* back and forth between encodings */
15 1.1 mrg struct {
16 1.1 mrg char *ename;
17 1.1 mrg int eno;
18 1.1 mrg } encs[] = {
19 1.1 mrg { AudioEmulaw, AUDIO_ENCODING_ULAW },
20 1.1 mrg { "ulaw", AUDIO_ENCODING_ULAW },
21 1.1 mrg { AudioEalaw, AUDIO_ENCODING_ALAW },
22 1.1 mrg { AudioEslinear, AUDIO_ENCODING_SLINEAR },
23 1.1 mrg { "linear", AUDIO_ENCODING_SLINEAR },
24 1.1 mrg { AudioEulinear, AUDIO_ENCODING_ULINEAR },
25 1.1 mrg { AudioEadpcm, AUDIO_ENCODING_ADPCM },
26 1.1 mrg { "ADPCM", AUDIO_ENCODING_ADPCM },
27 1.1 mrg { AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE },
28 1.1 mrg { "linear_le", AUDIO_ENCODING_SLINEAR_LE },
29 1.1 mrg { AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE },
30 1.1 mrg { AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE },
31 1.1 mrg { "linear_be", AUDIO_ENCODING_SLINEAR_BE },
32 1.1 mrg { AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE },
33 1.1 mrg { AudioEmpeg_l1_stream, AUDIO_ENCODING_MPEG_L1_STREAM },
34 1.1 mrg { AudioEmpeg_l1_packets,AUDIO_ENCODING_MPEG_L1_PACKETS },
35 1.1 mrg { AudioEmpeg_l1_system, AUDIO_ENCODING_MPEG_L1_SYSTEM },
36 1.1 mrg { AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM },
37 1.1 mrg { AudioEmpeg_l2_packets,AUDIO_ENCODING_MPEG_L2_PACKETS },
38 1.1 mrg { AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM },
39 1.1 mrg { 0, -1 }
40 1.1 mrg };
41 1.1 mrg
42 1.1 mrg
43 1.1 mrg char *
44 1.1 mrg audio_enc_from_val(val)
45 1.1 mrg int val;
46 1.1 mrg {
47 1.1 mrg int i;
48 1.1 mrg
49 1.1 mrg for (i = 0; encs[i].ename; i++)
50 1.1 mrg if (encs[i].eno == val)
51 1.1 mrg break;
52 1.1 mrg return (encs[i].ename);
53 1.1 mrg }
54 1.1 mrg
55 1.1 mrg int
56 1.1 mrg audio_enc_to_val(enc)
57 1.1 mrg const char *enc;
58 1.1 mrg {
59 1.1 mrg int i;
60 1.1 mrg
61 1.1 mrg for (i = 0; encs[i].ename; i++)
62 1.1 mrg if (strcmp(encs[i].ename, enc) == 0)
63 1.1 mrg break;
64 1.1 mrg if (encs[i].ename)
65 1.1 mrg return (encs[i].eno);
66 1.1 mrg else
67 1.1 mrg return (-1);
68 1.1 mrg }
69 1.1 mrg
70 1.1 mrg int
71 1.1 mrg audio_parse_encoding(encoding_str, fd, encp, precp)
72 1.1 mrg char *encoding_str;
73 1.1 mrg int fd;
74 1.1 mrg int *encp;
75 1.1 mrg int *precp;
76 1.1 mrg {
77 1.1 mrg int i, prec = 0;
78 1.1 mrg char *colon, *star;
79 1.1 mrg
80 1.1 mrg colon = strchr(encoding_str, ':');
81 1.1 mrg if (colon) {
82 1.1 mrg *colon++ = '\0';
83 1.1 mrg if (*colon)
84 1.1 mrg prec = atoi(colon);
85 1.1 mrg }
86 1.1 mrg star = strrchr(encoding_str, '*');
87 1.1 mrg if (star)
88 1.1 mrg *star = '\0';
89 1.1 mrg for (i = 0; ; i++) {
90 1.1 mrg audio_encoding_t enc;
91 1.1 mrg
92 1.1 mrg enc.index = i;
93 1.1 mrg if (ioctl(fd, AUDIO_GETENC, &enc) < 0)
94 1.1 mrg break;
95 1.1 mrg
96 1.1 mrg if (strcasecmp(enc.name, encoding_str) == 0 &&
97 1.1 mrg (prec == 0 || prec == enc.precision)) {
98 1.1 mrg *encp = enc.encoding;
99 1.1 mrg *precp = enc.precision;
100 1.1 mrg return (0);
101 1.1 mrg }
102 1.1 mrg
103 1.1 mrg }
104 1.1 mrg return (1);
105 1.1 mrg }
106 1.1 mrg
107 1.1 mrg /*
108 1.1 mrg * SunOS/NeXT .au format helpers
109 1.1 mrg */
110 1.1 mrg struct {
111 1.1 mrg int file_encoding;
112 1.1 mrg int encoding;
113 1.1 mrg int precision;
114 1.1 mrg } file2sw_encodings[] = {
115 1.1 mrg { AUDIO_FILE_ENCODING_MULAW_8, AUDIO_ENCODING_ULAW, 8 },
116 1.1 mrg { AUDIO_FILE_ENCODING_LINEAR_8, AUDIO_ENCODING_ULINEAR_BE, 8 },
117 1.1 mrg { AUDIO_FILE_ENCODING_LINEAR_16, AUDIO_ENCODING_ULINEAR_BE, 16 },
118 1.1 mrg { AUDIO_FILE_ENCODING_LINEAR_24, AUDIO_ENCODING_ULINEAR_BE, 24 },
119 1.1 mrg { AUDIO_FILE_ENCODING_LINEAR_32, AUDIO_ENCODING_ULINEAR_BE, 32 },
120 1.1 mrg #if 0
121 1.1 mrg { AUDIO_FILE_ENCODING_FLOAT, AUDIO_ENCODING_ULAW, 32 },
122 1.1 mrg { AUDIO_FILE_ENCODING_DOUBLE, AUDIO_ENCODING_ULAW, 64 },
123 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G721, AUDIO_ENCODING_ULAW, 4 },
124 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G722, AUDIO_ENCODING_ULAW, 0 },
125 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G723_3, AUDIO_ENCODING_ULAW, 3 },
126 1.1 mrg { AUDIO_FILE_ENCODING_ADPCM_G723_5, AUDIO_ENCODING_ULAW, 5 },
127 1.1 mrg #endif
128 1.1 mrg { AUDIO_FILE_ENCODING_ALAW_8, AUDIO_ENCODING_ALAW, 8 },
129 1.1 mrg { -1, -1 }
130 1.1 mrg };
131 1.1 mrg
132 1.1 mrg int
133 1.1 mrg audio_get_sun_encoding(sun_encoding, encp, precp)
134 1.1 mrg int sun_encoding;
135 1.1 mrg int *encp;
136 1.1 mrg int *precp;
137 1.1 mrg {
138 1.1 mrg int i;
139 1.1 mrg
140 1.1 mrg for (i = 0; file2sw_encodings[i].file_encoding != -1; i++)
141 1.1 mrg if (file2sw_encodings[i].file_encoding == sun_encoding) {
142 1.1 mrg *precp = file2sw_encodings[i].precision;
143 1.1 mrg *encp = file2sw_encodings[i].encoding;
144 1.1 mrg return (0);
145 1.1 mrg }
146 1.1 mrg return (1);
147 1.1 mrg }
148 1.1 mrg
149 1.1 mrg /*
150 1.1 mrg * sample header is:
151 1.1 mrg *
152 1.1 mrg * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@
153 1.1 mrg *
154 1.1 mrg */
155 1.1 mrg /*
156 1.1 mrg * WAV format helpers
157 1.1 mrg */
158 1.1 mrg /*
159 1.1 mrg * find a .wav header, etc. returns header length on success
160 1.1 mrg */
161 1.1 mrg size_t
162 1.1 mrg audio_parse_wav_hdr(hdr, sz, enc, prec, sample, channels)
163 1.1 mrg void *hdr;
164 1.1 mrg size_t sz;
165 1.1 mrg int *enc;
166 1.1 mrg int *prec;
167 1.1 mrg int *sample;
168 1.1 mrg int *channels;
169 1.1 mrg {
170 1.1 mrg char *where = hdr;
171 1.1 mrg wav_audioheaderpart *part;
172 1.1 mrg wav_audioheaderfmt *fmt;
173 1.1 mrg char *end = (((char *)hdr) + sz);
174 1.1 mrg int newenc, newprec;
175 1.1 mrg
176 1.1 mrg if (sz < 32)
177 1.1 mrg return (AUDIO_ENOENT);
178 1.1 mrg
179 1.1 mrg if (strncmp(where, "RIFF", 4))
180 1.1 mrg return (AUDIO_ENOENT);
181 1.1 mrg where += 8;
182 1.1 mrg if (strncmp(where, "WAVE", 4))
183 1.1 mrg return (AUDIO_ENOENT);
184 1.1 mrg where += 4;
185 1.1 mrg
186 1.1 mrg do {
187 1.1 mrg part = (wav_audioheaderpart *)where;
188 1.1 mrg where += getle32(part->len) + 8;
189 1.1 mrg } while (where < end && strncmp(part->name, "fmt ", 4));
190 1.1 mrg
191 1.1 mrg /* too short ? */
192 1.1 mrg if (where + 16 > end)
193 1.1 mrg return (AUDIO_ESHORTHDR);
194 1.1 mrg
195 1.1 mrg fmt = (wav_audioheaderfmt *)(part + 1);
196 1.1 mrg
197 1.1 mrg #if 0
198 1.1 mrg printf("fmt header is:\n\t%d\ttag\n\t%d\tchannels\n\t%d\tsample rate\n\t%d\tavg_bps\n\t%d\talignment\n\t%d\tbits per sample\n", getle16(fmt->tag), getle16(fmt->channels), getle32(fmt->sample_rate), getle32(fmt->avg_bps), getle16(fmt->alignment), getle16(fmt->bits_per_sample));
199 1.1 mrg #endif
200 1.1 mrg
201 1.1 mrg switch (getle16(fmt->tag)) {
202 1.1 mrg case WAVE_FORMAT_UNKNOWN:
203 1.1 mrg case WAVE_FORMAT_ADPCM:
204 1.1 mrg case WAVE_FORMAT_OKI_ADPCM:
205 1.1 mrg case WAVE_FORMAT_DIGISTD:
206 1.1 mrg case WAVE_FORMAT_DIGIFIX:
207 1.1 mrg case IBM_FORMAT_MULAW:
208 1.1 mrg case IBM_FORMAT_ALAW:
209 1.1 mrg case IBM_FORMAT_ADPCM:
210 1.1 mrg default:
211 1.1 mrg return (AUDIO_EWAVUNSUPP);
212 1.1 mrg
213 1.1 mrg case WAVE_FORMAT_PCM:
214 1.1 mrg switch (getle16(fmt->bits_per_sample)) {
215 1.1 mrg case 8:
216 1.1 mrg newprec = 8;
217 1.1 mrg break;
218 1.1 mrg case 16:
219 1.1 mrg newprec = 16;
220 1.1 mrg break;
221 1.1 mrg case 24:
222 1.1 mrg newprec = 24;
223 1.1 mrg break;
224 1.1 mrg case 32:
225 1.1 mrg newprec = 32;
226 1.1 mrg break;
227 1.1 mrg default:
228 1.1 mrg return (AUDIO_EWAVBADPCM);
229 1.1 mrg }
230 1.1 mrg newenc = AUDIO_ENCODING_ULINEAR;;
231 1.1 mrg break;
232 1.1 mrg case WAVE_FORMAT_ALAW:
233 1.1 mrg newenc = AUDIO_ENCODING_ALAW;
234 1.1 mrg newprec = 8;
235 1.1 mrg break;
236 1.1 mrg case WAVE_FORMAT_MULAW:
237 1.1 mrg newenc = AUDIO_ENCODING_ULAW;
238 1.1 mrg newprec = 8;
239 1.1 mrg break;
240 1.1 mrg }
241 1.1 mrg
242 1.1 mrg do {
243 1.1 mrg part = (wav_audioheaderpart *)where;
244 1.1 mrg where += (getle32(part->len) + 8);
245 1.1 mrg } while ((char *)where < end && strncmp(part->name, "data", 4));
246 1.1 mrg
247 1.1 mrg if (where <= end) {
248 1.1 mrg *channels = getle16(fmt->channels);
249 1.1 mrg *sample = getle32(fmt->sample_rate);
250 1.1 mrg *enc = newenc;
251 1.1 mrg *prec = newprec;
252 1.1 mrg part++;
253 1.1 mrg return ((char *)part - (char *)hdr);
254 1.1 mrg }
255 1.1 mrg return (AUDIO_EWAVNODATA);
256 1.1 mrg }
257 1.1 mrg
258 1.1 mrg /*
259 1.1 mrg * these belong elsewhere??
260 1.1 mrg */
261 1.1 mrg void
262 1.1 mrg decode_int(arg, intp)
263 1.1 mrg const char *arg;
264 1.1 mrg int *intp;
265 1.1 mrg {
266 1.1 mrg char *ep;
267 1.1 mrg int ret;
268 1.1 mrg
269 1.1 mrg ret = strtoul(arg, &ep, 0);
270 1.1 mrg
271 1.1 mrg if (ep[0] == '\0') {
272 1.1 mrg *intp = ret;
273 1.1 mrg return;
274 1.1 mrg }
275 1.1 mrg errx(1, "argument `%s' not a valid integer", arg);
276 1.1 mrg }
277 1.1 mrg
278 1.1 mrg #include <stdio.h>
279 1.1 mrg void
280 1.1 mrg decode_time(arg, tvp)
281 1.1 mrg const char *arg;
282 1.1 mrg struct timeval *tvp;
283 1.1 mrg {
284 1.1 mrg char *s, *colon, *dot;
285 1.1 mrg char *copy = strdup(arg);
286 1.1 mrg int first;
287 1.1 mrg
288 1.1 mrg if (copy == NULL)
289 1.1 mrg err(1, "could not allocate a copy of %s", arg);
290 1.1 mrg
291 1.1 mrg tvp->tv_sec = tvp->tv_usec = 0;
292 1.1 mrg s = copy;
293 1.1 mrg
294 1.1 mrg /* handle [hh:]mm:ss.dd */
295 1.1 mrg if ((colon = strchr(s, ':'))) {
296 1.1 mrg *colon++ = '\0';
297 1.1 mrg decode_int(s, &first);
298 1.1 mrg tvp->tv_sec = first * 60; /* minutes */
299 1.1 mrg s = colon;
300 1.1 mrg
301 1.1 mrg if ((colon = strchr(s, ':'))) {
302 1.1 mrg *colon++ = '\0';
303 1.1 mrg decode_int(s, &first);
304 1.1 mrg tvp->tv_sec += first;
305 1.1 mrg tvp->tv_sec *= 60; /* minutes and hours */
306 1.1 mrg s = colon;
307 1.1 mrg }
308 1.1 mrg }
309 1.1 mrg if ((dot = strchr(s, '.'))) {
310 1.1 mrg int i, base = 100000;
311 1.1 mrg
312 1.1 mrg *dot++ = '\0';
313 1.1 mrg
314 1.1 mrg for (i = 0; i < 6; i++, base /= 10) {
315 1.1 mrg if (!dot[i])
316 1.1 mrg break;
317 1.1 mrg if (!isdigit(dot[i]))
318 1.1 mrg errx(1, "argument `%s' is not a value time specification", arg);
319 1.1 mrg tvp->tv_usec += base * (dot[i] - '0');
320 1.1 mrg }
321 1.1 mrg }
322 1.1 mrg decode_int(s, &first);
323 1.1 mrg tvp->tv_sec += first;
324 1.1 mrg #if 0
325 1.1 mrg printf("tvp->tv_sec = %ld, tvp->tv_usec = %ld\n", tvp->tv_sec, tvp->tv_usec);
326 1.1 mrg #endif
327 1.1 mrg
328 1.1 mrg free(copy);
329 1.1 mrg }
330 1.1 mrg
331 1.1 mrg /*
332 1.1 mrg * decode a string into an encoding value.
333 1.1 mrg */
334 1.1 mrg void
335 1.1 mrg decode_encoding(arg, encp)
336 1.1 mrg const char *arg;
337 1.1 mrg int *encp;
338 1.1 mrg {
339 1.1 mrg size_t len;
340 1.1 mrg int i;
341 1.1 mrg
342 1.1 mrg len = strlen(arg);
343 1.1 mrg for (i = 0; encs[i].ename; i++)
344 1.1 mrg if (strncmp(encs[i].ename, arg, len) == 0) {
345 1.1 mrg *encp = encs[i].eno;
346 1.1 mrg return;
347 1.1 mrg }
348 1.1 mrg errx(1, "unknown encoding `%s'", arg);
349 1.1 mrg }
350 1.1 mrg
351 1.1 mrg const char *const audio_errlist[] = {
352 1.1 mrg "no audio entry",
353 1.1 mrg "short header",
354 1.1 mrg "unsupported WAV format",
355 1.1 mrg "bad (unsupported) WAV PCM format",
356 1.1 mrg "no WAV audio data",
357 1.1 mrg };
358 1.1 mrg
359 1.1 mrg const char *
360 1.1 mrg audio_errstring(errval)
361 1.1 mrg int errval;
362 1.1 mrg {
363 1.1 mrg
364 1.1 mrg errval = -errval;
365 1.1 mrg if (errval < 1 || errval > AUDIO_MAXERRNO)
366 1.1 mrg return "Invalid error";
367 1.1 mrg return audio_errlist[errval];
368 1.1 mrg }
369