code: plan9front

Download patch

ref: 89cb83a4266649bad7ec47fa96176766c2467a33
parent: 8af84630a8888bf6ed465f0b6897f8213f680af3
author: Jacob Moody <moody@posixcafe.org>
date: Wed Feb 8 21:41:21 EST 2023

audio/vocdec: Creative Voice File decoder

slight correction in file.c from previous commit

diff: cannot open b/sys/src/cmd/audio/vocdec//null: file does not exist: 'b/sys/src/cmd/audio/vocdec//null'
--- a/rc/bin/play
+++ b/rc/bin/play
@@ -69,6 +69,8 @@
 			midi
 		case *audio/mus*
 			games/mus | midi
+		case *audio/x-voc*
+			audio/vocdec
 		case *pls*
 			awk 'BEGIN {FS="="} /^File/{print $2}' | play1 list plain
 		case *
--- a/sys/man/1/audio
+++ b/sys/man/1/audio
@@ -1,6 +1,6 @@
 .TH AUDIO 1
 .SH NAME
-mp3dec, mp3enc, oggdec, oggenc, flacdec, flacenc, sundec, wavdec, pcmconv, mixfs \- decode and encode audio files
+mp3dec, mp3enc, oggdec, oggenc, flacdec, flacenc, sundec, wavdec, vocdec, pcmconv, mixfs \- decode and encode audio files
 .SH SYNOPSIS
 .B audio/mp3dec
 [
@@ -29,6 +29,8 @@
 ]
 .br
 .B audio/sundec
+.br
+.B audio/vocdec
 .PP
 .B audio/oggenc
 .br
--- a/sys/src/cmd/audio/mkfile
+++ b/sys/src/cmd/audio/mkfile
@@ -1,7 +1,7 @@
 </$objtype/mkfile
 
 LIBS=libogg libvorbis libFLAC libtags
-PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec flacenc wavdec sundec mixfs readtags zuke scream
+PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec flacenc wavdec sundec vocdec mixfs readtags zuke scream
 #libs must be made first
 DIRS=$LIBS $PROGS
 
--- /dev/null
+++ b/sys/src/cmd/audio/vocdec/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+<../config
+
+OFILES=vocdec.$O
+
+TARG=vocdec
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/sys/src/cmd/audio/vocdec/vocdec.c
@@ -1,0 +1,136 @@
+#include <u.h>
+#include <libc.h>
+
+uchar
+get(void)
+{
+	uchar b;
+
+	if(read(0, &b, 1) != 1)
+		sysfatal("read: %r");
+	return b;
+}
+
+uint
+get2(void)
+{
+	uchar b[2];
+
+	if(readn(0, b, 2) != 2)
+		sysfatal("read: %r");
+	return (b[0]<<0) | (b[1]<<8);
+}
+
+uint
+get3(void)
+{
+	uchar b[3];
+
+	if(readn(0, b, 3) != 3)
+		sysfatal("read: %r");
+	return (b[0]<<0) | (b[1]<<8) | (b[2]<<16);
+}
+
+uint
+get4(void)
+{
+	uchar b[4];
+
+	if(readn(0, b, 4) != 4)
+		sysfatal("read: %r");
+	return (b[0]<<0) | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
+}
+
+typedef struct Block Block;
+struct Block {
+	uchar type;
+	uint size;
+	uint freq;
+	uint codec;
+	uchar chan;
+	uint bits;
+};
+
+char*
+codec(int c)
+{
+	switch(c){
+	case 0x00:
+		return "u8";
+	case 0x04:
+		return "s16";
+	case 0x06:
+		return "µ8";
+	case 0x07:
+		return "a8";
+	default:
+		sysfatal("unsupported");
+	}
+	return nil;
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	Block b;
+	uchar buf[20];
+	char fmt[32], size[32];
+	ushort chksum, ver;
+
+	ARGBEGIN{
+	default:
+		usage();
+		break;
+	}ARGEND;
+
+	if(readn(0, buf, 20) != 20 || memcmp(buf, "Creative Voice File\x1a", 20) != 0)
+		sysfatal("not a voc file");
+
+	get2(); /* gulp */
+	ver = get2();
+	chksum = get2();
+	if(~ver + 0x1234 != chksum)
+		sysfatal("invalid checksum");
+
+	for(;;){
+		b.type = get();
+		if(b.type == 0)
+			break;
+		b.size = get3();
+
+		switch(b.type){
+		case 1:
+			b.freq = 1000000 / (256 - get());
+			b.codec = get();
+			b.chan = 1;
+			b.size -= 2;
+			break;
+		case 9:
+			b.freq = get4();
+			b.bits = get();
+			b.chan = get();
+			b.codec = get2();
+			get(); /* reserved */
+			b.size -= 4+1+1+2+1;
+			break;
+		default:
+			sysfatal("unsupported blocktype");
+			break;
+		}
+
+		snprint(fmt, sizeof fmt, "%sc%dr%d", codec(b.codec), b.chan, b.freq);
+		snprint(size, sizeof size, "%d", b.size);
+		if(fork() == 0){
+			execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, "-l", size, nil);
+			sysfatal("exec: %r");
+		}
+		waitpid();
+	}
+}
--- a/sys/src/cmd/file.c
+++ b/sys/src/cmd/file.c
@@ -913,7 +913,7 @@
 	"Extended module: ",	"XM audio",		17,	"audio/xm",
 	"MThd",			"midi audio",		4,	"audio/midi",
 	"MUS\x1a",		"mus audio",		4,	"audio/mus",
-	"Creative Voice File\x1a\x1a",	"voc audio",	22,	"auxio/x-voc",
+	"Creative Voice File\x1a",	"voc audio",	20,	"audio/x-voc",
 	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 	"\x00\x00\x00\xbb\x11\x22\x00\x44\xff\xff\xff\xff\xff\xff\xff\xff"