diff options
-rwxr-xr-x | Demo/sgi/al/alwatch.py | 19 | ||||
-rwxr-xr-x | Demo/sgi/al/broadcast.py | 27 | ||||
-rwxr-xr-x | Demo/sgi/al/intercom.py | 218 | ||||
-rwxr-xr-x | Demo/sgi/al/listen.py | 34 | ||||
-rwxr-xr-x | Demo/sgi/al/playaiff.py | 54 | ||||
-rwxr-xr-x | Demo/sgi/al/playback.py | 23 | ||||
-rwxr-xr-x | Demo/sgi/al/playold.py | 51 | ||||
-rwxr-xr-x | Demo/sgi/al/radio.py | 21 | ||||
-rwxr-xr-x | Demo/sgi/al/rec_play.py | 28 | ||||
-rwxr-xr-x | Demo/sgi/al/record.py | 23 | ||||
-rwxr-xr-x | Demo/sgi/al/unicast.py | 26 | ||||
-rwxr-xr-x | Demo/sgi/al/x.py | 12 |
12 files changed, 536 insertions, 0 deletions
diff --git a/Demo/sgi/al/alwatch.py b/Demo/sgi/al/alwatch.py new file mode 100755 index 0000000..5af0935 --- /dev/null +++ b/Demo/sgi/al/alwatch.py @@ -0,0 +1,19 @@ +import time +import al +dev = 1 +name = ['input source', 'left input atten', 'right input atten', \ + 'input rate', 'output rate', \ + 'left speaker gain', 'right speaker gain', \ + 'input count', 'output count', 'unused count', \ + 'sync input to aes', 'sync output to aes', \ + ] +x = al.queryparams(dev) +al.getparams(dev, x) +while 1: + time.millisleep(100) + y = x[:] + al.getparams(dev, x) + if x <> y: + for i in range(0, len(x), 2): + if x[i+1] <> y[i+1]: + print name[x[i]], ':', y[i+1], '-->', x[i+1] diff --git a/Demo/sgi/al/broadcast.py b/Demo/sgi/al/broadcast.py new file mode 100755 index 0000000..22452a3 --- /dev/null +++ b/Demo/sgi/al/broadcast.py @@ -0,0 +1,27 @@ +#! /ufs/guido/bin/sgi/python + +# broadcast [port] +# +# Broadcast audio input on the network as UDP packets; +# they can be received on any SGI machine with "radio.py". +# This uses the input sampling rate, input source etc. set by apanel. +# It uses the default sample width and #channels (16 bit/sample stereo). +# (This is 192,000 Bytes at a sampling speed of 48 kHz, or ~137 +# packets/second -- use with caution!!!) + +import sys, al +from socket import * + +port = 54321 +if sys.argv[1:]: port = eval(sys.argv[1]) + +s = socket(AF_INET, SOCK_DGRAM) +s.allowbroadcast(1) + +p = al.openport('broadcast', 'r') + +address = '<broadcast>', port +while 1: + # 700 samples equals 1400 bytes, or about the max packet size! + data = p.readsamps(700) + s.sendto(data, address) diff --git a/Demo/sgi/al/intercom.py b/Demo/sgi/al/intercom.py new file mode 100755 index 0000000..67c424a --- /dev/null +++ b/Demo/sgi/al/intercom.py @@ -0,0 +1,218 @@ +# intercom -- use mike and headset to *talk* to a person on another host. +# For SGI 4D/35 or Indigo running IRIX 4.0. +# Uses 16 bit sampling at 16000 samples/sec, or 32000 bytes/sec, +# tranmitted in 32 1000-byte UDP packets. (In each direction!) +# +# usage: +# intercom hostname - start talking to person on other host +# intercom -r hostname - called remotely to do the setup + +import sys, time, posix, gl, fl, FL, al, AL, getopt, rand +from socket import * + +# Hack sys.path so AL can be found +LIB = '/ufs/guido/lib/python' +if LIB not in sys.path: sys.path.insert(0, LIB) + +# Python binary to be used on remote machine +PYTHON = '/ufs/guido/bin/sgi/python' + +# Directory where the programs live +AUDIODIR = '/ufs/guido/mm/demo/audio' + +# UDP port numbers used (one for each direction!) +PORT1 = 51042 +PORT2 = PORT1+1 + +# Figure out the user name +try: + user = posix.environ['LOGNAME'] +except: + user = posix.environ['USER'] + +# Debug flags (Implemented as a list; non-empty means debugging is on) +debug = [] + +def main(): + remote = 0 + opts, args = getopt.getopt(sys.argv[1:], 'rd') + for opt, arg in opts: + if opt = '-r': remote = 1 + elif opt = '-d': debug.append(opt) + if len(args) <> 1: + msg = 'usage: intercom [-d] [-r] hostname' + msg = msg + ' (-r is for internal use only!)\n' + sys.stderr.write(msg) + sys.exit(2) + if remote: + server(args[0]) + else: + client(args[0]) + +def client(hostname): + print 'client starting' + cmd = 'rsh ' + hostname + ' "cd ' + AUDIODIR + cmd = cmd + '; DISPLAY=:0; export DISPLAY' + cmd = cmd + '; exec ' + PYTHON + ' intercom.py -r ' + for flag in debug: cmd = cmd + flag + ' ' + cmd = cmd + gethostname() + cmd = cmd + '"' + pipe = posix.popen(cmd, 'r') + ack = 0 + nak = 0 + while 1: + line = pipe.readline() + if not line: break + sys.stdout.write('remote: ' + line) + if line = 'NAK\n': + nak = 1 + break + elif line = 'ACK\n': + ack = 1 + break + if nak: + print 'Remote user doesn\'t want to talk to you.' + return + if not ack: + print 'No acknowledgement (remote side crashed?).' + return + # + print 'Ready...' + # + s = socket(AF_INET, SOCK_DGRAM) + s.bind('', PORT2) + # + otheraddr = gethostbyname(hostname), PORT1 + try: + ioloop(s, otheraddr) + except KeyboardInterrupt: + log('client got intr') + except error: + log('client got error') + finally: + s.sendto('', otheraddr) + log('client finished sending empty packet to server') + # + log('client exit') + print 'Done.' + +def server(hostname): + print 'server starting' + sys.stdout.flush() + # + if not remotedialog(): + print 'NAK' + return + # + print 'ACK' + # + s = socket(AF_INET, SOCK_DGRAM) + s.bind('', PORT1) + # + # Close std{in,out,err} so rsh will exit; reopen them as dummies + # + sys.stdin.close() + sys.stdin = open('/dev/null', 'r') + sys.stdout.close() + sys.stdout = open('/dev/null', 'w') + sys.stderr.close() + if debug: + sys.stderr = open('/tmp/intercom.err', 'a') + else: + sys.stderr = open('/dev/null', 'w') + # + ioloop(s, (gethostbyname(hostname), PORT2)) + log('server exit') + sys.exit(0) + +def remotedialog(): + gl.foreground() + gl.ringbell() + m1 = user + ' wants to talk to you over the audio channel.' + m2 = 'If it\'s OK, put on your headset and click Yes.' + m3 = 'If you\'re too busy, click No.' + return fl.show_question(m1, m2, m3) + +def ioloop(s, otheraddr): + # + dev = AL.DEFAULT_DEVICE + params = al.queryparams(dev) + al.getparams(dev, params) + time.sleep(1) + saveparams = params[:] + for i in range(0, len(params), 2): + if params[i] in (AL.INPUT_RATE, AL.OUTPUT_RATE): + params[i+1] = AL.RATE_16000 + elif params[i] = AL.INPUT_SOURCE: + params[i+1] = AL.INPUT_MIC + try: + al.setparams(dev, params) + ioloop1(s, otheraddr) + finally: + al.setparams(dev, saveparams) + +def ioloop1(s, otheraddr): + # + # Watch out! data is in bytes, but the port counts in samples, + # which are two bytes each (for 16-bit samples). + # Luckily, we use mono, else it would be worse (2 samples/frame...) + # + SAMPSPERBUF = 500 + BYTESPERSAMP = 2 # AL.SAMPLE_16 + BUFSIZE = BYTESPERSAMP*SAMPSPERBUF + QSIZE = 4*SAMPSPERBUF + # + config = al.newconfig() + config.setqueuesize(QSIZE) + config.setwidth(AL.SAMPLE_16) + config.setchannels(AL.MONO) + # + pid = posix.fork() + if pid: + # Parent -- speaker/headphones handler + log('parent started') + spkr = al.openport('spkr', 'w', config) + while 1: + data = s.recv(BUFSIZE) + if len(data) = 0: + # EOF packet + log('parent got empty packet; killing child') + posix.kill(pid, 15) + return + # Discard whole packet if we are too much behind + if spkr.getfillable() > len(data) / BYTESPERSAMP: + if len(debug) >= 2: + log('parent Q full; dropping packet') + spkr.writesamps(data) + else: + # Child -- microphone handler + log('child started') + try: + mike = al.openport('mike', 'r', config) + # Sleep a while to let the other side get started + time.sleep(1) + # Drain the queue before starting to read + data = mike.readsamps(mike.getfilled()) + # Loop, sending packets from the mike to the net + while 1: + data = mike.readsamps(SAMPSPERBUF) + s.sendto(data, otheraddr) + except KeyboardInterrupt: + log('child got interrupt; exiting') + posix._exit(0) + except error: + log('child got error; exiting') + posix._exit(1) + finally: + log('child got unexpected error; leaving w/ traceback') + +def log(msg): + if not debug: return + if type(msg) <> type(''): + msg = `msg` + + f = open('/tmp/intercom.log', 'a') + f.write(`sys.argv` + ' ' + `posix.getpid()` + ': ' + msg + '\n') + f.close() + +main() diff --git a/Demo/sgi/al/listen.py b/Demo/sgi/al/listen.py new file mode 100755 index 0000000..83f850a --- /dev/null +++ b/Demo/sgi/al/listen.py @@ -0,0 +1,34 @@ +# Listen to the input on host argv[1]. + +import sys, al, AL, posix + +BUFSIZE = 2000 +QSIZE = 4000 + +def main(): + if len(sys.argv) <> 2: + sys.stderr.write('usage: ' + sys.argv[0] + ' hostname\n') + sys.exit(2) + hostname = sys.argv[1] + cmd = 'exec rsh </dev/null ' + hostname + \ + ' "cd /ufs/guido/mm/demo/audio; ' + \ + 'exec /ufs/guido/bin/sgi/python record.py"' + pipe = posix.popen(cmd, 'r') + config = al.newconfig() + config.setchannels(AL.MONO) + config.setqueuesize(QSIZE) + port = al.openport('', 'w', config) + while 1: + data = pipe.read(BUFSIZE) + if not data: + sts = pipe.close() + sys.stderr.write(sys.argv[0] + ': end of data\n') + if sts: sys.stderr.write('rsh exit status '+`sts`+'\n') + sys.exit(1) + port.writesamps(data) + del data + +try: + main() +except KeyboardInterrupt: + sys.exit(1) diff --git a/Demo/sgi/al/playaiff.py b/Demo/sgi/al/playaiff.py new file mode 100755 index 0000000..f84a68c --- /dev/null +++ b/Demo/sgi/al/playaiff.py @@ -0,0 +1,54 @@ +import aiff +import al +import sys +import time + +def main(): + v = 1 + c = al.newconfig() + nchannels = c.getchannels() + nsampframes = 0 # ??? + sampwidth = c.getwidth() + samprate = 0.0 # unknown + filename = sys.argv[1] + f = open(filename, 'r') + type, totalsize = aiff.read_chunk_header(f) + if type <> 'FORM': + raise aiff.Error, 'FORM chunk expected at start of file' + aiff.read_form_chunk(f) + while 1: + try: + type, size = aiff.read_chunk_header(f) + except EOFError: + break + if v: print 'header:', `type`, size + if type = 'COMM': + nchannels, nsampframes, sampwidth, samprate = \ + aiff.read_comm_chunk(f) + if v: print nchannels, nsampframes, sampwidth, samprate + elif type = 'SSND': + offset, blocksize = aiff.read_ssnd_chunk(f) + if v: print offset, blocksize + data = f.read(size-8) + if size%2: void = f.read(1) + p = makeport(nchannels, sampwidth, samprate) + play(p, data, offset, blocksize) + elif type in aiff.skiplist: + aiff.skip_chunk(f, size) + else: + raise aiff.Error, 'bad chunk type ' + type + +def makeport(nchannels, sampwidth, samprate): + c = al.newconfig() + c.setchannels(nchannels) + c.setwidth(sampwidth/8) + # can't set the rate... + p = al.openport('', 'w', c) + return p + +def play(p, data, offset, blocksize): + data = data[offset:] + p.writesamps(data) + while p.getfilled() > 0: time.millisleep(10) + +main() diff --git a/Demo/sgi/al/playback.py b/Demo/sgi/al/playback.py new file mode 100755 index 0000000..967f746 --- /dev/null +++ b/Demo/sgi/al/playback.py @@ -0,0 +1,23 @@ +# Read mono 16bit samples from stdin and write them to the audio device. +# Assume the sampling rate is compatible. +# Use a small queue size to minimize delays. + +import al, sys +import AL + +BUFSIZE = 2000 +QSIZE = 4000 + +def main(): + c = al.newconfig() + c.setchannels(AL.MONO) + c.setqueuesize(QSIZE) + p = al.openport('', 'w', c) + while 1: + data = sys.stdin.read(BUFSIZE) + p.writesamps(data) + +try: + main() +except KeyboardInterrupt: + sys.exit(1) diff --git a/Demo/sgi/al/playold.py b/Demo/sgi/al/playold.py new file mode 100755 index 0000000..85a157d --- /dev/null +++ b/Demo/sgi/al/playold.py @@ -0,0 +1,51 @@ +# Play old style sound files (Guido's private format) + +import al, sys, time +import AL + +BUFSIZE = 8000 + +def main(): + if len(sys.argv) < 2: + f = sys.stdin + filename = sys.argv[0] + else: + if len(sys.argv) <> 2: + sys.stderr.write('usage: ' + \ + sys.argv[0] + ' filename\n') + sys.exit(2) + filename = sys.argv[1] + f = open(filename, 'r') + # + magic = f.read(4) + extra = '' + if magic = '0008': + rate = 8000 + elif magic = '0016': + rate = 16000 + elif magic = '0032': + rate = 32000 + else: + sys.stderr.write('no magic header; assuming 8k samples/sec.\n') + rate = 8000 + extra = magic + # + pv = [AL.OUTPUT_RATE, rate] + al.setparams(AL.DEFAULT_DEVICE, pv) + c = al.newconfig() + c.setchannels(AL.MONO) + c.setwidth(AL.SAMPLE_8) + port = al.openport(filename, 'w', c) + if extra: + port.writesamps(extra) + while 1: + buf = f.read(BUFSIZE) + if not buf: break + port.writesamps(buf) + while port.getfilled() > 0: + time.millisleep(100) + +try: + main() +except KeyboardInterrupt: + sys.exit(1) diff --git a/Demo/sgi/al/radio.py b/Demo/sgi/al/radio.py new file mode 100755 index 0000000..1b72369 --- /dev/null +++ b/Demo/sgi/al/radio.py @@ -0,0 +1,21 @@ +#! /ufs/guido/bin/sgi/python + +# radio [port] +# +# Receive audio packets broadcast by "broadcast.py" on another SGI machine. +# Use apanel to set the output sampling rate to match that of the broadcast. + +import sys, al +from socket import * + +port = 54321 +if sys.argv[1:]: port = eval(sys.argv[1]) + +s = socket(AF_INET, SOCK_DGRAM) +s.bind('', port) + +p = al.openport('radio', 'w') + +while 1: + data = s.recv(1400) + p.writesamps(data) diff --git a/Demo/sgi/al/rec_play.py b/Demo/sgi/al/rec_play.py new file mode 100755 index 0000000..e538b99 --- /dev/null +++ b/Demo/sgi/al/rec_play.py @@ -0,0 +1,28 @@ +# +# records an AIFF sample and plays it +# infinity number of times. +# + +import time +import al + +def recordit () : + p = al.openport('hello', 'r') + print 'recording...' + buf = p.readsamps(500000) + print 'done.' + p.closeport() + + return buf + +def playit (buf) : + p = al.openport('hello', 'w') + print 'playing...' + p.writesamps(buf) + while p.getfilled() > 0: + time.millisleep(10) + print 'done.' + p.closeport() + +while 1 : + playit (recordit ()) diff --git a/Demo/sgi/al/record.py b/Demo/sgi/al/record.py new file mode 100755 index 0000000..e5c0f5b --- /dev/null +++ b/Demo/sgi/al/record.py @@ -0,0 +1,23 @@ +# Record mono 16bits samples from the audio device and send them to stdout. +# Assume the sampling rate is compatible. +# Use a small queue size to minimize delays. + +import al, sys +import AL + +BUFSIZE = 2000 +QSIZE = 4000 + +def main(): + c = al.newconfig() + c.setchannels(AL.MONO) + c.setqueuesize(QSIZE) + p = al.openport('', 'r', c) + while 1: + data = p.readsamps(BUFSIZE) + sys.stdout.write(data) + +try: + main() +except KeyboardInterrupt: + sys.exit(1) diff --git a/Demo/sgi/al/unicast.py b/Demo/sgi/al/unicast.py new file mode 100755 index 0000000..8a53592 --- /dev/null +++ b/Demo/sgi/al/unicast.py @@ -0,0 +1,26 @@ +#! /ufs/guido/bin/sgi/python + +# unicast host [port] +# +# Similar to "broadcast.py" but sends to a specific host only; +# use "radio.py" on the designated host to receive. +# This is less stressful on other hosts on the same ethernet segment +# if you need to send to one host only. + +import sys, al +from socket import * + +host = sys.argv[1] + +port = 54321 +if sys.argv[2:]: port = eval(sys.argv[1]) + +s = socket(AF_INET, SOCK_DGRAM) + +p = al.openport('unicast', 'r') + +address = host, port +while 1: + # 700 samples equals 1400 bytes, or about the max packet size! + data = p.readsamps(700) + s.sendto(data, address) diff --git a/Demo/sgi/al/x.py b/Demo/sgi/al/x.py new file mode 100755 index 0000000..ecc12d8 --- /dev/null +++ b/Demo/sgi/al/x.py @@ -0,0 +1,12 @@ +# Demonstrate that rsh exits when the remote end closes std{in,out,err}. +# rsh voorn exec /ufs/guido/bin/sgi/python /ufs/guido/mm/demo/audio/x.py + +print 'hoi!' +import sys +sys.stdin.close() +sys.stdout.close() +sys.stderr.close() +import time +time.sleep(5) +sys.stdout = open('@', 'w') +sys.stdout.write('Hello\n') |