- Roll back the patch from about changeset 67, with the

adding of pthreads; that's all gone now, it sucked.
- Add a libao sound output, this has been mostly tested:
  - it works with wav output on my powerbook (where oss out
    is broken)
  - it works but sounds really jumpy when playing 44100Hz
    samples through a shitty onboard soundcard that only
    supports 48000Hz output... the dma buffer gets played
    too fast.
This commit is contained in:
Jamie Wilkinson 2004-02-02 12:42:18 +00:00
parent 2012da9a05
commit f581c7d17d
6 changed files with 300 additions and 333 deletions

View file

@ -226,192 +226,3 @@ int main (int argc, char *argv[])
AC_SUBST(SDL_LIBS)
rm -f conf.sdltest
])
dnl ACX_PTHREAD macro by Steven G. Johnson <stevenj@alum.mit.edu> and
dnl Alejandro Forero Cuervo <bachue@bachue.com>. Found at:
dnl http://www.gnu.org/software/ac-archive/Installed_Packages/acx_pthread.html
AC_DEFUN([ACX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
acx_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
AC_MSG_RESULT($acx_pthread_ok)
if test x"$acx_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all.
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# pthread: Linux, etcetera
# --thread-safe: KAI C++
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthread or
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
;;
esac
if test x"$acx_pthread_ok" = xno; then
for flag in $acx_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[acx_pthread_ok=yes])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($acx_pthread_ok)
if test "x$acx_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$acx_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: threads are created detached by default
# and the JOINABLE attribute has a nonstandard name (UNDETACHED).
AC_MSG_CHECKING([for joinable pthread attribute])
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_JOINABLE;],
ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
if test x"$ok" = xunknown; then
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_UNDETACHED;],
ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
fi
if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
[Define to the necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_RESULT(${ok})
if test x"$ok" = xunknown; then
AC_MSG_WARN([we do not know how to create joinable pthreads])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case "${host_cpu}-${host_os}" in
*-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
*solaris* | alpha*-osf*) flag="-D_REENTRANT";;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: must compile with cc_r
AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$acx_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
acx_pthread_ok=no
$2
fi
])dnl ACX_PTHREAD

View file

