diff -c /dev/null ../audioIO_NetBSD.c:1.3 *** /dev/null Wed Jun 14 22:24:24 2000 --- ../audioIO_NetBSD.c Wed Jun 14 22:24:25 2000 *************** *** 0 **** --- 1,198 ---- + /* this file is a part of amp software, (C) tomislav uzelac 1996,1997 + + Origional code by: tomislav uzelac + Modified by: + * Dan Nelson - BSD mods. + * Andrew Richards - moved code from audio.c and added mixer support etc + * Brett Lymn - NetBSD support & 8bit mode. + */ + + /* Support for NetBSD sound devices */ + + #include "amp.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "audioIO.h" + + /* optimal fragment size - if this is set too high you will get clicks + * in the audio output, below is near the upper limit for the sb sound driver + * on my machine (Toshiba 400CDT laptop). + */ + + int AUSIZ = 20480; + + /* declare these static to effectively isolate the audio device */ + + static int audio_fd; + static int mixer_fd; + static int volumeIoctl; + + static char *reduce; + + /* audioOpen() */ + /* should open the audio device, perform any special initialization */ + /* Set the frequency, no of channels and volume. Volume is only set if */ + /* it is not -1 */ + + void + audioOpen(int frequency, int stereo, int volume) + { + audio_info_t audio_dev; + int supportedMixers; + + if ((audio_fd = open ("/dev/audio", O_WRONLY, 0)) == -1) + die("Unable to open the audio device\n"); + DB(audio, msg("Audio device opened on %d\n",audio_fd); ) + + if ((mixer_fd=open("/dev/mixer",O_RDWR)) == -1) + warn("Unable to open mixer device\n"); + DB(audio, msg("Mixer device opened on %d\n",mixer_fd) ); + + if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &supportedMixers) == -1) { + warn("Unable to get mixer info assuming master volume\n"); + volumeIoctl=SOUND_MIXER_WRITE_VOLUME; + } else { + if ((supportedMixers & SOUND_MASK_PCM) != 0) + volumeIoctl=SOUND_MIXER_WRITE_PCM; + else + volumeIoctl=0; + } + + ioctl(audio_fd, AUDIO_GETINFO, &audio_dev); /* get current settings */ + AUDIO_INITINFO(&audio_dev); + + /* Set 1 or 2 channels */ + audio_dev.play.channels = (stereo ? 2 : 1); + + /* Set the output frequency */ + DB(audio, msg("Setting freq to %d Hz\n",frequency) ); + audio_dev.play.sample_rate = frequency; + + if (volume != -1) + audioSetVolume(volume); + + audio_dev.blocksize = AUSIZ; + audio_dev.play.encoding = AUDIO_ENCODING_SLINEAR; + audio_dev.hiwat = 20; + audio_dev.lowat = 1; + audio_dev.mode = AUMODE_PLAY; + + if (ioctl(audio_fd, AUDIO_SETINFO, &audio_dev) < 0) + die("AUDIO_SETINFO failed\n"); + + /* ok - try running the sound system at 16 bits, if that does not + * work then try 8 bits, if that does not work, give up. + */ + reduce = NULL; + audio_dev.play.precision = 16; + if (ioctl(audio_fd, AUDIO_SETINFO, &audio_dev) < 0) { + DB(audio, + msg("AUDIO_SETINFO for 16 bits failed, try 8 bits\n")); + if ((reduce = (char *) malloc(AUSIZ * sizeof(char))) == NULL) + die("Cannot malloc reduce buffer\n"); + audio_dev.play.precision = 8; + if (ioctl(audio_fd, AUDIO_SETINFO, &audio_dev) < 0) + die("AUDIO_SETINFO failed both 16bit and 8bit\n"); + AUSIZ = AUSIZ * sizeof(short); + } + } + + + /* audioSetVolume - only code this if your system can change the volume while */ + /* playing. sets the output volume 0-100 */ + + void + audioSetVolume(int volume) + { + DB(audio, msg("Setting volume to: %d\n",volume); ) + + volume=(volume<<8)+volume; + if ((mixer_fd != -1) && (volumeIoctl!=0)) + if (ioctl(mixer_fd, volumeIoctl, &volume) < 0) + warn("Unable to set sound volume\n"); + } + + + /* audioFlush() */ + /* should flush the audio device */ + + inline void + audioFlush() + { + DB(audio, msg("audio: flush %d\n",audio_fd) ); + + if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) == -1) + die("Unable to reset audio device\n"); + } + + + /* audioClose() */ + /* should close the audio device and perform any special shutdown */ + + void + audioClose() + { + close(audio_fd); + if (mixer_fd != -1) + close(mixer_fd); + DB(audio, msg("audio: closed %d\n",audio_fd) ); + } + + /* audioWrite */ + /* writes count bytes from buffer to the audio device */ + /* returns the number of bytes actually written */ + + inline int + audioWrite(char *buffer, int count) + { + int i; + short *cast; + + DB(audio, msg("audio: Writing %d bytes to audio descriptor %d\n",count, + getAudioFd()) ); + + /* if the reduce buffer is allocated we need to do 8bit writes + * so munge the data buffer appropriately. + */ + if (reduce != NULL) { + cast = (short *) buffer; + + for (i=0; i < count/sizeof(short); i++) { + reduce[i] = cast[i] >> 8; + } + return (sizeof(short) * write(audio_fd, reduce, + count/sizeof(short))); + } else { + return(write(audio_fd,buffer,count)); + } + } + + /* Let buffer.c have the audio descriptor so it can select on it. This means */ + /* that the program is dependent on a file descriptor to work. Should really */ + /* move the select's etc (with inlines of course) in here so that this is the */ + /* ONLY file which has hardware dependent audio stuff in it */ + + int + getAudioFd() + { + return(audio_fd); + }