This is sunplay_mm.c in view mode; [Download] [Up]
#include <config.h> /*****************************************************************/ /*****************************************************************/ /*** ***/ /*** ***/ /*** Play out a 20kHz file on the SPARC ***/ /*** ***/ /*** ***/ /*** H.F. Silverman 1/4/91 ***/ /*** Modified: H.F. Silverman 1/16/91 for amax parameter ***/ /*** Modified: A. Smith 2/14/91 for 8kHz for klatt synth ***/ /*** ***/ /*** Called: hplay(n,volume,amax,a) ***/ /*** ***/ /*** int n -- No. of 8kHz pts. ***/ /*** int device -- 0 -> speaker, 1 -> Jack ***/ /*** ***/ /*** ***/ /*****************************************************************/ /*****************************************************************/ #include <useconfig.h> #include <stdio.h> #include <math.h> #include <errno.h> #include <ctype.h> #include <fcntl.h> #include <sys/file.h> #include <sys/filio.h> #include <sys/stat.h> #include <sys/param.h> #include <signal.h> #include <stropts.h> #include <sys/ioctl.h> #include <multimedia/libaudio.h> #include <multimedia/audio_device.h> #ifndef __svr4__ #include <multimedia/ulaw2linear.h> #endif #include "proto.h" #include "getargs.h" #include "hplay.h" #define SAMP_RATE 8000 long samp_rate = SAMP_RATE; /* Audio Parameters */ int Verbose = FALSE; /* verbose messages */ int Immediate = FALSE; /* Should we hang waiting for device ? */ static int async = TRUE; static Audio_hdr dev_header; /* audio header for device */ static int dev_fd = -1; /* file descriptor for audio device */ char *dev_file = "/dev/audio"; static Audio_hdr ulaw_header; /* audio header for file */ static int ulaw_fd = -1; /* file descriptor for .au ulaw file */ static char *ulaw_file = NULL; static int linear_fd = -1; #ifdef AUDIO_DEV_AMD static int dev_kind = AUDIO_DEV_AMD; #endif /* file descriptor for 16 bit linear file */ static char *linear_file = NULL; char *prog = "hplay"; char *Ifile; /* current filename */ static RETSIGTYPE audio_catch PROTO((int)); static RETSIGTYPE audio_catch(sig) int sig; { fprintf(stderr, "signal\n"); } static int audio_open PROTO((void)) { /* Try it quickly, first */ dev_fd = open(dev_file, O_WRONLY | O_NDELAY); if ((dev_fd < 0) && (errno == EBUSY)) { if (Immediate) { fprintf(stderr, "%s: %s is busy\n", prog, dev_file); return 0; } if (Verbose) { fprintf(stderr, "%s: waiting for %s...", prog, dev_file); (void) fflush(stderr); } /* Now hang until it's open */ dev_fd = open(dev_file, O_WRONLY); if (Verbose) fprintf(stderr, "%s\n", (dev_fd < 0) ? "" : "open"); } else { int flags = fcntl(dev_fd, F_GETFL, NULL); if (flags >= 0) fcntl(dev_fd, F_SETFL, flags & ~O_NDELAY); } if (dev_fd < 0) { fprintf(stderr, "%s: error opening ", prog); perror(dev_file); return 0; } else { #ifdef AUDIO_DEV_AMD /* Get the device output encoding configuration */ if (ioctl(dev_fd, AUDIO_GETDEV, &dev_kind)) { /* Old releases of SunOs don't support the ioctl, but can only be run on old machines which have AMD device... */ dev_kind = AUDIO_DEV_AMD; } #endif if (audio_get_play_config(dev_fd, &dev_header) != AUDIO_SUCCESS) { fprintf(stderr, "%s: %s is not an audio device\n", prog, dev_file); close(dev_fd); dev_fd = -1; return 0; } } return 1; } int audio_init(argc, argv) int argc; char *argv[]; { int rate_set = 0; int use_linear = 0; int use_audio = 1; double gain = -1.0; int headphone = 2; int speaker = 2; prog = argv[0]; argc = getargs("Old Sun (demo/SOUND)",argc, argv, "g", "%lg", &gain, "Gain 0 .. 1.0", "r", "%d", &rate_set, "Sample rate", "h", NULL, &headphone, "Headphones", "s", NULL, &speaker, "Speaker", "a", NULL, &use_audio, "Audio enable", "L", NULL, &use_linear, "Force linear", "u", "", &ulaw_file, "Sun .au file", "l", "", &linear_file, "Raw linear file", NULL); if (help_only) return argc; if (ulaw_file) { if (strcmp(ulaw_file, "-") == 0) { ulaw_fd = 1; /* stdout */ } else { ulaw_fd = open(ulaw_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (ulaw_fd < 0) perror(ulaw_file); } } if (linear_file) { if (strcmp(linear_file, "-") == 0) { linear_fd = 1 /* stdout */ ; } else { linear_fd = open(linear_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (linear_fd < 0) perror(linear_file); } } if (rate_set) { samp_rate = rate_set; } if (use_audio && audio_open()) { if (!rate_set) samp_rate = dev_header.sample_rate; if (rate_set || use_linear) { dev_header.sample_rate = samp_rate; if (samp_rate > 8000 || use_linear) { dev_header.encoding = AUDIO_ENCODING_LINEAR; dev_header.bytes_per_unit = 2; } if (audio_set_play_config(dev_fd, &dev_header) != AUDIO_SUCCESS) { fprintf(stderr, "%s : %s cannot accept sample rate of %ldHz\n", prog, dev_file, samp_rate); close(dev_fd); dev_fd = -1; } } } if (dev_fd >= 0) { int myport = 0; if (gain >= 0.0) { int err = audio_set_play_gain(dev_fd, &gain); if (err != AUDIO_SUCCESS) { fprintf(stderr, "%s: could not set output volume for %s\n", prog, dev_file); } } if (headphone != 2) { if (headphone) myport |= AUDIO_HEADPHONE; else myport &= ~AUDIO_HEADPHONE; } if (speaker != 2) { if (speaker) myport |= AUDIO_SPEAKER; else myport &= ~AUDIO_SPEAKER; } if (myport != 0) audio_set_play_port(dev_fd, &myport); if (async) { int flag = 1; /* May need to use streams calls to send a SIGPOLL when write buffer is no longer full and use non-blocking writes, and manipluate our own buffer of unwritten data. However, at present just use FIOASYNC which means write returns as soon as it can queue the data (I think). */ signal(SIGIO, audio_catch); ioctl(dev_fd, FIOASYNC, &flag); } } if (ulaw_fd >= 0) { ulaw_header.sample_rate = samp_rate; if (samp_rate > 8000) { ulaw_header.encoding = AUDIO_ENCODING_LINEAR; ulaw_header.bytes_per_unit = 2; } else { ulaw_header.encoding = AUDIO_ENCODING_ULAW; ulaw_header.bytes_per_unit = 1; } ulaw_header.samples_per_unit = 1; ulaw_header.channels = 1; ulaw_header.data_size = AUDIO_UNKNOWN_SIZE; /* Write header - note that data_size is unknown at this stage, so we set it to AUDIO_UNKNOWN_SIZE (AFEB); if all goes well we will lseek back and do this again in audio_term() */ audio_write_filehdr(ulaw_fd, &ulaw_header, NULL, 0); /* reset the header info, so we can simply add to it */ ulaw_header.data_size = 0; } return argc; } void audio_term() { /* Close audio system */ if (dev_fd >= 0) { audio_drain(dev_fd, FALSE); close(dev_fd); dev_fd = -1; if (async) signal(SIGPOLL, SIG_DFL); } /* Finish ulaw file */ if (ulaw_fd >= 0) { off_t here = lseek(ulaw_fd, 0L, SEEK_CUR); if (here >= 0) { /* can seek this file - truncate it */ ftruncate(ulaw_fd, here); /* Now go back and overwite header with actual size */ if (lseek(ulaw_fd, 0L, SEEK_SET) == 0) { audio_write_filehdr(ulaw_fd, &ulaw_header, NULL, 0); } } close(ulaw_fd); ulaw_fd = -1; } /* Finish linear file */ if (linear_fd >= 0) { ftruncate(linear_fd, lseek(linear_fd, 0L, SEEK_CUR)); close(linear_fd); linear_fd = -1; } } void audio_play(n, data) int n; short *data; { if (n > 0) { if (linear_fd >= 0) { unsigned size = n * sizeof(short); if (write(linear_fd, data, n * sizeof(short)) != size) perror("write"); } if (dev_fd >= 0 && dev_header.encoding == AUDIO_ENCODING_LINEAR) { unsigned size = n * sizeof(short); if (write(dev_fd, data, n * sizeof(short)) != size) perror("write"); } if (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_LINEAR) { unsigned size = n * sizeof(short); if (write(ulaw_fd, data, n * sizeof(short)) != size) perror("write"); else ulaw_header.data_size += size; } if ((dev_fd >= 0 && dev_header.encoding == AUDIO_ENCODING_ULAW) || (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_ULAW)) { unsigned char *plabuf = (unsigned char *) malloc(n); if (plabuf) { int w; unsigned char *p = plabuf; unsigned char *e = p + n; while (p < e) { *p++ = audio_s2u(*data++); } if (dev_fd >= 0 && dev_header.encoding == AUDIO_ENCODING_ULAW) { p = plabuf; while ((w = write(dev_fd, p, n)) != n) { if (w == -1) { fprintf(stderr, "%d,%s:%d\n", errno, __FILE__, __LINE__); perror("audio"); abort(); } else { fprintf(stderr, "Writing %u, only wrote %u\n", n, w); p += w; n -= w; } } } if (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_ULAW) { if (write(ulaw_fd, plabuf, n) != n) perror(ulaw_file); else ulaw_header.data_size += n; } free(plabuf); } else { fprintf(stderr, "%s : No memory for ulaw data\n", prog); } } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.