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;
364 *dest++ = (unsigned char)(((int)*(src) +
372 /* Convert 8 bit signed stereo data to 8 bit signed mono data */
373 size_t sndcnv8S_2mono(void **data,size_t *sz,void **outbuf)
375 REGISTER unsigned char *src;
376 REGISTER unsigned char *dest;
380 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
383 src = (unsigned char *) *data;
385 dest = miscplay_sndbuf;
388 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
389 (int)*((signed char *)(src+1))) / 2);
396 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
397 size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf)
399 REGISTER unsigned char *src;
400 REGISTER unsigned char *dest;
404 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
407 src = (unsigned char *) *data;
409 dest = miscplay_sndbuf;
412 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
413 (int)*((signed char *)(src+1))) / 2) ^ 0x80;
420 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
421 size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf)
423 REGISTER unsigned char *src;
424 REGISTER unsigned char *dest;
428 if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; }
431 src = (unsigned char *) *data;
433 dest = miscplay_sndbuf;
435 *dest++ = *(src)++ ^ 0x80;
440 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
441 number --- I hope, I got this conversion right :-) */
442 static inline signed char int2ulaw(int i)
444 /* Lookup table for fast calculation of number of bits that need shifting*/
445 static short int t_bits[128] = {
446 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,
447 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,
448 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,
449 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};
450 REGISTER int bits,logi;
452 /* unrolling this condition (hopefully) improves execution speed */
454 if ((i = (132-i)) > 0x7FFF) i = 0x7FFF;
455 logi = (i >> ((bits = t_bits[i/256])+4));
456 return((bits << 4 | logi) ^ 0x7F); }
458 if ((i = 132+i) > 0x7FFF) i = 0x7FFF;
459 logi = (i >> ((bits = t_bits[i/256])+4));
460 return(~(bits << 4 | logi)); }
463 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
464 size_t sndcnvULaw_2linear(void **data,size_t *sz,void **outbuf)
466 /* conversion table stolen from Linux's ulaw.h */
467 static unsigned char ulaw_dsp[] = {
468 3, 7, 11, 15, 19, 23, 27, 31,
469 35, 39, 43, 47, 51, 55, 59, 63,
470 66, 68, 70, 72, 74, 76, 78, 80,
471 82, 84, 86, 88, 90, 92, 94, 96,
472 98, 99, 100, 101, 102, 103, 104, 105,
473 106, 107, 108, 109, 110, 111, 112, 113,
474 113, 114, 114, 115, 115, 116, 116, 117,
475 117, 118, 118, 119, 119, 120, 120, 121,
476 121, 121, 122, 122, 122, 122, 123, 123,
477 123, 123, 124, 124, 124, 124, 125, 125,
478 125, 125, 125, 125, 126, 126, 126, 126,
479 126, 126, 126, 126, 127, 127, 127, 127,
480 127, 127, 127, 127, 127, 127, 127, 127,
481 128, 128, 128, 128, 128, 128, 128, 128,
482 128, 128, 128, 128, 128, 128, 128, 128,
483 128, 128, 128, 128, 128, 128, 128, 128,
484 253, 249, 245, 241, 237, 233, 229, 225,
485 221, 217, 213, 209, 205, 201, 197, 193,
486 190, 188, 186, 184, 182, 180, 178, 176,
487 174, 172, 170, 168, 166, 164, 162, 160,
488 158, 157, 156, 155, 154, 153, 152, 151,
489 150, 149, 148, 147, 146, 145, 144, 143,
490 143, 142, 142, 141, 141, 140, 140, 139,
491 139, 138, 138, 137, 137, 136, 136, 135,
492 135, 135, 134, 134, 134, 134, 133, 133,
493 133, 133, 132, 132, 132, 132, 131, 131,
494 131, 131, 131, 131, 130, 130, 130, 130,
495 130, 130, 130, 130, 129, 129, 129, 129,
496 129, 129, 129, 129, 129, 129, 129, 129,
497 128, 128, 128, 128, 128, 128, 128, 128,
498 128, 128, 128, 128, 128, 128, 128, 128,
499 128, 128, 128, 128, 128, 128, 128, 128,
501 unsigned char *p=(unsigned char *)*data;
511 return p - (unsigned char *)*outbuf;
514 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
515 size_t sndcnvULaw_2mono(void **data,size_t *sz,void **outbuf)
518 static short int ulaw2int[256] = {
519 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
520 -16062,-15550,-15038,-14526,-14014,-13502,-12990,-12478,
521 -11966,-11454,-10942,-10430, -9918, -9406, -8894, -8382,
522 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
523 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
524 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
525 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
526 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
527 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
528 -942, -910, -878, -846, -814, -782, -750, -718,
529 -686, -654, -622, -590, -558, -526, -494, -462,
530 -438, -422, -406, -390, -374, -358, -342, -326,
531 -310, -294, -278, -262, -246, -230, -214, -198,
532 -186, -178, -170, -162, -154, -146, -138, -130,
533 -122, -114, -106, -98, -90, -82, -74, -66,
534 -60, -56, -52, -48, -44, -40, -36, -32,
535 -28, -24, -20, -16, -12, -8, -4, +0,
536 +16062,+15550,+15038,+14526,+14014,+13502,+12990,+12478,
537 +11966,+11454,+10942,+10430, +9918, +9406, +8894, +8382,
538 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
539 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
540 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
541 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
542 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
543 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
544 +942, +910, +878, +846, +814, +782, +750, +718,
545 +686, +654, +622, +590, +558, +526, +494, +462,
546 +438, +422, +406, +390, +374, +358, +342, +326,
547 +310, +294, +278, +262, +246, +230, +214, +198,
548 +186, +178, +170, +162, +154, +146, +138, +130,
549 +122, +114, +106, +98, +90, +82, +74, +66,
550 +60, +56, +52, +48, +44, +40, +36, +32,
551 +28, +24, +20, +16, +12, +8, +4, +0};
553 REGISTER unsigned char *src;
554 REGISTER unsigned char *dest;
558 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
561 src = (unsigned char *) *data;
563 dest = miscplay_sndbuf;
566 /* it is not possible to directly interpolate between two ulaw encoded
567 data bytes, thus we need to convert to linear format first and later
568 we convert back to ulaw format */
569 *dest++ = int2ulaw(ulaw2int[*src] +
577 size_t sndcnv16swap(void **data,size_t *sz,void **outbuf)
579 size_t cnt = *sz / 2;
583 p = (unsigned short *) *outbuf;
586 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
595 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
597 size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf)
599 REGISTER unsigned char *src;
600 REGISTER unsigned char *dest;
605 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
608 src = (unsigned char *) *data;
610 dest = miscplay_sndbuf;
611 for (count /= 2; count--; ) {
615 256*(int)(src[3])) / 2;
617 *dest++ = (unsigned char)(i & 0xFF);
618 *dest++ = (unsigned char)((i / 256) & 0xFF); }
623 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
625 size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf)
627 REGISTER unsigned char *src;
628 REGISTER unsigned char *dest;
633 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
636 src = (unsigned char *) *data;
638 dest = miscplay_sndbuf;
639 for (count /= 2; count--; ) {
643 256*(int)(src[2])) / 2;
645 *dest++ = (unsigned char)((i / 256) & 0xFF);
646 *dest++ = (unsigned char)(i & 0xFF); }
651 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
652 size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf)
654 REGISTER unsigned char *src;
655 REGISTER unsigned char *dest;
659 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
662 src = (unsigned char *) *data;
664 dest = miscplay_sndbuf;
666 *dest++ = (unsigned char)(((signed char *)src)[1] ^ (signed char)0x80);
673 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
674 size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf)
676 REGISTER unsigned char *src;
677 REGISTER unsigned char *dest;
681 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
684 src = (unsigned char *) *data;
686 dest = miscplay_sndbuf;
688 *dest++ = (unsigned char)(((signed char *)src)[0] ^ (signed char)0x80);
695 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
697 size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf)
699 REGISTER unsigned char *src;
700 REGISTER unsigned char *dest;
704 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
707 src = (unsigned char *) *data;
709 dest = miscplay_sndbuf;
711 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
712 (int)((signed char *)src)[3]) / 2 ^ 0x80);
719 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
721 size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf)
723 REGISTER unsigned char *src;
724 REGISTER unsigned char *dest;
728 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
731 src = (unsigned char *) *data;
733 dest = miscplay_sndbuf;
735 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
736 (int)((signed char *)src)[2]) / 2 ^ 0x80);
743 /* Look at the header of the sound file and try to determine the format;
744 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
745 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
746 fmtType analyze_format(unsigned char *format,int *fmt,int *speed,
748 size_t (**parsesndfile)(void **,size_t *sz,
751 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
752 if (!memcmp(format,"Creative Voice File\x1A\x1A\x00",22) &&
753 (format[22]+256*format[23]) ==
754 ((0x1233-format[24]-256*format[25])&0xFFFF)) { /* VOC */
758 *parsesndfile = parsevoc;
760 else if (!memcmp(format,"RIFF",4) &&
761 !memcmp(format+8,"WAVEfmt ",8)) { /* WAVE */
762 if (memcmp(format+20,"\001\000\001"/* PCM mono */,4) &&
763 memcmp(format+20,"\001\000\002"/* PCM stereo */,4))
765 *fmt = (format[32]/(*tracks = format[22])) == 1 ?
766 AFMT_U8 : AFMT_S16_LE;
767 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
768 *speed = format[24]+256*(format[25]+256*
769 (format[26]+256*format[27]));
770 *parsesndfile = parsewave;
772 else if (!memcmp(format,".snd",4)) { /* Sun Audio (big endian) */
773 if (format[7]+256*(format[6]+256*(format[5]+256*format[4])) < 24) {
777 *parsesndfile = parsesundecaudio;
778 return(fmtSunAudio); }
779 if (!memcmp(format+12,"\000\000\000\001",4)) *fmt = AFMT_MU_LAW;
780 else if (!memcmp(format+12,"\000\000\000\002",4)) *fmt = AFMT_S8;
781 else if (!memcmp(format+12,"\000\000\000\003",4)) *fmt = AFMT_S16_BE;
782 else return(fmtIllegal);
783 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
784 *speed = format[19]+256*(format[18]+256*
785 (format[17]+256*format[16]));
786 *tracks = format[23];
787 *parsesndfile = parsesundecaudio;
788 return(fmtSunAudio); }
789 else if (!memcmp(format,".sd",4)) { /* DEC Audio (little endian) */
790 if (format[4]+256*(format[5]+256*(format[6]+256*format[7])) < 24) {
794 *parsesndfile = parsesundecaudio;
795 return(fmtSunAudio); }
796 if (!memcmp(format+12,"\001\000\000",4)) *fmt = AFMT_MU_LAW;
797 else if (!memcmp(format+12,"\002\000\000",4)) *fmt = AFMT_S8;
798 else if (!memcmp(format+12,"\003\000\000",4)) *fmt = AFMT_S16_LE;
799 else return(fmtIllegal);
800 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
801 *speed = format[16]+256*(format[17]+256*
802 (format[18]+256*format[19]));
803 *tracks = format[20];
804 *parsesndfile = parsesundecaudio;
805 return(fmtSunAudio); }
810 *parsesndfile = parseraw;