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;
385 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
386 (int)*((signed char *)(src+1))) / 2);
393 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
394 size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf)
396 REGISTER unsigned char *src;
397 REGISTER unsigned char *dest;
401 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
404 src = (unsigned char *) *data;
406 dest = miscplay_sndbuf;
409 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
410 (int)*((signed char *)(src+1))) / 2) ^ 0x80;
417 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
418 size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf)
420 REGISTER unsigned char *src;
421 REGISTER unsigned char *dest;
425 if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; }
428 src = (unsigned char *) *data;
430 dest = miscplay_sndbuf;
432 *dest++ = *(src)++ ^ 0x80;
437 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
438 number --- I hope, I got this conversion right :-) */
439 static inline signed char int2ulaw(int i)
441 /* Lookup table for fast calculation of number of bits that need shifting*/
442 static short int t_bits[128] = {
443 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,
444 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,
445 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,
446 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};
447 REGISTER int bits,logi;
449 /* unrolling this condition (hopefully) improves execution speed */
451 if ((i = (132-i)) > 0x7FFF) i = 0x7FFF;
452 logi = (i >> ((bits = t_bits[i/256])+4));
453 return((bits << 4 | logi) ^ 0x7F); }
455 if ((i = 132+i) > 0x7FFF) i = 0x7FFF;
456 logi = (i >> ((bits = t_bits[i/256])+4));
457 return(~(bits << 4 | logi)); }
460 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
461 size_t sndcnvULaw_2linear(void **data,size_t *sz,void **outbuf)
463 /* conversion table stolen from Linux's ulaw.h */
464 static unsigned char ulaw_dsp[] = {
465 3, 7, 11, 15, 19, 23, 27, 31,
466 35, 39, 43, 47, 51, 55, 59, 63,
467 66, 68, 70, 72, 74, 76, 78, 80,
468 82, 84, 86, 88, 90, 92, 94, 96,
469 98, 99, 100, 101, 102, 103, 104, 105,
470 106, 107, 108, 109, 110, 111, 112, 113,
471 113, 114, 114, 115, 115, 116, 116, 117,
472 117, 118, 118, 119, 119, 120, 120, 121,
473 121, 121, 122, 122, 122, 122, 123, 123,
474 123, 123, 124, 124, 124, 124, 125, 125,
475 125, 125, 125, 125, 126, 126, 126, 126,
476 126, 126, 126, 126, 127, 127, 127, 127,
477 127, 127, 127, 127, 127, 127, 127, 127,
478 128, 128, 128, 128, 128, 128, 128, 128,
479 128, 128, 128, 128, 128, 128, 128, 128,
480 128, 128, 128, 128, 128, 128, 128, 128,
481 253, 249, 245, 241, 237, 233, 229, 225,
482 221, 217, 213, 209, 205, 201, 197, 193,
483 190, 188, 186, 184, 182, 180, 178, 176,
484 174, 172, 170, 168, 166, 164, 162, 160,
485 158, 157, 156, 155, 154, 153, 152, 151,
486 150, 149, 148, 147, 146, 145, 144, 143,
487 143, 142, 142, 141, 141, 140, 140, 139,
488 139, 138, 138, 137, 137, 136, 136, 135,
489 135, 135, 134, 134, 134, 134, 133, 133,
490 133, 133, 132, 132, 132, 132, 131, 131,
491 131, 131, 131, 131, 130, 130, 130, 130,
492 130, 130, 130, 130, 129, 129, 129, 129,
493 129, 129, 129, 129, 129, 129, 129, 129,
494 128, 128, 128, 128, 128, 128, 128, 128,
495 128, 128, 128, 128, 128, 128, 128, 128,
496 128, 128, 128, 128, 128, 128, 128, 128,
498 unsigned char *p=(unsigned char *)*data;
508 return p - (unsigned char *)*outbuf;
511 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
512 size_t sndcnvULaw_2mono(void **data,size_t *sz,void **outbuf)
515 static short int ulaw2int[256] = {
516 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
517 -16062,-15550,-15038,-14526,-14014,-13502,-12990,-12478,
518 -11966,-11454,-10942,-10430, -9918, -9406, -8894, -8382,
519 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
520 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
521 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
522 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
523 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
524 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
525 -942, -910, -878, -846, -814, -782, -750, -718,
526 -686, -654, -622, -590, -558, -526, -494, -462,
527 -438, -422, -406, -390, -374, -358, -342, -326,
528 -310, -294, -278, -262, -246, -230, -214, -198,
529 -186, -178, -170, -162, -154, -146, -138, -130,
530 -122, -114, -106, -98, -90, -82, -74, -66,
531 -60, -56, -52, -48, -44, -40, -36, -32,
532 -28, -24, -20, -16, -12, -8, -4, +0,
533 +16062,+15550,+15038,+14526,+14014,+13502,+12990,+12478,
534 +11966,+11454,+10942,+10430, +9918, +9406, +8894, +8382,
535 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
536 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
537 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
538 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
539 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
540 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
541 +942, +910, +878, +846, +814, +782, +750, +718,
542 +686, +654, +622, +590, +558, +526, +494, +462,
543 +438, +422, +406, +390, +374, +358, +342, +326,
544 +310, +294, +278, +262, +246, +230, +214, +198,
545 +186, +178, +170, +162, +154, +146, +138, +130,
546 +122, +114, +106, +98, +90, +82, +74, +66,
547 +60, +56, +52, +48, +44, +40, +36, +32,
548 +28, +24, +20, +16, +12, +8, +4, +0};
550 REGISTER unsigned char *src;
551 REGISTER unsigned char *dest;
555 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
558 src = (unsigned char *) *data;
560 dest = miscplay_sndbuf;
563 /* it is not possible to directly interpolate between two ulaw encoded
564 data bytes, thus we need to convert to linear format first and later
565 we convert back to ulaw format */
566 *dest++ = int2ulaw(ulaw2int[*src] +
574 size_t sndcnv16swap(void **data,size_t *sz,void **outbuf)
576 size_t cnt = *sz / 2;
580 p = (unsigned short *) *outbuf;
583 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
592 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
594 size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf)
596 REGISTER unsigned char *src;
597 REGISTER unsigned char *dest;
602 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
605 src = (unsigned char *) *data;
607 dest = miscplay_sndbuf;
608 for (count /= 2; count--; ) {
612 256*(int)(src[3])) / 2;
614 *dest++ = (unsigned char)(i & 0xFF);
615 *dest++ = (unsigned char)((i / 256) & 0xFF); }
620 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
622 size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf)
624 REGISTER unsigned char *src;
625 REGISTER unsigned char *dest;
630 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
633 src = (unsigned char *) *data;
635 dest = miscplay_sndbuf;
636 for (count /= 2; count--; ) {
640 256*(int)(src[2])) / 2;
642 *dest++ = (unsigned char)((i / 256) & 0xFF);
643 *dest++ = (unsigned char)(i & 0xFF); }
648 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
649 size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf)
651 REGISTER unsigned char *src;
652 REGISTER unsigned char *dest;
656 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
659 src = (unsigned char *) *data;
661 dest = miscplay_sndbuf;
663 *dest++ = (unsigned char)(((signed char *)src)[1] ^ (signed char)0x80);
670 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
671 size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf)
673 REGISTER unsigned char *src;
674 REGISTER unsigned char *dest;
678 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
681 src = (unsigned char *) *data;
683 dest = miscplay_sndbuf;
685 *dest++ = (unsigned char)(((signed char *)src)[0] ^ (signed char)0x80);
692 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
694 size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf)
696 REGISTER unsigned char *src;
697 REGISTER unsigned char *dest;
701 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
704 src = (unsigned char *) *data;
706 dest = miscplay_sndbuf;
708 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
709 (int)((signed char *)src)[3]) / 2 ^ 0x80);
716 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
718 size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf)
720 REGISTER unsigned char *src;
721 REGISTER unsigned char *dest;
725 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
728 src = (unsigned char *) *data;
730 dest = miscplay_sndbuf;
732 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
733 (int)((signed char *)src)[2]) / 2 ^ 0x80);
740 /* Look at the header of the sound file and try to determine the format;
741 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
742 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
743 fmtType analyze_format(unsigned char *format,int *fmt,int *speed,
745 size_t (**parsesndfile)(void **,size_t *sz,
748 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
749 if (!memcmp(format,"Creative Voice File\x1A\x1A\x00",22) &&
750 (format[22]+256*format[23]) ==
751 ((0x1233-format[24]-256*format[25])&0xFFFF)) { /* VOC */
755 *parsesndfile = parsevoc;
757 else if (!memcmp(format,"RIFF",4) &&
758 !memcmp(format+8,"WAVEfmt ",8)) { /* WAVE */
759 if (memcmp(format+20,"\001\000\001"/* PCM mono */,4) &&
760 memcmp(format+20,"\001\000\002"/* PCM stereo */,4))
762 *fmt = (format[32]/(*tracks = format[22])) == 1 ?
763 AFMT_U8 : AFMT_S16_LE;
764 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
765 *speed = format[24]+256*(format[25]+256*
766 (format[26]+256*format[27]));
767 *parsesndfile = parsewave;
769 else if (!memcmp(format,".snd",4)) { /* Sun Audio (big endian) */
770 if (format[7]+256*(format[6]+256*(format[5]+256*format[4])) < 24) {
774 *parsesndfile = parsesundecaudio;
775 return(fmtSunAudio); }
776 if (!memcmp(format+12,"\000\000\000\001",4)) *fmt = AFMT_MU_LAW;
777 else if (!memcmp(format+12,"\000\000\000\002",4)) *fmt = AFMT_S8;
778 else if (!memcmp(format+12,"\000\000\000\003",4)) *fmt = AFMT_S16_BE;
779 else return(fmtIllegal);
780 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
781 *speed = format[19]+256*(format[18]+256*
782 (format[17]+256*format[16]));
783 *tracks = format[23];
784 *parsesndfile = parsesundecaudio;
785 return(fmtSunAudio); }
786 else if (!memcmp(format,".sd",4)) { /* DEC Audio (little endian) */
787 if (format[4]+256*(format[5]+256*(format[6]+256*format[7])) < 24) {
791 *parsesndfile = parsesundecaudio;
792 return(fmtSunAudio); }
793 if (!memcmp(format+12,"\001\000\000",4)) *fmt = AFMT_MU_LAW;
794 else if (!memcmp(format+12,"\002\000\000",4)) *fmt = AFMT_S8;
795 else if (!memcmp(format+12,"\003\000\000",4)) *fmt = AFMT_S16_LE;
796 else return(fmtIllegal);
797 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
798 *speed = format[16]+256*(format[17]+256*
799 (format[18]+256*format[19]));
800 *tracks = format[20];
801 *parsesndfile = parsesundecaudio;
802 return(fmtSunAudio); }
807 *parsesndfile = parseraw;