Path: utzoo!utgpu!cs.utexas.edu!uunet!mcsun!ukc!mucs!cs.man.ac.uk!mario From: mario@cs.man.ac.uk (Mario Wolczko) Newsgroups: alt.sources Subject: Add flashing lights to your SPARCstation (patch to SunOS4.1 play) Keywords: noise, lights, sound, sparc Message-ID: <2165@m1.cs.man.ac.uk> Date: 20 Feb 91 21:03:58 GMT Sender: news@cs.man.ac.uk Reply-To: mario@cs.man.ac.uk (Mario Wolczko) Organization: Department of Computer Science, University of Manchester Lines: 296 Here's a quick patch to the sun-supplied "play" program (available on sparcstations and SLCs, SunOS4.1 or higher). Inspired by an earlier program to set the keyboard LEDs, it uses them as a VU meter... No man page, and not necessarily very clean, but it works (I think). Enjoy! Mario Wolczko ______ Dept. of Computer Science Internet: mario@cs.man.ac.uk /~ ~\ The University uucp: mcsun!ukc!man.cs!mario ( __ ) Manchester M13 9PL JANET: mario@uk.ac.man.cs `-': :`-' U.K. Tel: +44-61-275 6146 (FAX: 6280) ____; ;_____________the mushroom project___________________________________ *** play.c.sun Fri Dec 21 18:30:16 1990 --- play.c Tue Feb 5 18:23:19 1991 *************** *** 20,25 **** --- 20,26 ---- #include #include + #include #define Error (void) fprintf *************** *** 27,37 **** /* Local variables */ char *prog; char prog_desc[] = "Play an audio file"; ! char prog_opts[] = "Viv:d:?"; /* getopt() flags */ char *Stdin = "stdin"; unsigned char buf[1024 * 64]; /* size should depend on sample_rate */ #define MAX_GAIN (100) /* maximum gain */ --- 28,40 ---- /* Local variables */ char *prog; char prog_desc[] = "Play an audio file"; ! char prog_opts[] = "lViv:d:?"; /* getopt() flags */ char *Stdin = "stdin"; unsigned char buf[1024 * 64]; /* size should depend on sample_rate */ + int kbd; /* fd of kbd */ + unsigned char snd[2]; /* 2 buffer for writes to kbd */ #define MAX_GAIN (100) /* maximum gain */ *************** *** 41,47 **** --- 44,65 ---- */ #define SAMPLE_RATE_THRESHOLD (.01) + /* These define the sample used for averaging to calculate the bar graph size */ + #define LN2_SS 8 + #define SAMPLE_SIZE (1 << LN2_SS) + /* how to convert an average to a bar graph, given only 5 different bar sizes */ + static unsigned char bar[] = { + 0, + LED_CAPS_LOCK, + LED_CAPS_LOCK|LED_COMPOSE, + LED_CAPS_LOCK|LED_COMPOSE, + LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK, + LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK, + LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK|LED_NUM_LOCK, + LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK|LED_NUM_LOCK + }; + unsigned Volume = ~0; /* output volume */ double Savevol; /* saved volume level */ int Verbose = FALSE; /* verbose messages */ *************** *** 52,59 **** Audio_hdr Dev_hdr; /* audio header for device */ char *Ifile; /* current filename */ Audio_hdr File_hdr; /* audio header for file */ - /* Global variables */ extern int getopt(); extern int optind; --- 70,77 ---- Audio_hdr Dev_hdr; /* audio header for device */ char *Ifile; /* current filename */ Audio_hdr File_hdr; /* audio header for file */ + int leds = TRUE; /* use leds as vu meter */ /* Global variables */ extern int getopt(); extern int optind; *************** *** 63,73 **** usage() { Error(stderr, "%s -- usage:\n\t%s ", prog_desc, prog); ! Error(stderr, "\t[-iV] [-v #] [-d dev] [file ...]\nwhere:\n"); Error(stderr, "\t-i\tDon't hang if audio device is busy\n"); Error(stderr, "\t-V\tPrint verbose warning messages\n"); Error(stderr, "\t-v #\tSet output volume (0 - %d)\n", MAX_GAIN); Error(stderr, "\t-d dev\tSpecify audio device (default: /dev/audio)\n"); Error(stderr, "\tfile\tList of files to play\n"); Error(stderr, "\t\tIf no files specified, read stdin\n"); exit(1); --- 81,92 ---- usage() { Error(stderr, "%s -- usage:\n\t%s ", prog_desc, prog); ! Error(stderr, "\t[-iV] [-v #] [-d dev] [-l] [file ...]\nwhere:\n"); Error(stderr, "\t-i\tDon't hang if audio device is busy\n"); Error(stderr, "\t-V\tPrint verbose warning messages\n"); Error(stderr, "\t-v #\tSet output volume (0 - %d)\n", MAX_GAIN); Error(stderr, "\t-d dev\tSpecify audio device (default: /dev/audio)\n"); + Error(stderr, "\t-l\tDon't use the keyboard LEDs\n"); Error(stderr, "\tfile\tList of files to play\n"); Error(stderr, "\t\tIf no files specified, read stdin\n"); exit(1); *************** *** 83,91 **** --- 102,125 ---- (void) audio_set_play_gain(Audio_fd, &Savevol); (void) close(Audio_fd); /* close output */ } + if (leds) { + snd[1]= 0 ; write(kbd, snd, 2); + (void) close(kbd); + } exit(1); } + void set_channel(fd) /* choose output port on env var */ + int fd; + { + extern char *getenv(); + unsigned port= getenv("SST_EARPHONES") ? AUDIO_HEADPHONE : AUDIO_SPEAKER; + + (void) audio_set_play_port(fd, &port); + } + + + /* * Play a list of audio files. */ *************** *** 94,100 **** char **argv; { int i; ! int cnt; int err; int ifd; int stdinseen; --- 128,134 ---- char **argv; { int i; ! int cnt, cum_cnt; int err; int ifd; int stdinseen; *************** *** 101,106 **** --- 135,141 ---- double vol; struct stat st; struct sigvec vec; + register unsigned char *bufp; prog = argv[0]; /* save program initiation name */ *************** *** 123,128 **** --- 158,166 ---- case 'i': Immediate = TRUE; break; + case 'l': + leds = FALSE; + break; case '?': usage(); /*NOTREACHED*/ *************** *** 168,173 **** --- 206,213 ---- exit(1); } + set_channel(Audio_fd); + /* Get the device output encoding configuration */ if (audio_get_play_config(Audio_fd, &Dev_hdr) != AUDIO_SUCCESS) { Error(stderr, "%s: %s is not an audio device\n", *************** *** 188,193 **** --- 228,239 ---- } } + if (leds) { /* open keyboard device */ + kbd= open("/dev/kbd", O_WRONLY); + snd[0]= 016; /* code to set leds */ + if (kbd < 0) leds = FALSE; + } + /* Set up SIGINT handler to flush output */ vec.sv_handler = sigint; vec.sv_mask = 0; *************** *** 254,271 **** /* * At this point, we're all ready to copy the data. */ ! while ((cnt = read(ifd, (char *)buf, sizeof (buf))) >= 0) { ! /* If input EOF, write an eof marker */ ! err = write(Audio_fd, (char *)buf, cnt); ! if (err != cnt) { ! Error(stderr, "%s: output error: ", prog); ! perror(""); ! break; } ! if (cnt == 0) ! break; } if (cnt < 0) { Error(stderr, "%s: error reading ", prog); --- 300,358 ---- /* * At this point, we're all ready to copy the data. + * The outer loop grabs a chunk of data. */ ! for (cum_cnt=0; cnt = read(ifd, (char *)buf, sizeof (buf)), cnt > 0;) { ! /* the inner loop breaks the chunk into ! SAMPLE_SIZEd samples, and averages them */ ! for (bufp= buf; cnt >= SAMPLE_SIZE ; ! bufp += SAMPLE_SIZE, cnt -= SAMPLE_SIZE) { ! register unsigned int total= 0, n; ! /* write to the audio channel */ ! err = write(Audio_fd, (char *)bufp, SAMPLE_SIZE); ! if (err != SAMPLE_SIZE) { ! Error(stderr, "%s: output error: ", prog); ! perror(""); ! break; ! } ! ! if (leds) { ! cum_cnt += SAMPLE_SIZE; ! /* this is the averaging calculation */ ! for (n= 0; n < SAMPLE_SIZE; ++n) { ! unsigned char b=bufp[n]; ! /* full wave rectification */ ! total += b&0x80 ? b^0xFF : b^0x7F; ! } ! ! /* now convert to bargraph pattern */ ! /* seven bits of data -- strip 4 */ ! snd[1]= bar[total >> (LN2_SS + 4)]; ! /* and output to leds */ ! write(kbd, snd, 2); ! ! /* this keeps the leds and audio in sync */ ! cum_cnt += SAMPLE_SIZE; ! if (cum_cnt > 8000) { /* approx 1s */ ! audio_drain(Audio_fd,FALSE); ! cum_cnt= 0; ! } ! } } ! /* remaining chunk: don't average */ ! if (leds) { /* this keeps the leds and audio in sync */ ! cum_cnt += SAMPLE_SIZE; ! if (cum_cnt > 8000) { /* approx 1s */ ! audio_drain(Audio_fd,FALSE); ! cum_cnt= 0; ! } ! snd[1]= 0 ; write(kbd, snd, 2); ! } ! write(Audio_fd, (char *)buf, cnt); ! ! /* If input EOF, write an eof marker */ ! if (cnt > 0) write(Audio_fd, (char *)buf, 0); } if (cnt < 0) { Error(stderr, "%s: error reading ", prog); Brought to you by Super Global Mega Corp .com