From a19a216bc60160c162e616145ef091dd18ce4e61 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Feb 2021 14:40:46 -0600 Subject: Python 0.9.1 as posted in alt.sources --- src/audiomodule.c | 615 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 615 insertions(+) create mode 100644 src/audiomodule.c (limited to 'src/audiomodule.c') diff --git a/src/audiomodule.c b/src/audiomodule.c new file mode 100644 index 0000000..cca0102 --- /dev/null +++ b/src/audiomodule.c @@ -0,0 +1,615 @@ +/*********************************************************** +Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* Silicon Graphics audio module implementation */ +/* For SGI Personal IRIS 4D/20 under IRIX 3.3; mentions "IP6" */ +/* Note: The set-in-gain ioctl exists but is non-functional */ + +#include +#include +#include "asa.h" + +#include "allobjects.h" +#include "modsupport.h" + +static int audio_fd = -1; + +static int +init() +{ + if (audio_fd >= 0) + return 1; + if ((audio_fd = asa_init()) >= 0) + return 1; + err_setstr(RuntimeError, "can't initialize async audio"); + return 0; +} + + +/* POSIX methods */ + +static object * +audio_get_ioctl(self, args, code) + object *self; + object *args; + long code; +{ + long x; + if (!getnoarg(args)) + return NULL; + if (!init()) + return NULL; + if ((x = ioctl(audio_fd, code, (char *) NULL)) < 0) { + return NULL; + } + return newintobject(x); +} + +static object * +audio_set_ioctl(self, args, code) + object *self; + object *args; + long code; +{ + long x; + if (!getlongarg(args, &x)) + return NULL; + if (!init()) + return NULL; + if (ioctl(audio_fd, code, (char *) x) != 0) + return NULL; + INCREF(None); + return None; +} + +static object * +audio_getingain(self, args) + object *self; + object *args; +{ + return audio_get_ioctl(self, args, AUDIOCGETINGAIN); +} + +static object * +audio_getoutgain(self, args) + object *self; + object *args; +{ + return audio_get_ioctl(self, args, AUDIOCGETOUTGAIN); +} + +static object * +audio_setingain(self, args) + object *self; + object *args; +{ + return audio_set_ioctl(self, args, AUDIOCSETINGAIN); +} + +static object * +audio_setoutgain(self, args) + object *self; + object *args; +{ + return audio_set_ioctl(self, args, AUDIOCSETOUTGAIN); +} + +static object * +audio_setrate(self, args) + object *self; + object *args; +{ + return audio_set_ioctl(self, args, AUDIOCSETRATE); +} + +static object * +audio_setduration(self, args) + object *self; + object *args; +{ + return audio_set_ioctl(self, args, AUDIOCDURATION); +} + +/* Compute average bias, and remove it */ + +static void +unbias(buf, len) + char *buf; + int len; +{ + register int i; + register int c; + register long bias; + if (len == 0) + return; + bias = 0; + for (i = 0; i < len; i++) { + c = buf[i]; + if (c > 127) + c -= 256; + bias += c; + } + bias = (bias + len/2) / len; /* Rounded average */ + if (bias != 0) { + for (i = 0; i < len; i++) { + buf[i] -= bias; + } + } +} + +static object * +audio_read(self, args) + object *self; + object *args; +{ + int c, i, n; + object *v; + char *s; + if (!getintarg(args, &n)) + return NULL; + if (n <= 0) { + err_setstr(RuntimeError, "audio.read: arg <= 0"); + return NULL; + } + if (!init()) + return NULL; + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return err_nomem(); + s = getstringvalue(v); + n = read(audio_fd, s, n); + if (intrcheck()) { + DECREF(v); + err_set(KeyboardInterrupt); + return NULL; + } + /* Check for errors */ + if (n < 0) { + DECREF(v); + return NULL; + } + /* But EOF is reported as an empty string */ + + unbias(s, n); + resizestring(&v, n); + return v; +} + +static object * +audio_write(self, args) + object *self; + object *args; +{ + int n, n2; + object *v; + if (!getstrarg(args, &v)) + return NULL; + if (!init()) + return NULL; + errno = 0; + n2 = write(audio_fd, getstringvalue(v), n = getstringsize(v)); + if (intrcheck()) { + err_set(KeyboardInterrupt); + return NULL; + } + /* Check for other errors */ + if (n2 != n) { + if (errno == 0) + errno = EIO; + return NULL; + } + INCREF(None); + return None; +} + +/* audio.amplify(sample, f1, f2). + Amplify a sample by a factor changing from f1/256 to (almost) f2/256. + Negative factors are allowed. Sound values that are to large + to fit in a byte are clipped. */ + +static object * +audio_amplify(self, args) + object *self; + object *args; +{ + object *v; + char *s, *t; + int f1, f2; + int i, n; + int c; + if (!getstrintintarg(args, &v, &f1, &f2)) + return NULL; + n = getstringsize(v); + s = getstringvalue(v); + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return err_nomem(); + t = getstringvalue(v); + for (i = 0; i < n; i++) { + c = s[i]; + if (c > 127) c -= 256; /* If chars are unsigned */ + c = c * ( f1*(n-i) + f2*i ) / ( n*256 ); + if (c > 127) c = 127; + else if (c < -128) c = -128; + t[i] = c; + } + return v; +} + +/* audio.reverse(s): return a sample backwards */ + +static object * +audio_reverse(self, args) + object *self; + object *args; +{ + object *v; + char *s, *t; + int i, n; + if (!getstrarg(args, &v)) + return NULL; + n = getstringsize(v); + s = getstringvalue(v); + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return err_nomem(); + t = getstringvalue(v); + for (i = 0; i < n; i++) { + t[n-1-i] = s[i]; + } + return v; +} + +/* audio.add(a, b): add two samples. + Bytes that exceed the range are clipped. + If one is shorter, the rest of the longer sample is returned unchanged. */ + +static object * +audio_add(self, args) + object *self; + object *args; +{ + object *a, *b, *v; + char *sa, *sb, *t; + int i, n, na, nb, c, ca, cb; + if (!getstrstrarg(args, &a, &b)) + return NULL; + na = getstringsize(a); + sa = getstringvalue(a); + nb = getstringsize(b); + sb = getstringvalue(b); + n = (na > nb) ? na : nb; + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return err_nomem(); + t = getstringvalue(v); + for (i = 0; i < n; i++) { + c = 0; + if (i < na) { + ca = sa[i]; + if (ca > 127) ca = ca - 256; + c = c + ca; + } + if (i < nb) { + cb = sb[i]; + if (cb > 127) cb = cb - 256; + c = c + cb; + } + if (c > 127) c = 127; + else if (c < -128) c = -128; + t[i] = c; + } + return v; +} + +/* audio.chr2num(s) returns a list containing the numeric values + of the samples. */ + +static object * +audio_chr2num(self, args) + object *self; + object *args; +{ + object *v, *w; + char *s; + int c, i, n; + static object *ints[256]; + + /* To avoid filling memory with all those int objects, we create + integer objects for all the desired values and reference these. */ + if (ints[255] == NULL) { + for (i = 0; i < 256; i++) { + if (ints[i] != NULL) + continue; + c = i; + if (c > 127) c -= 256; + ints[i] = newintobject((long)c); + if (ints[i] == NULL) + return NULL; + } + } + + if (!getstrarg(args, &v)) + return NULL; + n = getstringsize(v); + s = getstringvalue(v); + v = newlistobject(n); + if (v == NULL) + return err_nomem(); + for (i = 0; i < n; i++) { + c = s[i] & 0xff; + w = ints[c]; + INCREF(w); + if (setlistitem(v, i, w) != 0) { + DECREF(v); + return NULL; + } + } + return v; +} + +/* audio.num2chr is the inverse of audio.chr2num. + Excess values are clipped. */ + +static object * +audio_num2chr(self, args) + object *self; + object *args; +{ + object *v, *w; + char *s; + int c, i, n; + if (!is_listobject(args)) { + err_badarg(); + return NULL; + } + n = getlistsize(args); + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return NULL; + s = getstringvalue(v); + for (i = 0; i < n; i++) { + w = getlistitem(args, i); + if (!is_intobject(w)) { + DECREF(v); + err_badarg(); + return NULL; + } + s[i] = getintvalue(w); + } + return v; +} + +static object *stdaudio_buffer = NULL; + +static object * +audio_start_recording(self, args) + object *self; + object *args; +{ + int n; + object *v; + char *s; + if (!getintarg(args, &n)) + return NULL; + if (stdaudio_buffer != NULL) { + err_setstr(RuntimeError, "audio.start_recording: device busy"); + return NULL; + } + if (n <= 0) { + err_setstr(TypeError, "audio.start_recording: arg <= 0"); + return NULL; + } + if (!init()) + return NULL; + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) + return err_nomem(); + s = getstringvalue(v); + asa_start_read(s, n); + stdaudio_buffer = v; + INCREF(None); + return None; +} + +static object * +audio_poll(self, args) + object *self; + object *args; +{ + int n; + if (!getnoarg(args)) + return NULL; + if (stdaudio_buffer == NULL) { + err_setstr(RuntimeError, "audio.poll: not busy"); + return NULL; + } + if (!init()) + return NULL; + if ((n = asa_poll()) < 0) + return NULL; + return newintobject(n); +} + +static object * +audio_wait_recording(self, args) + object *self; + object *args; +{ + object *v; + int n; + if (!getnoarg(args)) + return NULL; + if (stdaudio_buffer == NULL) { + err_setstr(RuntimeError, "audio.wait_recording: not busy"); + return NULL; + } + if (!init()) + return NULL; + if ((n = asa_wait()) < 0) + return NULL; + v = stdaudio_buffer; + stdaudio_buffer = NULL; + unbias(getstringvalue(v), n); + resizestring(&v, n); + return v; +} + +static object * +audio_stop_recording(self, args) + object *self; + object *args; +{ + int n; + object *v; + char *s; + if (!getnoarg(args)) + return NULL; + if (stdaudio_buffer == NULL) { + err_setstr(RuntimeError, "audio.stop_recording: not busy"); + return NULL; + } + if ((n = asa_cancel()) < 0) + return NULL; + v = stdaudio_buffer; + stdaudio_buffer = NULL; + s = getstringvalue(v); + unbias(s, n); + resizestring(&v, n); + return v; +} + +static object * +audio_start_playing(self, args) + object *self; + object *args; +{ + object *v; + if (!getstrarg(args, &v)) + return NULL; + if (stdaudio_buffer != NULL) { + err_setstr(RuntimeError, "audio.start_recording: device rbusy"); + return NULL; + } + asa_start_write(getstringvalue(v), (int)getstringsize(v)); + INCREF(v); + stdaudio_buffer = v; + INCREF(None); + return None; +} + +static object * +audio_wait_playing(self, args) + object *self; + object *args; +{ + int n; + if (!getnoarg(args)) + return NULL; + if (stdaudio_buffer == NULL) { + err_setstr(RuntimeError, "audio.wait_playing: not busy"); + return NULL; + } + if ((n = asa_wait()) < 0) + return NULL; + DECREF(stdaudio_buffer); + stdaudio_buffer = NULL; + /* XXX return newintobject((long)n); ??? */ + INCREF(None); + return None; +} + +static object * +audio_stop_playing(self, args) + object *self; + object *args; +{ + int n; + if (!getnoarg(args)) + return NULL; + if (stdaudio_buffer == NULL) { + err_setstr(RuntimeError, "audio.stop_playing: not busy"); + return NULL; + } + if ((n = asa_cancel()) < 0) + return NULL; + DECREF(stdaudio_buffer); + stdaudio_buffer = NULL; + return newintobject((long)n); +} + +static object * +audio_audio_done(self, args) + object *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + asa_done(); + if (stdaudio_buffer != NULL) + DECREF(stdaudio_buffer); + stdaudio_buffer = NULL; + audio_fd = -1; + INCREF(None); + return None; +} + + +static struct methodlist audio_methods[] = { + {"getingain", audio_getingain}, + {"getoutgain", audio_getoutgain}, + {"setingain", audio_setingain}, + {"setoutgain", audio_setoutgain}, + {"setrate", audio_setrate}, + {"setduration", audio_setduration}, + {"read", audio_read}, + {"write", audio_write}, + {"amplify", audio_amplify}, + {"reverse", audio_reverse}, + {"add", audio_add}, + {"chr2num", audio_chr2num}, + {"num2chr", audio_num2chr}, + + /* "asa" interface: */ + + {"start_recording", audio_start_recording}, + {"poll_recording", audio_poll}, + {"wait_recording", audio_wait_recording}, + {"stop_recording", audio_stop_recording}, + + {"start_playing", audio_start_playing}, + {"poll_playing", audio_poll}, + {"wait_playing", audio_wait_playing}, + {"stop_playing", audio_stop_playing}, + + {"done", audio_audio_done}, + + {NULL, NULL} /* Sentinel */ +}; + +void +initaudio() +{ + initmodule("audio", audio_methods); +} -- cgit v1.2.3