1 /* miscplay.c - general routines related to playing sounds
3 ** Copyright (C) 1995,96 by Markus Gutschke (gutschk@math.uni-muenster.de)
4 ** This was sawed out from version 1.3 of linuxplay.c by
5 ** Robert Bihlmeyer <robbe@orcus.priv.at>.
7 ** Parts of this code were inspired by sunplay.c, which is copyright 1989 by
8 ** Jef Poskanzer and 1991,92 by Jamie Zawinski; c.f. sunplay.c for further
11 ** Permission to use, copy, modify, and distribute this software and its
12 ** documentation for any purpose and without fee is hereby granted, provided
13 ** that the above copyright notice appear in all copies and that both that
14 ** copyright notice and this permission notice appear in supporting
15 ** documentation. This software is provided "as is" without express or
25 #include "syssignal.h"
27 #define warn(str) message("audio: %s ",GETTEXT(str))
32 #define UNUSED(x) ((void)(x))
37 /* Maintain global variable for keeping parser state information; this struct
38 is set to zero before the first invocation of the parser. The use of a
39 global variable prevents multiple concurrent executions of this code, but
40 this does not happen anyways... */
56 unsigned char leftover[HEADERSZ];
57 signed long chunklength;
64 unsigned char leftover[HEADERSZ];
68 /* Use a global buffer as scratch-pad for possible conversions of the
70 unsigned char miscplay_sndbuf[SNDBUFSZ];
72 /* Initialize global parser state information to zero */
73 void reset_parsestate()
75 memset(&parsestate,0,sizeof(parsestate));
78 /* Verify that we could fully parse the entire soundfile; this is needed
79 only for files in WAVE format */
80 int parse_wave_complete()
82 if (parsestate.wave.state != wvOutOfBlock &&
83 parsestate.wave.state != wvFatal) {
84 warn("Unexpected end of WAVE file");
90 /* There is no special treatment required for parsing raw data files; we
91 assume that these files contain data in 8bit unsigned format that
92 has been sampled at 8kHz; there is no extra header */
93 static size_t parseraw(void **data,size_t *sz,void **outbuf)
102 /* Currently we cannot cope with files in VOC format; if you really need
103 to play these files, they should be converted by using SOX */
104 static size_t parsevoc(void **data,size_t *sz,void **outbuf)
112 /* We need to perform some look-ahead in order to parse files in WAVE format;
113 this might require re-partioning of the data segments if headers cross the
114 boundaries between two read operations. This is done in a two-step way:
115 first we request a certain amount of bytes... */
116 static inline int waverequire(void **data,size_t *sz,size_t rq)
121 warn("Header size exceeded while parsing WAVE file");
122 parsestate.wave.state = wvFatal;
125 if ((rq -= parsestate.wave.left) <= 0)
127 if (rq > *sz) {rq = *sz; rc = 0;}
128 memcpy(parsestate.wave.leftover+parsestate.wave.left,
130 parsestate.wave.left += rq;
131 (*(unsigned char **)data) += rq;
136 /* ...and next we remove this many bytes from the buffer */
137 static inline void waveremove(size_t rq)
139 if (parsestate.wave.left <= rq)
140 parsestate.wave.left = 0;
142 parsestate.wave.left -= rq;
143 memmove(parsestate.wave.leftover,
144 parsestate.wave.leftover+rq,
145 parsestate.wave.left); }
149 /* Sound files in WAVE format can contain an arbitrary amount of tagged
150 chunks; this requires quite some effort for parsing the data */
151 static size_t parsewave(void **data,size_t *sz,void **outbuf)
154 switch (parsestate.wave.state) {
156 if (!waverequire(data,sz,20))
158 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
159 parsestate.wave.chunklength = parsestate.wave.leftover[16] +
160 256*(parsestate.wave.leftover[17] +
161 256*(parsestate.wave.leftover[18] +
162 256*parsestate.wave.leftover[19]));
164 parsestate.wave.state = wvSubchunk;
167 if (!waverequire(data,sz,parsestate.wave.chunklength))
169 parsestate.wave.align = parsestate.wave.chunklength < 14 ? 1
170 : parsestate.wave.leftover[12];
171 if (parsestate.wave.align != 1 &&
172 parsestate.wave.align != 2 &&
173 parsestate.wave.align != 4) {
174 warn("Illegal datawidth detected while parsing WAVE file");
175 parsestate.wave.state = wvFatal; }
177 parsestate.wave.state = wvOutOfBlock;
178 waveremove(parsestate.wave.chunklength);
181 if (!waverequire(data,sz,8))
183 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
184 parsestate.wave.chunklength = parsestate.wave.leftover[4] +
185 256*(parsestate.wave.leftover[5] +
186 256*(parsestate.wave.leftover[6] +
187 256*(parsestate.wave.leftover[7] & 0x7F)));
188 if (memcmp(parsestate.wave.leftover,"data",4))
189 parsestate.wave.state = wvSkipChunk;
191 parsestate.wave.state = wvSoundChunk;
195 if (parsestate.wave.chunklength > 0 && *sz > 0 &&
196 (signed long)*sz < (signed long)parsestate.wave.chunklength) {
197 parsestate.wave.chunklength -= *sz;
200 if (parsestate.wave.chunklength > 0 && *sz > 0) {
201 *sz -= parsestate.wave.chunklength;
202 (*(unsigned char **)data) += parsestate.wave.chunklength; }
203 parsestate.wave.state = wvOutOfBlock; }
207 if (parsestate.wave.left) { /* handle leftover bytes from last
208 alignment operation */
209 count = parsestate.wave.left;
211 if (rq > (size_t) parsestate.wave.chunklength)
212 rq = parsestate.wave.chunklength;
213 if (!waverequire(data,sz,rq)) {
214 parsestate.wave.chunklength -= parsestate.wave.left - count;
216 parsestate.wave.chunklength -= rq;
217 *outbuf = parsestate.wave.leftover;
218 parsestate.wave.left = 0;
220 if (*sz >= (size_t) parsestate.wave.chunklength) {
221 count = parsestate.wave.chunklength;
225 count -= rq = count % parsestate.wave.align; }
227 (*(unsigned char **)data) += count;
229 if ((parsestate.wave.chunklength -= count) < parsestate.wave.align) {
230 parsestate.wave.state = wvOutOfBlock;
231 /* Some broken software (e.g. SOX) attaches junk to the end of a sound
232 chunk; so, let's ignore this... */
233 if (parsestate.wave.chunklength)
234 parsestate.wave.state = wvSkipChunk; }
236 /* align data length to a multiple of datasize; keep additional data
237 in "leftover" buffer --- this is necessary to ensure proper
238 functioning of the sndcnv... routines */
239 waverequire(data,sz,rq);
242 warn("Irrecoverable error while parsing WAVE file");
243 parsestate.wave.state = wvFatal;
251 /* Strip the header from files in Sun/DEC audio format; this requires some
252 extra processing as the header can be an arbitrary size and it might
253 result in alignment errors for subsequent conversions --- thus we do
254 some buffering, where needed */
255 static size_t parsesundecaudio(void **data,size_t *sz,void **outbuf)
257 /* There is data left over from the last invocation of this function; join
258 it with the new data and return a sound chunk that is as big as a
260 if (parsestate.audio.left) {
261 if (parsestate.audio.left + *sz > (size_t) parsestate.audio.align) {
263 memmove(parsestate.audio.leftover + parsestate.audio.left,
265 count = parsestate.audio.align - parsestate.audio.left);
266 *outbuf = parsestate.audio.leftover;
268 *data = (*(char **)data) + count;
269 parsestate.audio.left = 0;
270 return(parsestate.audio.align); }
272 /* We need even more data in order to get one complete single entry! */
273 memmove(parsestate.audio.leftover + parsestate.audio.left,
276 *data = (*(char **)data) + *sz;
277 parsestate.audio.left += *sz;
281 /* This is the main sound chunk, strip of any extra data that does not fit
282 the alignment requirements and move these bytes into the leftover buffer*/
283 if (parsestate.audio.isdata) {
286 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
287 memmove(parsestate.audio.leftover,
288 (char *)*outbuf + rc - parsestate.audio.left,
289 parsestate.audio.left);
290 rc -= parsestate.audio.left; }
294 /* This is the first invocation of this function; we need to parse the
295 header information and determine how many bytes we need to skip until
296 the start of the sound chunk */
297 if (!parsestate.audio.skipping) {
298 unsigned char *header = (unsigned char *) *data;
300 warn("Irrecoverable error while parsing Sun/DEC audio file");
302 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
303 if (header[3]) { /* Sun audio (big endian) */
304 parsestate.audio.align = ((header[15] > 2)+1)*header[23];
305 parsestate.audio.skipping = header[7]+256*(header[6]+256*
306 (header[5]+256*header[4])); }
307 else { /* DEC audio (little endian) */
308 parsestate.audio.align = ((header[12] > 2)+1)*header[20];
309 parsestate.audio.skipping = header[4]+256*(header[5]+256*
310 (header[6]+256*header[7])); }}
312 /* We are skipping extra data that has been attached to header; most usually
313 this will be just a comment, such as the original filename and/or the
314 creation date. Make sure that we do not return less than one single sound
315 sample entry to the caller; if this happens, rather decide to move those
316 few bytes into the leftover buffer and deal with it later */
317 if (*sz >= (size_t) parsestate.audio.skipping) {
318 /* Skip just the header information and return the sound chunk */
319 int rc = *sz - parsestate.audio.skipping;
320 *outbuf = (char *)*data + parsestate.audio.skipping;
321 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
322 memmove(parsestate.audio.leftover,
323 (char *)*outbuf + rc - parsestate.audio.left,
324 parsestate.audio.left);
325 rc -= parsestate.audio.left; }
327 parsestate.audio.skipping = 0;
328 parsestate.audio.isdata++;
331 /* Skip everything */
332 parsestate.audio.skipping -= *sz;
336 /* If the soundcard could not be set to natively support the data format, we
337 try to do some limited on-the-fly conversion to a different format; if
338 no conversion is needed, though, we can output directly */
339 size_t sndcnvnop(void **data,size_t *sz,void **outbuf)
348 /* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */
349 size_t sndcnv8U_2mono(void **data,size_t *sz,void **outbuf)
351 REGISTER unsigned char *src;
352 REGISTER unsigned char *dest;
356 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
359 src = (unsigned char *) *data;
361 dest = miscplay_sndbuf;
363 *dest++ = (unsigned char)(((int)*(src)++ +
369 /* Convert 8 bit signed stereo data to 8 bit signed mono data */
370 size_t sndcnv8S_2mono(void **data,size_t *sz,void **outbuf)
372 REGISTER unsigned char *src;
373 REGISTER unsigned char *dest;
377 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
380 src = (unsigned char *) *data;
382 dest = miscplay_sndbuf;
384 *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
385 (int)*((signed char *)(src++))) / 2);
390 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
391 size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf)
393 REGISTER unsigned char *src;
394 REGISTER unsigned char *dest;
398 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
401 src = (unsigned char *) *data;
403 dest = miscplay_sndbuf;
405 *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
406 (int)*((signed char *)(src++))) / 2) ^ 0x80;
411 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
412 size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf)
414 REGISTER unsigned char *src;
415 REGISTER unsigned char *dest;
419 if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; }
422 src = (unsigned char *) *data;
424 dest = miscplay_sndbuf;
426 *dest++ = *(src)++ ^ 0x80;
431 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
432 number --- I hope, I got this conversion right :-) */
433 static inline signed char int2ulaw(int i)
435 /* Lookup table for fast calculation of number of bits that need shifting*/
436 static short int t_bits[128] = {
437 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
438 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
439 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
440 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
441 REGISTER int bits,logi;
443 /* unrolling this condition (hopefully) improves execution speed */
445 if ((i = (132-i)) > 0x7FFF) i = 0x7FFF;
446 logi = (i >> ((bits = t_bits[i/256])+4));
447 return((bits << 4 | logi) ^ 0x7F); }
449 if ((i = 132+i) > 0x7FFF) i = 0x7FFF;
450 logi = (i >> ((bits = t_bits[i/256])+4));
451 return(~(bits << 4 | logi)); }
454 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
455 size_t sndcnvULaw_2linear(void **data,size_t *sz,void **outbuf)
457 /* conversion table stolen from Linux's ulaw.h */
458 static unsigned char ulaw_dsp[] = {
459 3, 7, 11, 15, 19, 23, 27, 31,
460 35, 39, 43, 47, 51, 55, 59, 63,
461 66, 68, 70, 72, 74, 76, 78, 80,
462 82, 84, 86, 88, 90, 92, 94, 96,
463 98, 99, 100, 101, 102, 103, 104, 105,
464 106, 107, 108, 109, 110, 111, 112, 113,
465 113, 114, 114, 115, 115, 116, 116, 117,
466 117, 118, 118, 119, 119, 120, 120, 121,
467 121, 121, 122, 122, 122, 122, 123, 123,
468 123, 123, 124, 124, 124, 124, 125, 125,
469 125, 125, 125, 125, 126, 126, 126, 126,
470 126, 126, 126, 126, 127, 127, 127, 127,
471 127, 127, 127, 127, 127, 127, 127, 127,
472 128, 128, 128, 128, 128, 128, 128, 128,
473 128, 128, 128, 128, 128, 128, 128, 128,
474 128, 128, 128, 128, 128, 128, 128, 128,
475 253, 249, 245, 241, 237, 233, 229, 225,
476 221, 217, 213, 209, 205, 201, 197, 193,
477 190, 188, 186, 184, 182, 180, 178, 176,
478 174, 172, 170, 168, 166, 164, 162, 160,
479 158, 157, 156, 155, 154, 153, 152, 151,
480 150, 149, 148, 147, 146, 145, 144, 143,
481 143, 142, 142, 141, 141, 140, 140, 139,
482 139, 138, 138, 137, 137, 136, 136, 135,
483 135, 135, 134, 134, 134, 134, 133, 133,
484 133, 133, 132, 132, 132, 132, 131, 131,
485 131, 131, 131, 131, 130, 130, 130, 130,
486 130, 130, 130, 130, 129, 129, 129, 129,
487 129, 129, 129, 129, 129, 129, 129, 129,
488 128, 128, 128, 128, 128, 128, 128, 128,
489 128, 128, 128, 128, 128, 128, 128, 128,
490 128, 128, 128, 128, 128, 128, 128, 128,
492 unsigned char *p=(unsigned char *)*data;
499 return p - (unsigned char *)*outbuf;
502 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
503 size_t sndcnvULaw_2mono(void **data,size_t *sz,void **outbuf)
506 static short int ulaw2int[256] = {
507 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
508 -16062,-15550,-15038,-14526,-14014,-13502,-12990,-12478,
509 -11966,-11454,-10942,-10430, -9918, -9406, -8894, -8382,
510 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
511 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
512 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
513 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
514 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
515 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
516 -942, -910, -878, -846, -814, -782, -750, -718,
517 -686, -654, -622, -590, -558, -526, -494, -462,
518 -438, -422, -406, -390, -374, -358, -342, -326,
519 -310, -294, -278, -262, -246, -230, -214, -198,
520 -186, -178, -170, -162, -154, -146, -138, -130,
521 -122, -114, -106, -98, -90, -82, -74, -66,
522 -60, -56, -52, -48, -44, -40, -36, -32,
523 -28, -24, -20, -16, -12, -8, -4, +0,
524 +16062,+15550,+15038,+14526,+14014,+13502,+12990,+12478,
525 +11966,+11454,+10942,+10430, +9918, +9406, +8894, +8382,
526 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
527 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
528 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
529 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
530 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
531 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
532 +942, +910, +878, +846, +814, +782, +750, +718,
533 +686, +654, +622, +590, +558, +526, +494, +462,
534 +438, +422, +406, +390, +374, +358, +342, +326,
535 +310, +294, +278, +262, +246, +230, +214, +198,
536 +186, +178, +170, +162, +154, +146, +138, +130,
537 +122, +114, +106, +98, +90, +82, +74, +66,
538 +60, +56, +52, +48, +44, +40, +36, +32,
539 +28, +24, +20, +16, +12, +8, +4, +0};
541 REGISTER unsigned char *src;
542 REGISTER unsigned char *dest;
546 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
549 src = (unsigned char *) *data;
551 dest = miscplay_sndbuf;
553 /* it is not possible to directly interpolate between two ulaw encoded
554 data bytes, thus we need to convert to linear format first and later
555 we convert back to ulaw format */
556 *dest++ = int2ulaw(ulaw2int[*(src)++] +
562 size_t sndcnv16swap(void **data,size_t *sz,void **outbuf)
564 size_t cnt = *sz / 2;
568 p = (unsigned short *) *outbuf;
570 *p++ = ((*p & 0x00ff) << 8) | (*p >> 8);
578 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
580 size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf)
582 REGISTER unsigned char *src;
583 REGISTER unsigned char *dest;
588 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
591 src = (unsigned char *) *data;
593 dest = miscplay_sndbuf;
594 for (count /= 2; count--; ) {
598 256*(int)(src[3])) / 2;
600 *dest++ = (unsigned char)(i & 0xFF);
601 *dest++ = (unsigned char)((i / 256) & 0xFF); }
606 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
608 size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf)
610 REGISTER unsigned char *src;
611 REGISTER unsigned char *dest;
616 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
619 src = (unsigned char *) *data;
621 dest = miscplay_sndbuf;
622 for (count /= 2; count--; ) {
626 256*(int)(src[2])) / 2;
628 *dest++ = (unsigned char)((i / 256) & 0xFF);
629 *dest++ = (unsigned char)(i & 0xFF); }
634 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
635 size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf)
637 REGISTER unsigned char *src;
638 REGISTER unsigned char *dest;
642 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
645 src = (unsigned char *) *data;
647 dest = miscplay_sndbuf;
649 *dest++ = (unsigned char)(((signed char *)src)[1] ^ (signed char)0x80);
656 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
657 size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf)
659 REGISTER unsigned char *src;
660 REGISTER unsigned char *dest;
664 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
667 src = (unsigned char *) *data;
669 dest = miscplay_sndbuf;
671 *dest++ = (unsigned char)(((signed char *)src)[0] ^ (signed char)0x80);
678 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
680 size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf)
682 REGISTER unsigned char *src;
683 REGISTER unsigned char *dest;
687 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
690 src = (unsigned char *) *data;
692 dest = miscplay_sndbuf;
694 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
695 (int)((signed char *)src)[3]) / 2 ^ 0x80);
702 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
704 size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf)
706 REGISTER unsigned char *src;
707 REGISTER unsigned char *dest;
711 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
714 src = (unsigned char *) *data;
716 dest = miscplay_sndbuf;
718 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
719 (int)((signed char *)src)[2]) / 2 ^ 0x80);
726 /* Look at the header of the sound file and try to determine the format;
727 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
728 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
729 fmtType analyze_format(unsigned char *format,int *fmt,int *speed,
731 size_t (**parsesndfile)(void **,size_t *sz,
734 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
735 if (!memcmp(format,"Creative Voice File\x1A\x1A\x00",22) &&
736 (format[22]+256*format[23]) ==
737 ((0x1233-format[24]-256*format[25])&0xFFFF)) { /* VOC */
741 *parsesndfile = parsevoc;
743 else if (!memcmp(format,"RIFF",4) &&
744 !memcmp(format+8,"WAVEfmt ",8)) { /* WAVE */
745 if (memcmp(format+20,"\001\000\001"/* PCM mono */,4) &&
746 memcmp(format+20,"\001\000\002"/* PCM stereo */,4))
748 *fmt = (format[32]/(*tracks = format[22])) == 1 ?
749 AFMT_U8 : AFMT_S16_LE;
750 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
751 *speed = format[24]+256*(format[25]+256*
752 (format[26]+256*format[27]));
753 *parsesndfile = parsewave;
755 else if (!memcmp(format,".snd",4)) { /* Sun Audio (big endian) */
756 if (format[7]+256*(format[6]+256*(format[5]+256*format[4])) < 24) {
760 *parsesndfile = parsesundecaudio;
761 return(fmtSunAudio); }
762 if (!memcmp(format+12,"\000\000\000\001",4)) *fmt = AFMT_MU_LAW;
763 else if (!memcmp(format+12,"\000\000\000\002",4)) *fmt = AFMT_S8;
764 else if (!memcmp(format+12,"\000\000\000\003",4)) *fmt = AFMT_S16_BE;
765 else return(fmtIllegal);
766 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
767 *speed = format[19]+256*(format[18]+256*
768 (format[17]+256*format[16]));
769 *tracks = format[23];
770 *parsesndfile = parsesundecaudio;
771 return(fmtSunAudio); }
772 else if (!memcmp(format,".sd",4)) { /* DEC Audio (little endian) */
773 if (format[4]+256*(format[5]+256*(format[6]+256*format[7])) < 24) {
777 *parsesndfile = parsesundecaudio;
778 return(fmtSunAudio); }
779 if (!memcmp(format+12,"\001\000\000",4)) *fmt = AFMT_MU_LAW;
780 else if (!memcmp(format+12,"\002\000\000",4)) *fmt = AFMT_S8;
781 else if (!memcmp(format+12,"\003\000\000",4)) *fmt = AFMT_S16_LE;
782 else return(fmtIllegal);
783 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
784 *speed = format[16]+256*(format[17]+256*
785 (format[18]+256*format[19]));
786 *tracks = format[20];
787 *parsesndfile = parsesundecaudio;
788 return(fmtSunAudio); }
793 *parsesndfile = parseraw;