@ -76,9 +76,6 @@ OSS_LIBS=""
AC_CHECK_LIB([ossaudio], [_oss_ioctl], [OSS_LIBS="-lossaudio"])
AC_SUBST(OSS_LIBS)
dnl Check for POSIX threads
ACX_PTHREAD(,AC_MSG_ERROR(["POSIX threads required!"]))
dnl -----------------
dnl Check for SVGAlib
dnl -----------------
@ -311,6 +308,64 @@ dnl ---------------------
HAVE_ZIP=disabled
dnl ---------------
dnl Check for libao
dnl ---------------
HAVE_AO=no
AC_ARG_WITH(ao,
AC_HELP_STRING([--with-ao(=DIR)],
[use libao (optionally, found in DIR)]),
dnl argument was given, check for --without
if test "x${with_ao}" != xno ; then
ac_with_ao=yes
else
ac_with_ao=no
fi,
ac_with_ao=auto
)
if test "x${ac_with_ao}" != xno ; then
dnl --with-ao was explicitly given, so look in the given dir
if test "x${ac_with_ao}" != xauto ; then
AO_CFLAGS="$AO_CFLAGS -I$withval/include"
AO_LIBS="$AO_LIBS -L$withval/lib"
fi
dnl set CPPFLAGS for coming tests
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $AO_CFLAGS"
dnl test for installed library first, for people who may have
dnl the libs installed by no headers
AC_CHECK_LIB(ao, ao_initialize,
AO_LIBS="$AO_LIBS -lao"
HAVE_AO=maybe,
HAVE_AO=no,
[$AO_LIBS])
dnl check the header
if test "x$HAVE_AO" = xmaybe ; then
AC_CHECK_HEADER(ao/ao.h,
HAVE_AO=yes,
HAVE_AO=no
)
fi
dnl sum up
if test "x$HAVE_AO" = xyes ; then
AC_DEFINE(HAVE_AO, 1, [Define this if you have libao])
AC_SUBST(AO_LIBS)
AC_SUBST(AO_CFLAGS)
else
dnl if we were explicitly told to use ao and it's not there
if test "x${ac_with_ao}" = xyes ; then
AC_MSG_WARN([
*** You have explicitly asked for libao support, but the required libraries
*** and development files could not be found.])
fi
fi
dnl clean up
CPPFLAGS="$save_CPPFLAGS"
else
HAVE_AO=disabled
fi
dnl -----------------------
dnl Checks for header files
dnl -----------------------
@ -700,6 +755,8 @@ AC_MSG_RESULT([ SDL: ............. $HAVE_SDL])
dnl AC_MSG_RESULT([ Framebuffer: ..... $HAVE_FB])
dnl AC_MSG_RESULT([ AAlib: ........... $HAVE_AA])
AC_MSG_RESULT([ libao .............. $HAVE_AO])
AC_MSG_RESULT([
Installation directories:

View file

@ -47,7 +47,7 @@ endif
if BUILD_SDLQUAKE2
SOUND = cd_sdl.c snd_sdl.c snd_dma.c snd_mix.c snd_mem.c
else
SOUND = cd.c snd.c snd_dma.c snd_mix.c snd_mem.c
SOUND = cd.c snd_ao.c snd_dma.c snd_mix.c snd_mem.c
endif
quake2_SOURCES = main.c q_sh.c vid_menu.c vid_so.c q_glob.c net_udp.c \
@ -83,21 +83,17 @@ EXTRA_ref_tdfx_la_SOURCES = rw_in_svgalib.c gl_fxmesa.c
EXTRA_ref_softx_la_SOURCES = rw_x11.c
EXTRA_quake2_SOURCES = snd_mixa.S cd_sdl.c snd_sdl.c snd_dma.c \
snd_mix.c snd_mem.c cd.c snd.c
snd_mix.c snd_mem.c cd.c snd_ao.c
if BUILD_SDLQUAKE2
quake2_CFLAGS = $(std_cflags) @PTHREAD_CFLAGS@ @SDL_CFLAGS@
quake2_CFLAGS = $(std_cflags) @SDL_CFLAGS@
else
quake2_CFLAGS = $(std_cflags) @PTHREAD_CFLAGS@
quake2_CFLAGS = $(std_cflags)
endif
# the macro puts -pthread into cflags, but we want to link
# with this flag too, so stick it into the ldflags if it's there...
# extra cflags at link time can't hurt
quake2_LDFLAGS = @PTHREAD_CFLAGS@
if BUILD_SDLQUAKE2
quake2_LDADD = @PTHREAD_LIBS@ @DL_LIBS@ @OSS_LIBS@ @SDL_LIBS@ @SYSTEM_LIBS@ -lm
quake2_LDADD = @DL_LIBS@ @AO_LIBS@ @SDL_LIBS@ @SYSTEM_LIBS@ -lm
else
quake2_LDADD = @PTHREAD_LIBS@ @DL_LIBS@ @OSS_LIBS@ @SYSTEM_LIBS@ -lm
quake2_LDADD = @DL_LIBS@ @AO_LIBS@ @SYSTEM_LIBS@ -lm
endif
# ref_glx

View file

@ -49,7 +49,6 @@
#include <mntent.h>
#elif defined(__FreeBSD__) || defined(__bsd__) || defined (__NetBSD__)
#include <fstab.h>
#include <pthread.h>
#elif defined(__sun__)
#include <sys/file.h>
#endif
@ -327,7 +326,6 @@ XilSystemState xil_state;
int main (int argc, char **argv) {
int time, oldtime, newtime;
sigset_t sigs;
#ifdef SOL8_XIL_WORKAROUND
{
@ -353,11 +351,6 @@ int main (int argc, char **argv) {
}
}
/* block the SIGPOLL signal so that only the audio thread gets it */
sigemptyset(&sigs);
sigaddset(&sigs, SIGPOLL);
pthread_sigmask(SIG_BLOCK, &sigs, NULL);
/* go back to real user for config loads */
saved_euid = geteuid();
seteuid(getuid());

180
src/snd.c
View file

@ -31,7 +31,6 @@
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
@ -55,12 +54,6 @@
#include "client.h"
#include "snd_loc.h"
#define FRAGSIZEEXP 9
#define FRAGSIZE (1<<FRAGSIZEEXP)
#define AUDIOBUFFERSIZE 4096
#define AUDIOBUFFERS 64
#ifdef __sgi
/* must be a power of 2! */
@ -80,8 +73,6 @@ long long sgisnd_lastframewritten = 0;
static int audio_fd = -1;
static volatile int snd_inited;
static volatile int frags_sent;
static int mmapped = 0;
static int tryrates[] = { 11025, 22051, 44100, 48000, 8000 };
@ -95,19 +86,6 @@ cvar_t *snddevice;
cvar_t * s_loadas8bit;
cvar_t * s_khz;
static pthread_t audio;
void * thesound(void * arg) {
while (snd_inited) {
write(audio_fd, dma.buffer + frags_sent * FRAGSIZE, FRAGSIZE);
frags_sent++;
frags_sent &= (dma.samples * (dma.samplebits/8) / FRAGSIZE) - 1;
}
pthread_exit(0L);
/* Not reached */
return NULL;
}
qboolean SNDDMA_Init(void) {
/* merged in from snd_irix.c -- jaq */
#ifdef __sgi
@ -193,7 +171,7 @@ qboolean SNDDMA_Init(void) {
alFreeConfig(ac);
return true;
#else /* __sgi */
#else /* !__sgi */
int rc;
int fmt;
int tmp;
@ -214,7 +192,7 @@ qboolean SNDDMA_Init(void) {
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
}
// open /dev/dsp, check capability to mmap, and get size of dma buffer
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
/* snd_bsd.c had "if (!audio_fd)" */
if (audio_fd == -1)
@ -248,37 +226,23 @@ qboolean SNDDMA_Init(void) {
return 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1
|| !(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
Com_Printf("SNDDMA_Init: Sound device does not support mmap");
} else {
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Sound driver too old.\n");
close(audio_fd);
audio_fd = -1;
return 0;
} else
mmapped = 1;
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
{
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Sound driver too old.\n");
close(audio_fd);
audio_fd = -1;
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
if (!mmapped) {
int frags = 2 << 16 | FRAGSIZEEXP;
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frags) == -1) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not set sound fragments");
/* NOMMAP - jaq
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
{
Com_Printf("SNDDMA_Init: Sorry, but your soundcard doesn't support trigger or mmap. (%08x)\n", caps);
*/
close(audio_fd);
audio_fd = -1;
return 0;
}
}
close(audio_fd);
audio_fd = -1;
return 0;
}
/* NOMMAP - jaq
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
{
perror("GETOSPACE");
@ -287,7 +251,6 @@ qboolean SNDDMA_Init(void) {
audio_fd = -1;
return 0;
}
*/
// set sample bits & speed
@ -390,67 +353,49 @@ qboolean SNDDMA_Init(void) {
// toggle the trigger & start her up
if (!mmapped) {
dma.submission_chunk = AUDIOBUFFERSIZE;
dma.samples = AUDIOBUFFERS * dma.submission_chunk * dma.channels;
dma.samplepos = 0;
if ((dma.buffer = malloc(dma.samples * (dma.samplebits/8))) == 0) {
perror(snddevice->string);
Com_Printf("Could not allocate shm->buffer");
close(audio_fd);
audio_fd = -1;
return 0;
}
snd_inited = 1;
pthread_create(&audio, 0L, thesound, 0L);
} else {
tmp = 0;
tmp = 0;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
dma.submission_chunk = 1;
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
dma.submission_chunk = 1;
// memory map the dma buffer
// memory map the dma buffer
if (!dma.buffer) {
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize,
if (!dma.buffer) {
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize,
#if defined(__FreeBSD__) && (__FreeBSD_version < 500000)
PROT_READ|PROT_WRITE,
PROT_READ|PROT_WRITE,
#else
PROT_WRITE,
PROT_WRITE,
#endif
MAP_FILE|MAP_SHARED, audio_fd, 0);
}
if (!dma.buffer || dma.buffer == MAP_FAILED) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not mmap %s.\n", snddevice->string);
close(audio_fd);
audio_fd = -1;
return 0;
}
if (rc < 0) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not toggle. (1)\n");
close(audio_fd);
audio_fd = -1;
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not toggle. (2)\n");
close(audio_fd);
audio_fd = -1;
return 0;
}
dma.samplepos = 0;
snd_inited = 1;
MAP_FILE|MAP_SHARED, audio_fd, 0);
}
if (!dma.buffer || dma.buffer == MAP_FAILED) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not mmap %s.\n", snddevice->string);
close(audio_fd);
audio_fd = -1;
return 0;
}
if (rc < 0) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not toggle. (1)\n");
close(audio_fd);
audio_fd = -1;
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("SNDDMA_Init: Could not toggle. (2)\n");
close(audio_fd);
audio_fd = -1;
return 0;
}
dma.samplepos = 0;
snd_inited = 1;
return 1;
#endif /* !__sgi */
}
@ -481,9 +426,6 @@ int SNDDMA_GetDMAPos(void) {
if (!snd_inited) return 0;
if (!mmapped)
return (frags_sent * FRAGSIZE) / (dma.samplebits/8) + FRAGSIZE/16;
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
{
perror(snddevice->string);
@ -515,22 +457,12 @@ void SNDDMA_Shutdown(void) {
}
#else
if (snd_inited) {
if (!mmapped) {
snd_inited = 0L;
pthread_join(audio, 0L);
munmap (dma.buffer, dma.samples *dma.samplebits / 8);
dma.buffer = 0L;
if (dma.buffer) {
free(dma.buffer);
dma.buffer = 0L;
}
} else {
munmap (dma.buffer, dma.samples *dma.samplebits / 8);
dma.buffer = 0L;
}
close(audio_fd);
audio_fd = -1;
snd_inited = 0;
close(audio_fd);
audio_fd = -1;
snd_inited = 0;
}
#endif
}

178
src/snd_ao.c Normal file
View file

@ -0,0 +1,178 @@
/* libao sound output
*
* Copyright (c) 2004 Jamie Wilkinson <jaq@spacepants.org>
* for The Quakeforge Project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_AO
# include <ao/ao.h>
#endif
#include "client.h"
#include "snd_loc.h"
static int snd_inited;
static int samplesize;
cvar_t * sndbits;
cvar_t * sndspeed;
cvar_t * sndchannels;
cvar_t * snddevice;
ao_device * device;
/* SNDDMA_Init: initialises cycling through a DMA bufffer and returns
* information on it
*/
qboolean SNDDMA_Init(void) {
int driver_id;
ao_sample_format format;
ao_option * options = NULL;
if (!snddevice) {
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
}
ao_initialize();
#if 1
if ((driver_id = ao_default_driver_id()) == -1) {
#else
if ((driver_id = ao_driver_id("wav")) == -1) {
#endif
Com_Printf("Couldn't find a default driver for sound output\n");
return 0;
}
/*ao_append_option(&options, "debug", "");*/
format.bits = dma.samplebits = sndbits->value;
format.rate = dma.speed = 44100;
format.channels = dma.channels = sndchannels->value;
format.byte_format = AO_FMT_NATIVE;
switch (dma.speed) {
case 44100:
dma.samples = 2048 * dma.channels;
break;
case 22050:
dma.samples = 1024 * dma.channels;
break;
default:
dma.samples = 512 * dma.channels;
break;
}
#if 1
if ((device = ao_open_live(driver_id, &format, options)) == NULL) {
#else
if ((device = ao_open_file(driver_id, "foo.wav", 1, &format, options)) == NULL) {
#endif
switch (errno) {
case AO_ENODRIVER:
Com_Printf("W: No ao driver for %d\n", driver_id);
break;
case AO_ENOTLIVE:
Com_Printf("W: Not a valid live output device\n");
break;
case AO_EBADOPTION:
Com_Printf("W: Valid option has invalid key\n");
break;
case AO_EOPENDEVICE:
Com_Printf("W: Cannot open device\n");
break;
case AO_EFAIL:
Com_Printf("W: Something broke during ao_open_live\n");
break;
case AO_ENOTFILE:
Com_Printf("W: Not a file\n");
break;
case AO_EOPENFILE:
Com_Printf("W: Can't open file\n");
break;
case AO_EFILEEXISTS:
Com_Printf("W: File exists already\n");
break;
default:
Com_Printf("W: whoa, bad trip dude\n");
break;
}
return 0;
}
samplesize = dma.samplebits >> 3;
dma.buffer = malloc(dma.samples * samplesize);
memset(dma.buffer, 0, dma.samples * samplesize);
snd_inited = 1;
dma.samplepos = 0;
dma.submission_chunk = 1;
return 1;
}
/* SNDDMA_GetDMAPos: get the current DMA position
*/
int SNDDMA_GetDMAPos(void) {
if (snd_inited)
return dma.samplepos;
else
Com_Printf("Sound not initialised\n");
return 0;
}
/* SNDDMA_Shutdown: shutdown the DMA xfer
*/
void SNDDMA_Shutdown(void) {
if (snd_inited) {
ao_close(device);
ao_shutdown();
free(dma.buffer);
dma.buffer = 0;
snd_inited = 0;
}
}
/* SNDDMA_Submit: send sound to device if buffer isn't really the dma buffer
*/
void SNDDMA_Submit(void) {
if (!snd_inited)
return;
/* ao_play returns success, not number of samples successfully output
* unlike alsa or arts, so we can only assume that the whole buffer
* made it out... though this makes updating dma.samplepos easy */
if (ao_play(device, dma.buffer, dma.samples * samplesize) == 0) {
Com_Printf("W: error occurred while playing buffer\n");
ao_close(device);
ao_shutdown();
snd_inited = 0;
}
dma.samplepos += dma.samples;
}
void SNDDMA_BeginPainting(void) {
}