e37e6d06d1
<rxg@ms25.url.com.tw>, the maintainer of this package). Changes are bugfixes, and use of the native NetBSD sound API instead of OSS emulation.
245 lines
6.4 KiB
Text
245 lines
6.4 KiB
Text
$NetBSD: patch-ag,v 1.3 2000/10/18 11:22:44 rh Exp $
|
|
|
|
--- ../audioIO_NetBSD.c.orig Tue Oct 17 17:50:54 2000
|
|
+++ ../audioIO_NetBSD.c Tue Oct 17 20:01:20 2000
|
|
@@ -0,0 +1,240 @@
|
|
+/* 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.
|
|
+ * Rui-Xiang Guo - NetBSD native API support.
|
|
+ */
|
|
+
|
|
+/* Support for NetBSD sound devices */
|
|
+
|
|
+#include "amp.h"
|
|
+#include "audioIO.h"
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
+#include <stdio.h>
|
|
+#include <errno.h>
|
|
+#include <string.h>
|
|
+#include <malloc.h>
|
|
+#include <stdlib.h>
|
|
+#include <signal.h>
|
|
+#include <sys/audioio.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/filio.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/ioctl.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 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;
|
|
+
|
|
+ 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));
|
|
+
|
|
+ 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 */
|
|
+
|
|
+int device_id = 3;
|
|
+char *mixer_device;
|
|
+mixer_ctrl_t *values;
|
|
+mixer_devinfo_t *infos;
|
|
+
|
|
+void
|
|
+audioSetMixer()
|
|
+{
|
|
+ int i, ndev;
|
|
+ mixer_devinfo_t dinfo;
|
|
+
|
|
+ mixer_device = getenv("MIXERDEVICE");
|
|
+ if (mixer_device == NULL)
|
|
+ mixer_device = "/dev/mixer0";
|
|
+
|
|
+ if ((mixer_fd = open(mixer_device, O_RDWR)) < 0)
|
|
+ warn("Unable to open mixer device\n");
|
|
+ DB(audio, msg("Mixer device opened on %d\n", mixer_fd));
|
|
+
|
|
+ for (ndev = 0; ; ndev++) {
|
|
+ dinfo.index = ndev;
|
|
+ if (ioctl(mixer_fd, AUDIO_MIXER_DEVINFO, &dinfo) < 0)
|
|
+ break;
|
|
+ }
|
|
+ infos = calloc(ndev, sizeof *infos);
|
|
+ values = calloc(ndev, sizeof *values);
|
|
+
|
|
+ for (i = 0; i < ndev; i++) {
|
|
+ infos[i].index = i;
|
|
+ ioctl(mixer_fd, AUDIO_MIXER_DEVINFO, &infos[i]);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ndev; i++) {
|
|
+ if (infos[i].type == AUDIO_MIXER_VALUE) {
|
|
+ values[i].dev = i;
|
|
+ values[i].type = infos[i].type;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ values[device_id].un.value.num_channels = 2;
|
|
+}
|
|
+
|
|
+void
|
|
+audioSetVolume(int volume)
|
|
+{
|
|
+ mixer_ctrl_t *m;
|
|
+
|
|
+ DB(audio, msg("Setting volume to: %d\n", volume));
|
|
+ m = &values[device_id];
|
|
+
|
|
+ if (ioctl(mixer_fd, AUDIO_MIXER_WRITE, m) < 0)
|
|
+ warn("Unable to set sound volume\n");
|
|
+
|
|
+ m->un.value.level[0] = m->un.value.level[1] = volume * AUDIO_MAX_GAIN / 100;
|
|
+}
|
|
+
|
|
+void
|
|
+audioSetBalance(int volume, int balance)
|
|
+{
|
|
+ mixer_ctrl_t *m;
|
|
+
|
|
+ DB(audio, msg("Setting volume to: %d\n", volume));
|
|
+ DB(audio, msg("Setting balance to: %d\n", balance));
|
|
+ m = &values[device_id];
|
|
+
|
|
+ if (ioctl(mixer_fd, AUDIO_MIXER_WRITE, m) < 0)
|
|
+ warn("Unable to set sound volume\n");
|
|
+
|
|
+ if (balance < 0) {
|
|
+ m->un.value.level[0] = volume * AUDIO_MAX_GAIN / 100;
|
|
+ m->un.value.level[1] = m->un.value.level[0] * (20 + balance) / 20;
|
|
+ }
|
|
+ else {
|
|
+ m->un.value.level[1] = volume * AUDIO_MAX_GAIN / 100;
|
|
+ m->un.value.level[0] = m->un.value.level[1] * (20 - balance) / 20;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* audioFlush() */
|
|
+/* should flush the audio device */
|
|
+
|
|
+inline void
|
|
+audioFlush()
|
|
+{
|
|
+ DB(audio, msg("audio: flush %d\n", audio_fd));
|
|
+}
|
|
+
|
|
+
|
|
+/* 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);
|
|
+}
|