diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-12-05 15:46:27 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-12-05 15:46:27 +0000 |
commit | cff0ebade5fb37b3d5614ae9ff76513e4b0e4640 (patch) | |
tree | dce5da7b316b7cf71b4001808cd276f20d26ef16 /sys | |
parent | 48f53e57be61f7cee021fdb21849d4759770f722 (diff) |
audio/scream: multicast audio protocol
Diffstat (limited to 'sys')
-rw-r--r-- | sys/man/1/scream | 77 | ||||
-rw-r--r-- | sys/src/cmd/audio/mkfile | 2 | ||||
-rw-r--r-- | sys/src/cmd/audio/scream/mkfile | 21 | ||||
-rw-r--r-- | sys/src/cmd/audio/scream/screamdec.c | 71 | ||||
-rw-r--r-- | sys/src/cmd/audio/scream/screamenc.c | 32 | ||||
-rwxr-xr-x | sys/src/cmd/audio/scream/screamrecv | 13 | ||||
-rwxr-xr-x | sys/src/cmd/audio/scream/screamsend | 13 |
7 files changed, 228 insertions, 1 deletions
diff --git a/sys/man/1/scream b/sys/man/1/scream new file mode 100644 index 000000000..9d0d26be4 --- /dev/null +++ b/sys/man/1/scream @@ -0,0 +1,77 @@ +.TH SCREAM 1 +.SH NAME +screamsend, screamrecv, screamenc, screamdec \- multicast audio protocol +.SH SYNOPSIS +.B audio/screamsend +[ +.I interfaceip +]... +.br +.B audio/screamrecv +[ +.I interfaceip +]... +.br +.B audio/screamenc +.br +.B audio/screamdec +.SH DESCRIPTION +.PP +Scream is a simple network protocol for transmitting PCM audio on a local network. +It sends UDP packets at a constant rate to the multicast address +.B 239.255.77.77 +on port +.BR 4010 . +Each packet starts with a small 5-byte header that contains information about the +sample-rate and data format followed raw PCM data payload (maximum 1157 bytes). +.PP +.I Screamsend +reads PCM audio from +.B /dev/audio +and sends scream packets to the local network on the interface given by +.IR interfaceip. +When +.I interfaceip +is omitted, it uses first IPv4 interface ip address from +.B /net/ipselftab +as a default. +.PP +.I Screamrecv +listens for packets from the local network on the interfaces +selected by +.IR interfaceip +and writes PCM audio to +.BR /dev/audio . +When no +.I interfaceip +addresses where given, it will listen on all interfaces with an IPv4 address. +.PP +Both +.I screamsend +and +.I screamrecv +are usually run after +.I audio/mixfs +(see +.IR audio (1)) +to provide loopback audio source as well as mixing for multiple senders. +.PP +.I Screamenc +reads PCM audio from standard-input and writes scream packets to standard-output. +.PP +.I Screamdec +reads scream packets from standard-input, and writes PCM audio to standard-output. +It spawns +.I audio/pcmconv +(see +.IR audio (1)) +to convert the audio in case the scream packet format is not +the default of 16-bit little-endian stereo samples at 44100 Hz. +It exits when no packets have arrived for 500 milliseconds. +.SH SOURCE +.B /sys/src/cmd/audio/scream +.SH SEE ALSO +.IR audio (1). +.br +.B https://github.com/duncanthrax/scream + diff --git a/sys/src/cmd/audio/mkfile b/sys/src/cmd/audio/mkfile index 941a094a8..ecdcdb098 100644 --- 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 +PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec flacenc wavdec sundec mixfs readtags zuke scream #libs must be made first DIRS=$LIBS $PROGS diff --git a/sys/src/cmd/audio/scream/mkfile b/sys/src/cmd/audio/scream/mkfile new file mode 100644 index 000000000..809611330 --- /dev/null +++ b/sys/src/cmd/audio/scream/mkfile @@ -0,0 +1,21 @@ +</$objtype/mkfile +<../config + +TARG=screamenc screamdec +RC=screamsend screamrecv + +</sys/src/cmd/mkmany + +$O.screamenc: screamenc.$O +$O.screamdec: screamdec.$O + +# Override install target to install rc. +install:V: + for (i in $TARG) + mk $MKFLAGS $i.install + for (i in $RC) + mk $MKFLAGS $i.rcinstall + +%.rcinstall:V: + cp $stem $BIN/$stem + chmod +x $BIN/$stem diff --git a/sys/src/cmd/audio/scream/screamdec.c b/sys/src/cmd/audio/scream/screamdec.c new file mode 100644 index 000000000..40f3f386e --- /dev/null +++ b/sys/src/cmd/audio/scream/screamdec.c @@ -0,0 +1,71 @@ +#include <u.h> +#include <libc.h> + +char deffmt[] = "s16c2r44100"; +char fmt[64]; +uchar hdr[5]; +uchar buf[2048]; +int pfd[2]; + +char* +getformat(uchar hdr[5]) +{ + int freq, bits, chan; + + if(hdr[0] & 0x80) + freq = 44100; + else + freq = 48000; + freq *= hdr[0] & 0x7F; + bits = hdr[1]; + chan = hdr[2]; + snprint(fmt, sizeof(fmt), "s%dc%dr%d", bits, chan, freq); + return fmt; +} + +void +main(void) +{ + int n; + + for(;;){ + alarm(500); + + n = read(0, buf, sizeof(buf)); + if(n < sizeof(hdr)) + break; + + if(pfd[1] == 0 || memcmp(buf, hdr, sizeof(hdr)) != 0){ + if(pfd[1] > 1){ + close(pfd[1]); + waitpid(); + } + if(strcmp(getformat(buf), deffmt) == 0){ + pfd[1] = 1; + } else { + if(pipe(pfd) < 0) + sysfatal("pipe: %r"); + switch(fork()){ + case -1: + sysfatal("fork: %r"); + case 0: + close(pfd[1]); + dup(pfd[0], 0); + execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, nil); + sysfatal("exec: %r"); + return; + } + close(pfd[0]); + } + memmove(hdr, buf, sizeof(hdr)); + } + + n -= sizeof(hdr); + if(n <= 0) + continue; + + if(write(pfd[1], buf+sizeof(hdr), n) != n) + break; + } + exits(nil); +} diff --git a/sys/src/cmd/audio/scream/screamenc.c b/sys/src/cmd/audio/scream/screamenc.c new file mode 100644 index 000000000..afe088f94 --- /dev/null +++ b/sys/src/cmd/audio/scream/screamenc.c @@ -0,0 +1,32 @@ +#include <u.h> +#include <libc.h> + +int freq = 44100; +int chan = 2; +int bps = 16; +int delay = 5; + +uchar buf[2048]; + +void +main(void) +{ + int n, m; + + if((freq % 44100) == 0){ + buf[0] = 0x80 | (freq / 44100); + } else { + buf[0] = freq / 48000; + } + buf[1] = bps; + buf[2] = chan; + buf[3] = 0; + buf[4] = 0; + + n = (bps/8)*chan*((delay*freq+999)/1000); + while((m = read(0, buf+5, n)) > 0){ + if(write(1, buf, 5+m) < 0) + sysfatal("write: %r"); + } + exits(nil); +} diff --git a/sys/src/cmd/audio/scream/screamrecv b/sys/src/cmd/audio/scream/screamrecv new file mode 100755 index 000000000..9c247d5e7 --- /dev/null +++ b/sys/src/cmd/audio/scream/screamrecv @@ -0,0 +1,13 @@ +#!/bin/rc +rfork e +lifc=() +while(~ $1 *.*.*.*){ + lifc=($lifc $1) + shift +} +if(! ~ $#* 0){ + echo 'Usage: audio/screamrecv [interfaceip]...' >[1=2] + exit 'usage' +} +if(~ $#lifc 0) lifc=`{awk '/4u/{print $1}' /net/ipselftab} +exec aux/listen1 -t -p4 -O^'addmulti '^$lifc udp!239.255.77.77!4010 rc -c 'exec audio/screamdec > /dev/audio' diff --git a/sys/src/cmd/audio/scream/screamsend b/sys/src/cmd/audio/scream/screamsend new file mode 100755 index 000000000..ed6689f3e --- /dev/null +++ b/sys/src/cmd/audio/scream/screamsend @@ -0,0 +1,13 @@ +#!/bin/rc +rfork e +lifc=() +while(~ $1 *.*.*.*){ + lifc=($lifc $1) + shift +} +if(! ~ $#* 0){ + echo 'Usage: audio/screamsend [interfaceip]...' >[1=2] + exit 'usage' +} +if(~ $#lifc 0) lifc=`{awk '/4u/{print $1}' /net/ipselftab} +exec audio/screamenc < /dev/audio | exec aux/trampoline -o^'addmulti '^$lifc udp!239.255.77.77!4010 |