diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-14 04:38:45 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-14 04:38:45 +0100 |
commit | 5ceb834f0ed45978497ff81582b7c828d27dcf6f (patch) | |
tree | 7d3b283a1c43120c6eee7f4305fcedab5974c648 /sys/src/cmd/audio | |
parent | d7b7723c96cdee0be6a5120293ecfde60bd65bdc (diff) |
audio: replace µlawdec, add big endian and µlaw audio formats to pcmconv, µlaw in wav support
to support µ-law audio embedded in wav and big endian pcm
in sun audio files the µ-law and a-law and big endian integer
decoding was added to pcmconv. sundec now parses the sun
audio header supporting stereo now.
Diffstat (limited to 'sys/src/cmd/audio')
-rw-r--r-- | sys/src/cmd/audio/mkfile | 2 | ||||
-rw-r--r-- | sys/src/cmd/audio/pcmconv/pcmconv.c | 218 | ||||
-rw-r--r-- | sys/src/cmd/audio/sundec/mkfile (renamed from sys/src/cmd/audio/µlawdec/mkfile) | 4 | ||||
-rw-r--r-- | sys/src/cmd/audio/sundec/sundec.c | 62 | ||||
-rw-r--r-- | sys/src/cmd/audio/wavdec/wavdec.c | 34 | ||||
-rw-r--r-- | sys/src/cmd/audio/µlawdec/µlawdec.c | 368 |
6 files changed, 278 insertions, 410 deletions
diff --git a/sys/src/cmd/audio/mkfile b/sys/src/cmd/audio/mkfile index ddc4af14d..f5d59a139 100644 --- a/sys/src/cmd/audio/mkfile +++ b/sys/src/cmd/audio/mkfile @@ -1,7 +1,7 @@ </$objtype/mkfile LIBS=libogg libvorbis libFLAC -PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec wavdec µlawdec +PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec wavdec sundec #libs must be made first DIRS=$LIBS $PROGS diff --git a/sys/src/cmd/audio/pcmconv/pcmconv.c b/sys/src/cmd/audio/pcmconv/pcmconv.c index 92f963ac6..add9b0548 100644 --- a/sys/src/cmd/audio/pcmconv/pcmconv.c +++ b/sys/src/cmd/audio/pcmconv/pcmconv.c @@ -9,8 +9,9 @@ struct Desc int rate; int channels; int framesz; - int bits; - int fmt; + int abits; /* bits after input conversion */ + int bits; /* bits in input stream per sample */ + Rune fmt; }; struct Chan @@ -236,6 +237,31 @@ siconv(int *dst, uchar *src, int bits, int skip, int count) } void +Siconv(int *dst, uchar *src, int bits, int skip, int count) +{ + int i, v, s, b; + + b = (bits+7)/8; + s = sizeof(int)*8-bits; + while(count--){ + v = 0; + i = 0; + switch(b){ + case 4: + v = src[i++]; + case 3: + v = (v<<8) | src[i++]; + case 2: + v = (v<<8) | src[i++]; + case 1: + v = (v<<8) | src[i]; + } + *dst++ = v << s; + src += skip; + } +} + +void uiconv(int *dst, uchar *src, int bits, int skip, int count) { int i, s, b; @@ -262,38 +288,105 @@ uiconv(int *dst, uchar *src, int bits, int skip, int count) } void +Uiconv(int *dst, uchar *src, int bits, int skip, int count) +{ + int i, s, b; + uint v; + + b = (bits+7)/8; + s = sizeof(uint)*8-bits; + while(count--){ + v = 0; + i = 0; + switch(b){ + case 4: + v = src[i++]; + case 3: + v = (v<<8) | src[i++]; + case 2: + v = (v<<8) | src[i++]; + case 1: + v = (v<<8) | src[i]; + } + *dst++ = (v << s) - (~0UL>>1); + src += skip; + } +} + +void ficonv(int *dst, uchar *src, int bits, int skip, int count) { if(bits == 32){ while(count--){ float f; - f = *((float*)src); + f = *((float*)src), src += skip; if(f > 1.0) *dst++ = 0x7fffffff; else if(f < -1.0) *dst++ = -0x80000000; else *dst++ = f*2147483647.f; - src += skip; } } else { while(count--){ double d; - d = *((double*)src); + d = *((double*)src), src += skip; if(d > 1.0) *dst++ = 0x7fffffff; else if(d < -1.0) *dst++ = -0x80000000; else *dst++ = d*2147483647.f; - src += skip; } } } void +aiconv(int *dst, uchar *src, int, int skip, int count) +{ + int t, seg; + uchar a; + + while(count--){ + a = *src, src += skip; + a ^= 0x55; + t = (a & 0xf) << 4; + seg = (a & 0x70) >> 4; + switch(seg){ + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + t = (a & 0x80) ? t : -t; + *dst++ = t << (sizeof(int)*8 - 16); + } +} + +void +µiconv(int *dst, uchar *src, int, int skip, int count) +{ + int t; + uchar u; + + while(count--){ + u = *src, src += skip; + u = ~u; + t = ((u & 0xf) << 3) + 0x84; + t <<= (u & 0x70) >> 4; + t = u & 0x80 ? 0x84 - t: t - 0x84; + *dst++ = t << (sizeof(int)*8 - 16); + } +} + +void soconv(int *src, uchar *dst, int bits, int skip, int count) { int i, v, s, b; @@ -318,6 +411,30 @@ soconv(int *src, uchar *dst, int bits, int skip, int count) } void +Soconv(int *src, uchar *dst, int bits, int skip, int count) +{ + int i, v, s, b; + + b = (bits+7)/8; + s = sizeof(int)*8-bits; + while(count--){ + v = *src++ >> s; + i = b; + switch(b){ + case 4: + dst[--i] = v, v >>= 8; + case 3: + dst[--i] = v, v >>= 8; + case 2: + dst[--i] = v, v >>= 8; + case 1: + dst[--i] = v; + } + dst += skip; + } +} + +void uoconv(int *src, uchar *dst, int bits, int skip, int count) { int i, s, b; @@ -343,6 +460,31 @@ uoconv(int *src, uchar *dst, int bits, int skip, int count) } void +Uoconv(int *src, uchar *dst, int bits, int skip, int count) +{ + int i, s, b; + uint v; + + b = (bits+7)/8; + s = sizeof(uint)*8-bits; + while(count--){ + v = ((~0UL>>1) + *src++) >> s; + i = b; + switch(b){ + case 4: + dst[--i] = v, v >>= 8; + case 3: + dst[--i] = v, v >>= 8; + case 2: + dst[--i] = v, v >>= 8; + case 1: + dst[--i] = v; + } + dst += skip; + } +} + +void foconv(int *src, uchar *dst, int bits, int skip, int count) { if(bits == 32){ @@ -362,24 +504,31 @@ Desc mkdesc(char *f) { Desc d; - int c; + Rune r; char *p; memset(&d, 0, sizeof(d)); p = f; - while(c = *p++){ - switch(c){ - case 'r': + while(*p != 0){ + p += chartorune(&r, p); + switch(r){ + case L'r': d.rate = strtol(p, &p, 10); break; - case 'c': + case L'c': d.channels = strtol(p, &p, 10); break; - case 's': - case 'u': - case 'f': - d.fmt = c; - d.bits = strtol(p, &p, 10); + case L'm': + r = L'µ'; + case L's': + case L'S': + case L'u': + case L'U': + case L'f': + case L'a': + case L'µ': + d.fmt = r; + d.bits = d.abits = strtol(p, &p, 10); break; default: goto Bad; @@ -387,9 +536,14 @@ mkdesc(char *f) } if(d.rate <= 0) goto Bad; - if(d.fmt == 'f'){ + if(d.fmt == L'a' || d.fmt == L'µ'){ + if(d.bits != 8) + goto Bad; + d.abits = sizeof(int)*8 - 16; + } else if(d.fmt == L'f'){ if(d.bits != 32 && d.bits != 64) goto Bad; + d.abits = sizeof(int)*8; } else if(d.bits <= 0 || d.bits > 32) goto Bad; d.framesz = ((d.bits+7)/8) * d.channels; @@ -472,21 +626,31 @@ main(int argc, char *argv[]) } if(i.channels > nelem(ch)) - sysfatal("too many input channels %d", i.channels); + sysfatal("too many input channels: %d", i.channels); switch(i.fmt){ - case 's': iconv = siconv; break; - case 'u': iconv = uiconv; break; - case 'f': iconv = ficonv; break; + case L's': iconv = siconv; break; + case L'S': iconv = Siconv; break; + case L'u': iconv = uiconv; break; + case L'U': iconv = Uiconv; break; + case L'f': iconv = ficonv; break; + case L'a': iconv = aiconv; break; + case L'µ': iconv = µiconv; break; + default: + sysfatal("unsupported input format: %C", i.fmt); } switch(o.fmt){ - case 's': oconv = soconv; break; - case 'u': oconv = uoconv; break; - case 'f': oconv = foconv; break; + case L's': oconv = soconv; break; + case L'S': oconv = Soconv; break; + case L'u': oconv = uoconv; break; + case L'U': oconv = Uoconv; break; + case L'f': oconv = foconv; break; + default: + sysfatal("unsupported output format: %C", o.fmt); } - if(i.fmt == 'f' || o.fmt == 'f') + if(i.fmt == L'f' || o.fmt == L'f') setfcr(getfcr() & ~(FPINVAL|FPOVFL)); nin = (sizeof(ibuf)-i.framesz)/i.framesz; @@ -511,7 +675,7 @@ main(int argc, char *argv[]) l -= n; n /= i.framesz; (*iconv)(in, ibuf, i.bits, i.framesz, n); - dither(in, i.bits, o.bits, n); + dither(in, i.abits, o.abits, n); m = resample(&ch[0], in, out, n) - out; if(m < 1){ if(n == 0) @@ -521,7 +685,7 @@ main(int argc, char *argv[]) if(i.channels == o.channels){ for(k=1; k<i.channels; k++){ (*iconv)(in, ibuf + k*((i.bits+7)/8), i.bits, i.framesz, n); - dither(in, i.bits, o.bits, n); + dither(in, i.abits, o.abits, n); resample(&ch[k], in, out, n); if(m > 0) (*oconv)(out, obuf + k*((o.bits+7)/8), o.bits, o.framesz, m); diff --git a/sys/src/cmd/audio/µlawdec/mkfile b/sys/src/cmd/audio/sundec/mkfile index c4ed6668c..33be86055 100644 --- a/sys/src/cmd/audio/µlawdec/mkfile +++ b/sys/src/cmd/audio/sundec/mkfile @@ -1,8 +1,8 @@ </$objtype/mkfile <../config -OFILES=µlawdec.$O +OFILES=sundec.$O -TARG=µlawdec +TARG=sundec </sys/src/cmd/mkone diff --git a/sys/src/cmd/audio/sundec/sundec.c b/sys/src/cmd/audio/sundec/sundec.c new file mode 100644 index 000000000..345bcc03e --- /dev/null +++ b/sys/src/cmd/audio/sundec/sundec.c @@ -0,0 +1,62 @@ +#include <u.h> +#include <libc.h> + +ulong +get4(void) +{ + uchar buf[4]; + + if(readn(0, buf, 4) != 4) + sysfatal("read: %r"); + return buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]; +} + +char *fmttab[] = { + [1] "µ8", /* 8-bit G.711 µ-law */ + [2] "S8", /* 8-bit linear PCM */ + [3] "S16", /* 16-bit linear PCM */ + [4] "S24", /* 24-bit linear PCM */ + [5] "S32", /* 32-bit linear PCM */ + [6] "f32", /* 32-bit IEEE floating point */ + [7] "f64", /* 64-bit IEEE floating point */ + [27] "a8", /* 8-bit G.711 A-law */ +}; + +void +main(int, char *argv[]) +{ + char buf[64], fmt[32]; + ulong enc, rate, chans, len, off; + int n; + + argv0 = argv[0]; + if(get4() != 0x2e736e64UL) + sysfatal("no sun format"); + off = get4(); + if(off < 24) + sysfatal("bad data ofset"); + off -= 24; + len = get4(); + if(len == 0xffffffffUL) + len = 0; + enc = get4(); + rate = get4(); + chans = get4(); + if(enc >= nelem(fmttab) || fmttab[enc] == 0) + sysfatal("unsupported encoding: %lux", enc); + snprint(fmt, sizeof(fmt), "%sc%ludr%lud", fmttab[enc], chans, rate); + while(off > 0){ + n = sizeof(buf); + if(off < n) + n = off; + n = read(0, buf, n); + if(n <= 0) + sysfatal("read: %r"); + off -= n; + } + if(len > 0){ + snprint(buf, sizeof(buf), "%lud", len); + execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, "-l", buf, 0); + } else + execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, 0); +} diff --git a/sys/src/cmd/audio/wavdec/wavdec.c b/sys/src/cmd/audio/wavdec/wavdec.c index 77a7e3e26..9b116c550 100644 --- a/sys/src/cmd/audio/wavdec/wavdec.c +++ b/sys/src/cmd/audio/wavdec/wavdec.c @@ -42,7 +42,7 @@ getcc(char tag[4]) void main(int, char *argv[]) { - char buf[8*1024], fmt[32]; + char buf[1024], fmt[32]; ulong len, n; Wave wav; @@ -70,22 +70,32 @@ main(int, char *argv[]) len -= 2+2+4+4+2+2; } while(len > 0){ - if(len < sizeof(buf)) + n = sizeof(buf); + if(len < n) n = len; - else - n = sizeof(buf); - if(readn(0, buf, n) != n) + n = read(0, buf, n); + if(n <= 0) sysfatal("read: %r"); len -= n; } } - - if(wav.fmt != 1) - sysfatal("compressed format (0x%x) not supported", wav.fmt); - snprint(fmt, sizeof(fmt), "%c%dr%dc%d", - wav.bits == 8 ? 'u' : 's', wav.bits, - wav.rate, - wav.channels); + switch(wav.fmt){ + case 1: + snprint(fmt, sizeof(fmt), "%c%dr%dc%d", wav.bits == 8 ? 'u' : 's', + wav.bits, wav.rate, wav.channels); + break; + case 3: + snprint(fmt, sizeof(fmt), "f32r%dc%d", wav.rate, wav.channels); + break; + case 6: + snprint(fmt, sizeof(fmt), "a8r%dc%d", wav.rate, wav.channels); + break; + case 7: + snprint(fmt, sizeof(fmt), "µ8r%dc%d", wav.rate, wav.channels); + break; + default: + sysfatal("wave format (0x%lux) not supported", (ulong)wav.fmt); + } snprint(buf, sizeof(buf), "%lud", len); execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, "-l", buf, 0); } diff --git a/sys/src/cmd/audio/µlawdec/µlawdec.c b/sys/src/cmd/audio/µlawdec/µlawdec.c deleted file mode 100644 index 3c55f83f8..000000000 --- a/sys/src/cmd/audio/µlawdec/µlawdec.c +++ /dev/null @@ -1,368 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <bio.h> - -enum { - Qmask = 0xf, /* quantization mask */ - Nsegs = 8, /* A-law segments */ - Segshift = 4, - Segmask = 0x70, -}; - -static short segend[Nsegs] = { - 0xff, 0x1ff, 0x3ff, 0x7ff, - 0xfff, 0x1fff, 0x3fff, 0x7fff -}; - -/* copy from CCITT G.711 specifications */ -static uchar u2a[128] = { /* μ- to A-law conversions */ - 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 27, 29, 31, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, - 46, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128 -}; - -static uchar a2u[128] = { /* A- to μ-law conversions */ - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 48, 49, 49, - 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 64, - 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127 -}; - -/* speed doesn't matter. table has 8 entires */ -static int -search(int val, short *table, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (val <= *table++) - return i; - } - return size; -} - -/* - * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law - * - * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. - * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -uchar -linear2alaw(int pcm) /* 2's complement (16-bit range) */ -{ - uchar aval; - int mask, seg; - - if (pcm >= 0) { - mask = 0xd5; /* sign (7th) bit = 1 */ - } else { - mask = 0x55; /* sign bit = 0 */ - pcm = -pcm - 8; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm, segend, 8); - - /* Combine the sign, segment, and quantization bits. */ - if (seg >= 8) - /* out of range, return maximum value. */ - return 0x7f ^ mask; - else { - aval = seg << Segshift; - if (seg < 2) - aval |= pcm>>4 & Qmask; - else - aval |= pcm>>(seg + 3) & Qmask; - return aval ^ mask; - } -} - -/* - * alaw2linear() - Convert an A-law value to 16-bit linear PCM - * - */ -int -alaw2linear(uchar a) -{ - int t, seg; - - a ^= 0x55; - - t = (a & Qmask) << 4; - seg = (a & Segmask) >> Segshift; - switch (seg) { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - } - return (a & 0x80) ? t : -t; -} - -enum { - Bias = 0x84, /* Bias for linear code. */ -}; - -/* - * linear2μlaw() - Convert a linear PCM value to μ-law - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -uchar -linear2μlaw(int pcm) -{ - int mask, seg; - uchar uval; - - /* Get the sign and the magnitude of the value. */ - if (pcm < 0) { - pcm = Bias - pcm; - mask = 0x7f; - } else { - pcm += Bias; - mask = 0xff; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm, segend, 8); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - if (seg >= 8) - /* out of range, return maximum value. */ - return 0x7f ^ mask; - else { - uval = seg<< 4 | ((pcm >> (seg + 3)) & 0xf); - return uval ^ mask; - } -} - -/* - * μlaw2linear() - Convert a μ-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -int -μlaw2linear(uchar μ) -{ - int t; - - /* Complement to obtain normal μ-law value. */ - μ = ~μ; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((μ & Qmask) << 3) + Bias; - t <<= (μ & Segmask) >> Segshift; - - return μ & 0x80? Bias - t: t - Bias; -} - -/* A-law to μ-law conversion */ -uchar -alaw2μlaw(uchar a) -{ -// a &= 0xff; - if(a & 0x80) - return 0xff ^ a2u[a ^ 0xd5]; - else - return 0x7f ^ a2u[a ^ 0x55]; -} - -/* μ-law to A-law conversion */ -uchar -μlaw2alaw(uchar μ) -{ -// μ &= 0xff; - if(μ & 0x80) - return 0xd5 ^ u2a[0xff ^ μ] - 1; - else - return 0x55 ^ u2a[0x7f ^ μ] - 1; -} - -static void -setrate(int rate) -{ - int fd; - - fd = open("/dev/volume", OWRITE); - if(fd == -1){ - fprint(2, "μlawdec: can't set rate %d: open: %r\n", rate); - return; - } - if(fprint(fd, "speed %d", rate) == -1) - fprint(2, "μlawdec: can't set rate %d: fprint: %r\n", rate); - else - fprint(2, "μlawdec: rate %d\n", rate); - close(fd); -} - -enum { - Sig = 0, - Offset = 1, - Enc = 3, - Rate = 4, - Nchan = 5, -}; - -u32int -μlawword(uchar *buf, int w) -{ - buf += 4*w; - return buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]; -} - -int -pcmconv(char *fmt) -{ - int pid, pfd[2]; - - if(pipe(pfd) < 0) - return -1; - pid = fork(); - if(pid < 0){ - close(pfd[0]); - close(pfd[1]); - return -1; - } - if(pid == 0){ - dup(pfd[1], 0); - close(pfd[1]); - close(pfd[0]); - execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, 0); - sysfatal("exec: %r"); - } - close(pfd[1]); - return pfd[0]; -} - -void -main(void) -{ - int fd, n; - uchar buf[5*4]; - char fmt[32]; - vlong off; - Biobuf i, o; - - if(Binit(&i, 0, OREAD) == -1) - sysfatal("μlawdec: Binit: %r"); - if(Bread(&i, buf, sizeof buf) != sizeof buf) - sysfatal("μlawdec: Bread: %r"); - off = μlawword(buf, Offset); - if(off < 24) - sysfatal("μlawdec: bad offset: %lld", off); - if(μlawword(buf, Sig) != 0x2e736e64) - sysfatal("μlawdec: not .au file"); - if(μlawword(buf, Enc) != 1) - sysfatal("μlawdec: not μlaw"); - - snprint(fmt, sizeof(fmt), "s16c1r%d", μlawword(buf, Rate)); - fd = pcmconv(fmt); - if(fd < 0) - sysfatal("μlawdec: pcmconv: %r"); - - if(Binit(&o, fd, OWRITE) == -1) - sysfatal("μlawdec: Binit: %r"); - - while(off > 0){ - n = sizeof(buf); - if(off < n) - n = off; - if(Bread(&i, buf, n) != n) - sysfatal("μlawdec: Bread: %r"); - off -= n; - } - - for(;;){ - switch(Bread(&i, buf, 1)){ - case 0: - goto done; - case -1: - sysfatal("μlawdec: Bread: %r"); - } - n = μlaw2linear(buf[0]); - buf[0] = n&0xff; - buf[1] = (n&0xff00)>>8; - if(Bwrite(&o, buf, 2) != 2) - sysfatal("μlawdec: Bwrite: %r"); - } -done: - Bterm(&o); - Bterm(&i); -} |