- Added pluggable sound architecture for runtime loading of

sound driver modules.
This commit is contained in:
Jamie Wilkinson 2004-03-15 02:25:43 +00:00
parent 97d7b9731e
commit f4a2cc9ca2
10 changed files with 533 additions and 421 deletions

6
NEWS
View file

@ -1,6 +1,12 @@
NEWS for quake2 NEWS for quake2
=============== ===============
0.x (//04)
---
* Pluggable sound driver architecture, sound output drivers configurable
at runtime.
0.2.2 (25/02/04) 0.2.2 (25/02/04)
----- -----

View file

@ -4,7 +4,7 @@ dnl stick the revision info into the resulting configure script
AC_REVISION($Revision$) dnl AC_REVISION($Revision$) dnl
AC_PREREQ(2.50) AC_PREREQ(2.50)
AC_INIT(quake2, 0.2.2, quake2-devel@lists.quakeforge.net) AC_INIT(quake2, 0.2.3, quake2-devel@lists.quakeforge.net)
AC_CONFIG_AUX_DIR(.) AC_CONFIG_AUX_DIR(.)
AC_CONFIG_SRCDIR(src/main.c) AC_CONFIG_SRCDIR(src/main.c)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
@ -323,8 +323,38 @@ dnl ------------------
OSS_CFLAGS="" OSS_CFLAGS=""
OSS_LIBS="" OSS_LIBS=""
AC_CHECK_LIB([ossaudio], [_oss_ioctl], [OSS_LIBS="-lossaudio"]) AC_CHECK_LIB([ossaudio], [_oss_ioctl], [OSS_LIBS="-lossaudio"])
AC_CHECK_HEADERS([soundcard.h sys/soundcard.h])
AC_SUBST(OSS_CFLAGS) AC_SUBST(OSS_CFLAGS)
AC_SUBST(OSS_LIBS) AC_SUBST(OSS_LIBS)
if test "x$ac_cv_header_sys_soundcard_h" = "xyes"; then
AC_MSG_CHECKING(for AFMT_S16_NE in sys/soundcard.h)
AC_EGREP_CPP([QF_maGiC_VALUE],
[ #include <sys/soundcard.h>
#ifdef AFMT_S16_NE
QF_maGiC_VALUE
#endif ],
HAVE_AFMT_S16_NE=yes
AC_MSG_RESULT(yes)
,
AC_MSG_RESULT(no)
)
else if test "x$ac_cv_header_soundcard_h" = "xyes"; then
AC_MSG_CHECKING(for AFMT_S16_NE in soundcard.h)
AC_EGREP_CPP([QF_maGiC_VALUE],
[ #include <soundcard.h>
#ifdef AFMT_S16_NE
QF_maGiC_VALUE
#endif ],
HAVE_AFMT_S16_NE=yes
AC_MSG_RESULT(yes)
,
AC_MSG_RESULT(no)
)
fi
fi
AC_SUBST(HAVE_AFMT_S16_NE)
AM_CONDITIONAL(BUILD_OSS, test x = x)
SNDDRIVERS="$SNDDRIVERS snd_oss.la"
dnl --------------- dnl ---------------
dnl Check for libao dnl Check for libao
@ -370,6 +400,7 @@ if test "x${ac_with_ao}" != xno ; then
AC_DEFINE(HAVE_AO, 1, [Define this if you have libao]) AC_DEFINE(HAVE_AO, 1, [Define this if you have libao])
AC_SUBST(AO_LIBS) AC_SUBST(AO_LIBS)
AC_SUBST(AO_CFLAGS) AC_SUBST(AO_CFLAGS)
SNDDRIVERS="$SNDDRIVERS snd_ao.la"
else else
dnl if we were explicitly told to use ao and it's not there dnl if we were explicitly told to use ao and it's not there
if test "x${ac_with_ao}" = xyes ; then if test "x${ac_with_ao}" = xyes ; then
@ -384,7 +415,7 @@ if test "x${ac_with_ao}" != xno ; then
else else
HAVE_AO=disabled HAVE_AO=disabled
fi fi
AM_CONDITIONAL(USE_AO, test "x$HAVE_AO" = xyes) AM_CONDITIONAL(BUILD_AO, test "x$HAVE_AO" = xyes)
dnl -------------- dnl --------------
dnl Check for ALSA dnl Check for ALSA
@ -420,7 +451,7 @@ if test "x${ac_with_alsa}" != xno ; then
[$ALSA_LIBS]) [$ALSA_LIBS])
dnl check the header dnl check the header
if test "x$HAVE_ALSA" = xmaybe ; then if test "x$HAVE_ALSA" = xmaybe ; then
AC_CHECK_HEADER(sys/asoundlib.h, AC_CHECK_HEADER(alsa/asoundlib.h,
HAVE_ALSA=yes, HAVE_ALSA=yes,
HAVE_ALSA=no HAVE_ALSA=no
) )
@ -430,6 +461,7 @@ if test "x${ac_with_alsa}" != xno ; then
AC_DEFINE(HAVE_ALSA, 1, [Define this if you have ALSA]) AC_DEFINE(HAVE_ALSA, 1, [Define this if you have ALSA])
AC_SUBST(ALSA_CFLAGS) AC_SUBST(ALSA_CFLAGS)
AC_SUBST(ALSA_LIBS) AC_SUBST(ALSA_LIBS)
SNDDRIVERS="$SNDDRIVERS snd_alsa.la"
else else
dnl if we were explicitly told to use alsa and it's not there dnl if we were explicitly told to use alsa and it's not there
if test "x${ac_with_alsa}" = xyes ; then if test "x${ac_with_alsa}" = xyes ; then
@ -444,18 +476,7 @@ if test "x${ac_with_alsa}" != xno ; then
else else
HAVE_ALSA=disabled HAVE_ALSA=disabled
fi fi
AM_CONDITIONAL(USE_ALSA, test "x$HAVE_ALSA" = xyes) AM_CONDITIONAL(BUILD_ALSA, test "x$HAVE_ALSA" = xyes)
dnl -----------------------
dnl Checks for header files
dnl -----------------------
#AC_PATH_X
#AC_HEADER_DIRENT
#AC_HEADER_STDC
dnl AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([ sys/soundcard.h ])
dnl ------------------------------------------------------------- dnl -------------------------------------------------------------
dnl Checks for typedefs, structures, and compiler characteristics dnl Checks for typedefs, structures, and compiler characteristics
@ -478,34 +499,6 @@ AC_TRY_LINK(
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
) )
if test "x$ac_cv_header_sys_soundcard_h" = "xyes"; then
AC_MSG_CHECKING(for AFMT_S16_NE in sys/soundcard.h)
AC_EGREP_CPP([QF_maGiC_VALUE],
[ #include <sys/soundcard.h>
#ifdef AFMT_S16_NE
QF_maGiC_VALUE
#endif ],
HAVE_AFMT_S16_NE=yes
AC_MSG_RESULT(yes)
,
AC_MSG_RESULT(no)
)
else if test "x$ac_cv_header_soundcard_h" = "xyes"; then
AC_MSG_CHECKING(for AFMT_S16_NE in soundcard.h)
AC_EGREP_CPP([QF_maGiC_VALUE],
[ #include <soundcard.h>
#ifdef AFMT_S16_NE
QF_maGiC_VALUE
#endif ],
HAVE_AFMT_S16_NE=yes
AC_MSG_RESULT(yes)
,
AC_MSG_RESULT(no)
)
fi
fi
AC_SUBST(HAVE_AFMT_S16_NE)
dnl ----------------------------- dnl -----------------------------
dnl Checks for library functions. dnl Checks for library functions.
dnl ----------------------------- dnl -----------------------------
@ -567,7 +560,7 @@ AC_ARG_ENABLE(opt,
AC_MSG_RESULT(no), AC_MSG_RESULT(no),
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
USE_OPT="yes" USE_OPT="yes"
OPT_CFLAGS="$OPT_CFLAGS -O2 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" OPT_CFLAGS="$OPT_CFLAGS -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations"
) )
if test "x$USE_OPT" = "xyes"; then if test "x$USE_OPT" = "xyes"; then
case "${host}" in case "${host}" in
@ -588,6 +581,11 @@ if test "x$USE_OPT" = "xyes"; then
*) *)
;; ;;
esac esac
else
# kill off that fucking retarded -O2 that gets bunged in by default
temp_CFLAGS=`echo $CFLAGS | sed 's/O2/O0/g'`
CFLAGS="$temp_CFLAGS"
AC_MSG_WARN([[** Compiler optimisations switched off **]])
fi fi
AC_SUBST(OPT_CFLAGS) AC_SUBST(OPT_CFLAGS)
@ -596,14 +594,15 @@ dnl Compiler warnings
dnl ----------------- dnl -----------------
WARN_CFLAGS="" WARN_CFLAGS=""
dnl USE_WARN=""
AC_MSG_CHECKING(whether to abort on compiler warnings) AC_MSG_CHECKING(whether to abort on compiler warnings)
AC_ARG_ENABLE(warn, AC_ARG_ENABLE(warn,
[ --disable-warn don't abort on compiler warnings ], [ --disable-warn don't abort on compiler warnings ],
AC_MSG_RESULT(no), AC_MSG_RESULT(no),
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
dnl USE_WARN="yes" #WARN_CFLAGS="$WARN_CFLAGS -W -Wall -Werror"
WARN_CFLAGS="$WARN_CFLAGS -Wall -Werror" WARN_CFLAGS="$WARN_CFLAGS -Wall -Werror"
# -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast -Wwrite-strings
# -Wpointer-arith -Wundef -Wmissing-declarations -Winline -Wconversion
) )
AC_SUBST(WARN_CFLAGS) AC_SUBST(WARN_CFLAGS)
@ -764,6 +763,7 @@ AM_CONDITIONAL(BUILD_TDFX, test "x$BUILD_TDFX" = xyes)
AM_CONDITIONAL(BUILD_SDLGL, test "x$BUILD_SDLGL" = xyes) AM_CONDITIONAL(BUILD_SDLGL, test "x$BUILD_SDLGL" = xyes)
AC_SUBST(VID_REFS) AC_SUBST(VID_REFS)
AC_SUBST(SNDDRIVERS)
dnl ----------------------------------------------------------- dnl -----------------------------------------------------------
dnl Configuraton tests complete -- provide a summary of results dnl Configuraton tests complete -- provide a summary of results
@ -795,6 +795,7 @@ AC_CONFIG_FILES([
AC_OUTPUT AC_OUTPUT
VID_REFS=`echo $VID_REFS | sed -e 's/ref_//g' -e 's/\.la//g'` VID_REFS=`echo $VID_REFS | sed -e 's/ref_//g' -e 's/\.la//g'`
SNDDRIVERS=`echo $SNDDRIVERS | sed -e 's/snd_//g' -e 's/\.la//g'`
AC_MSG_RESULT([ AC_MSG_RESULT([
Quake2Forge $VERSION: Automatic configuration OK. Quake2Forge $VERSION: Automatic configuration OK.
@ -834,7 +835,8 @@ AC_MSG_RESULT([ SDL: ............. $HAVE_SDL])
dnl AC_MSG_RESULT([ Framebuffer: ..... $HAVE_FB]) dnl AC_MSG_RESULT([ Framebuffer: ..... $HAVE_FB])
dnl AC_MSG_RESULT([ AAlib: ........... $HAVE_AA]) dnl AC_MSG_RESULT([ AAlib: ........... $HAVE_AA])
AC_MSG_RESULT([ Audio drivers:]) AC_MSG_RESULT([ Sound drivers: ..... ${SNDDRIVERS- none}])
AC_MSG_RESULT([ OSS .............. yes])
AC_MSG_RESULT([ ALSA ............. $HAVE_ALSA]) AC_MSG_RESULT([ ALSA ............. $HAVE_ALSA])
if test "x${ac_with_alsa}" = xyes ; then if test "x${ac_with_alsa}" = xyes ; then
if test "x${HAVE_ALSA}" != xyes ; then if test "x${HAVE_ALSA}" != xyes ; then

38
docs/README.sound Normal file
View file

@ -0,0 +1,38 @@
Quake2Forge sound
=================
Quake2Forge supports several sound output APIs.
To set your sound output driver, set the snddriver cvar, like so:
quake2 +set snddriver oss
The currently supported list of drivers are:
oss -- OSS from Linux 2.4 and earlier, and some BSDs
alsa -- ALSA 0.9 from Linux 2.6 onwards
ao -- libao audio output library
Each driver uses the snddevice cvar in different ways:
oss uses the device node for the sound card, e.g. /dev/dsp
alsa uses the pcm name, e.g. default or plughw:0,0
ao uses the name of the backend, e.g. oss or alsa09
e.g.:
quake2 +set snddriver oss +set snddevice /dev/dsp
quake2 +set snddriver alsa +set snddevice default
quake2 +set snddriver ao +set snddevice oss
Unexpected behaviour can usually be attributed to a snddevice setting from
a previous snddriver.
The sound driver can be changed at run time from within the console by
setting the two cvars above and calling 'snd_restart':
]set snddriver ao
]set snddevice oss
]snd_restart

View file

@ -4,9 +4,10 @@ std_cflags = -pipe @WARN_CFLAGS@ @OPT_CFLAGS@
module_ldflags = -module -avoid-version -rpath $(pkglibdir) module_ldflags = -module -avoid-version -rpath $(pkglibdir)
bin_PROGRAMS = quake2 bin_PROGRAMS = quake2
pkglib_LTLIBRARIES = @VID_REFS@ pkglib_LTLIBRARIES = @VID_REFS@ @SNDDRIVERS@
EXTRA_LTLIBRARIES = ref_soft.la ref_softx.la ref_softsdl.la \ EXTRA_LTLIBRARIES = ref_soft.la ref_softx.la ref_softsdl.la \
ref_glx.la ref_sdlgl.la ref_tdfx.la ref_glx.la ref_sdlgl.la ref_tdfx.la \
snd_oss.la snd_alsa.la snd_ao.la
# Common source files # Common source files
REF_GL_COMMON = q_sh.c q_shared.c q_glob.c qgl.c \ REF_GL_COMMON = q_sh.c q_shared.c q_glob.c qgl.c \
@ -42,19 +43,7 @@ else
QUAKE2_ASM= QUAKE2_ASM=
endif endif
if USE_ALSA SOUND = cd.c snd_dma.c snd_mix.c snd_mem.c
SOUND = cd.c snd_alsa.c snd_dma.c snd_mix.c snd_mem.c
else
if USE_AO
SOUND = cd.c snd_ao.c snd_dma.c snd_mix.c snd_mem.c
else
if BUILD_SDLQUAKE2
SOUND = cd_sdl.c snd_sdl.c snd_dma.c snd_mix.c snd_mem.c
else
SOUND = cd.c snd_oss.c snd_dma.c snd_mix.c snd_mem.c
endif
endif
endif
quake2_SOURCES = main.c q_sh.c vid_menu.c vid_so.c q_glob.c net_udp.c \ quake2_SOURCES = main.c q_sh.c vid_menu.c vid_so.c q_glob.c net_udp.c \
\ \
@ -92,32 +81,31 @@ EXTRA_quake2_SOURCES = snd_mixa.S cd_sdl.c snd_sdl.c snd_dma.c \
snd_mix.c snd_mem.c cd.c \ snd_mix.c snd_mem.c cd.c \
snd_oss.c snd_ao.c snd_alsa.c snd_oss.c snd_ao.c snd_alsa.c
if USE_ALSA quake2_CFLAGS = $(std_cflags)
quake2_CFLAGS = $(std_cflags) @ALSA_CFLAGS@ quake2_LDADD = @DL_LIBS@ @SYSTEM_LIBS@ -lm
else
if USE_AO # oss sound driver
quake2_CFLAGS = $(std_cflags) @AO_CFLAGS@ if BUILD_OSS
else snd_oss_la_SOURCES = snd_oss.c
if BUILD_SDLQUAKE2 snd_oss_la_CFLAGS = $(std_cflags) -fPIC @OSS_CFLAGS@
quake2_CFLAGS = $(std_cflags) @SDL_CFLAGS@ snd_oss_la_LIBADD = @OSS_LIBS@
else snd_oss_la_LDFLAGS = $(module_ldflags)
quake2_CFLAGS = $(std_cflags) @OSS_CFLAGS@
endif
endif
endif endif
if USE_ALSA # alsa sound driver
quake2_LDADD = @DL_LIBS@ @ALSA_LIBS@ @SYSTEM_LIBS@ -lm if BUILD_ALSA
else snd_alsa_la_SOURCES = snd_alsa.c
if USE_AO snd_alsa_la_CFLAGS = $(std_cflags) -fPIC @ALSA_CFLAGS@
quake2_LDADD = @DL_LIBS@ @AO_LIBS@ @SYSTEM_LIBS@ -lm snd_alsa_la_LIBADD = @ALSA_LIBS@
else snd_alsa_la_LDFLAGS = $(module_ldflags)
if BUILD_SDLQUAKE2
quake2_LDADD = @DL_LIBS@ @SDL_LIBS@ @SYSTEM_LIBS@ -lm
else
quake2_LDADD = @DL_LIBS@ @OSS_LIBS@ @SYSTEM_LIBS@ -lm
endif
endif endif
# libao sound driver
if BUILD_AO
snd_ao_la_SOURCES = snd_ao.c
snd_ao_la_CFLAGS = $(std_cflags) -fPIC @AO_CFLAGS@
snd_ao_la_LIBADD = @AO_LIBS@
snd_ao_la_LDFLAGS = $(module_ldflags)
endif endif
# ref_glx # ref_glx

View file

@ -40,7 +40,6 @@
#include <termios.h> #include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
/* #include <sys/vt.h> */
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
@ -66,10 +65,10 @@
#ifdef HAVE_XF86_DGA #ifdef HAVE_XF86_DGA
#include <X11/extensions/xf86dga.h> #include <X11/extensions/xf86dga.h>
#endif // HAVE_XF86_DGA #endif /* HAVE_XF86_DGA */
#ifdef HAVE_XF86_VIDMODE #ifdef HAVE_XF86_VIDMODE
#include <X11/extensions/xf86vmode.h> #include <X11/extensions/xf86vmode.h>
#endif // HAVE_XF86_VIDMODE #endif /* HAVE_XF86_VIDMODE */
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
#include <sys/types.h> #include <sys/types.h>
@ -1051,7 +1050,7 @@ int GLimp_SetMode( unsigned int *pwidth, unsigned int *pheight, int mode, qboole
scrnum = DefaultScreen(dpy); scrnum = DefaultScreen(dpy);
root = RootWindow(dpy, scrnum); root = RootWindow(dpy, scrnum);
// Get video mode list /* Get video mode list */
MajorVersion = MinorVersion = 0; MajorVersion = MinorVersion = 0;
#ifdef HAVE_XF86_VIDMODE #ifdef HAVE_XF86_VIDMODE
if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
@ -1061,7 +1060,7 @@ int GLimp_SetMode( unsigned int *pwidth, unsigned int *pheight, int mode, qboole
MajorVersion, MinorVersion); MajorVersion, MinorVersion);
vidmode_ext = true; vidmode_ext = true;
} }
#endif // HAVE_XF86_VIDMODE #endif /* HAVE_XF86_VIDMODE */
visinfo = qglXChooseVisual(dpy, scrnum, attrib); visinfo = qglXChooseVisual(dpy, scrnum, attrib);
if (!visinfo) { if (!visinfo) {

View file

@ -1,199 +1,190 @@
/* /*
snd_alsa.c * 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
*/
This program is free software; you can redistribute it and/or #ifdef HAVE_CONFIG_H
modify it under the terms of the GNU General Public License #include "config.h"
as published by the Free Software Foundation; either version 2 #endif
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_ALSA
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#endif
#include "client.h" #include "client.h"
#include "snd_loc.h" #include "snd_loc.h"
#define snd_buf (dma.samples * 2)
static int snd_inited; static int snd_inited;
static char *buffer;
static snd_pcm_t *playback_handle; static snd_pcm_t * pcm_handle;
static snd_pcm_hw_params_t *hw_params; static snd_pcm_hw_params_t * hw_params;
cvar_t *sndbits; #define BUFFER_SIZE 4096
cvar_t *sndspeed;
cvar_t *sndchannels;
cvar_t *snddevice;
static int tryrates[] = { 44100, 22051, 11025, 8000 }; int tryrates[] = { 44100, 22051, 11025, 8000 };
qboolean SNDDMA_Init (void) /* sound info */
{ static struct sndinfo * si;
qboolean SNDDMA_Init(struct sndinfo * s) {
int i; int i;
int err; int err;
if (!snddevice) { if (snd_inited)
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE); return 1;
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
snddevice = Cvar_Get("snddevice", "default", CVAR_ARCHIVE);
}
err = snd_pcm_open(&playback_handle, snddevice->string, snd_inited = 0;
SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) { si = s;
Com_Printf("ALSA snd error, cannot open device %s (%s)\n",
snddevice->string, si->dma->samples = 1024;
if ((err = snd_pcm_open(&pcm_handle, si->device->string,
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
si->Com_Printf("ALSA snd error, cannot open device %s (%s)\n",
si->device->string,
snd_strerror(err)); snd_strerror(err));
return 0; return 0;
} }
err = snd_pcm_hw_params_malloc(&hw_params); if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error, cannot allocate hw params (%s)\n",
Com_Printf("ALSA snd error, cannot allocate hw params (%s)\n",
snd_strerror(err)); snd_strerror(err));
return 0; return 0;
} }
err = snd_pcm_hw_params_any (playback_handle, hw_params); if ((err = snd_pcm_hw_params_any(pcm_handle, hw_params)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error, cannot init hw params (%s)\n",
Com_Printf("ALSA snd error, cannot init hw params (%s)\n",
snd_strerror(err)); snd_strerror(err));
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
err = snd_pcm_hw_params_set_access(playback_handle, hw_params, if ((err = snd_pcm_hw_params_set_access(pcm_handle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED); SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error, cannot set access (%s)\n",
Com_Printf("ALSA snd error, cannot set access (%s)\n",
snd_strerror(err)); snd_strerror(err));
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
dma.samplebits = sndbits->value; si->dma->samplebits = si->bits->value;
if (dma.samplebits == 16 || dma.samplebits != 8) { if (si->dma->samplebits == 16 || si->dma->samplebits != 8) {
err = snd_pcm_hw_params_set_format(playback_handle, hw_params, if ((err = snd_pcm_hw_params_set_format(pcm_handle, hw_params,
SND_PCM_FORMAT_S16_LE); SND_PCM_FORMAT_S16_LE)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error, 16 bit sound not supported, trying 8\n");
Com_Printf("ALSA snd error, 16 bit sound not supported, trying 8\n"); si->dma->samplebits = 8;
dma.samplebits = 8;
} }
} }
if (dma.samplebits == 8) { if (si->dma->samplebits == 8) {
err = snd_pcm_hw_params_set_format(playback_handle, hw_params, if ((err = snd_pcm_hw_params_set_format(pcm_handle, hw_params,
SND_PCM_FORMAT_U8); SND_PCM_FORMAT_U8)) < 0) {
} si->Com_Printf("ALSA snd error, cannot set sample format (%s)\n",
if (err < 0) {
Com_Printf("ALSA snd error, cannot set sample format (%s)\n",
snd_strerror(err)); snd_strerror(err));
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
}
dma.speed = (int)sndspeed->value; si->dma->speed = (int)si->speed->value;
if (!dma.speed) { if (!si->dma->speed) {
for (i=0 ; i<sizeof(tryrates)/4 ; i++) { for (i = 0; i < sizeof(tryrates); i++) {
int dir = 0;
int test = tryrates[i]; int test = tryrates[i];
err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params,
&test, 0); if ((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hw_params,
if (err < 0) { &test, &dir)) < 0) {
Com_Printf("ALSA snd error, cannot set sample rate %d (%s)\n", si->Com_Printf("ALSA snd error, cannot set sample rate %d (%s)\n",
tryrates[i], snd_strerror(err)); tryrates[i], snd_strerror(err));
} else {
si->dma->speed = test;
if (dir != 0) {
si->Com_Printf("alsa: The rate %d Hz is not supported by your hardware, using %d Hz instead.\n", test, err);
} }
else {
dma.speed = test;
break; break;
} }
} }
} }
if (!dma.speed) { if (!si->dma->speed) {
Com_Printf("ALSA snd error couldn't set rate.\n"); si->Com_Printf("ALSA snd error couldn't set rate.\n");
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
dma.channels = (int)sndchannels->value; si->dma->channels = (int)si->channels->value;
if (dma.channels < 1 || dma.channels > 2) if (si->dma->channels < 1 || si->dma->channels > 2)
dma.channels = 2; si->dma->channels = 2;
err = snd_pcm_hw_params_set_channels(playback_handle,hw_params,dma.channels); if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hw_params, si->dma->channels)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error couldn't set channels %d (%s).\n",
Com_Printf("ALSA snd error couldn't set channels %d (%s).\n", si->dma->channels, snd_strerror(err));
dma.channels, snd_strerror(err));
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
err = snd_pcm_hw_params(playback_handle, hw_params); if ((err = snd_pcm_hw_params(pcm_handle, hw_params)) < 0) {
if (err < 0) { si->Com_Printf("ALSA snd error couldn't set params (%s).\n",snd_strerror(err));
Com_Printf("ALSA snd error couldn't set params (%s).\n",snd_strerror(err));
snd_pcm_hw_params_free(hw_params); snd_pcm_hw_params_free(hw_params);
return 0; return 0;
} }
buffer=malloc(snd_buf); si->dma->buffer = malloc(BUFFER_SIZE);
memset(buffer, 0, snd_buf); memset(si->dma->buffer, 0, BUFFER_SIZE);
dma.samplepos = 0; si->dma->samplepos = 0;
dma.submission_chunk = 1; si->dma->samples = BUFFER_SIZE / (si->dma->samplebits / 8);
dma.buffer = buffer; si->dma->submission_chunk = 1;
si->Com_Printf("alsa: buffer size is %d, %d samples\n", BUFFER_SIZE, si->dma->samples);
snd_inited = 1; snd_inited = 1;
return 1; return 1;
} }
int int SNDDMA_GetDMAPos(void) {
SNDDMA_GetDMAPos (void) if (snd_inited)
{ return si->dma->samplepos;
if(snd_inited)
return dma.samplepos;
else else
Com_Printf ("Sound not inizialized\n"); si->Com_Printf("Sound not inizialized\n");
return 0; return 0;
} }
void void SNDDMA_Shutdown(void) {
SNDDMA_Shutdown (void)
{
if (snd_inited) { if (snd_inited) {
snd_pcm_close(playback_handle); snd_pcm_drop(pcm_handle);
snd_pcm_close(pcm_handle);
snd_inited = 0; snd_inited = 0;
} }
free(dma.buffer); free(si->dma->buffer);
si->dma->buffer = NULL;
} }
/* /* SNDDMA_Submit
SNDDMA_Submit * Send sound to device if buffer isn't really the dma buffer
Send sound to device if buffer isn't really the dma buffer */
*/ void SNDDMA_Submit(void) {
void
SNDDMA_Submit (void)
{
int written; int written;
if(!snd_inited) if(!snd_inited)
return; return;
written = snd_pcm_writei(playback_handle, dma.buffer, snd_buf); if ((written = snd_pcm_writei(pcm_handle, si->dma->buffer, si->dma->samples * (si->dma->samplebits / 8))) < 0) {
dma.samplepos+=(written / (dma.samplebits / 8)); snd_pcm_prepare(pcm_handle);
si->Com_Printf("alsa: buffer underrun\n");
}
si->dma->samplepos += written / (si->dma->samplebits / 8);
} }
void SNDDMA_BeginPainting(void) void SNDDMA_BeginPainting(void) {
{
} }

View file

@ -33,103 +33,95 @@
static int snd_inited; static int snd_inited;
static int samplesize; static int samplesize;
cvar_t * sndbits; struct sndinfo * si;
cvar_t * sndspeed;
cvar_t * sndchannels;
cvar_t * snddevice;
ao_device * device; ao_device * device;
/* SNDDMA_Init: initialises cycling through a DMA bufffer and returns /* SNDDMA_Init: initialises cycling through a DMA bufffer and returns
* information on it * information on it
*/ */
qboolean SNDDMA_Init(void) { qboolean SNDDMA_Init(struct sndinfo * s) {
int driver_id; int driver_id;
ao_sample_format format; ao_sample_format format;
ao_option * options = NULL; ao_option * options = NULL;
if (!snddevice) { if (snd_inited)
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE); return 1;
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); snd_inited = 0;
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
} si = s;
ao_initialize(); ao_initialize();
#if 1 if ((driver_id = ao_driver_id(si->device->string)) == -1) {
si->Com_Printf("ao: no driver %s found, trying default\n", si->device->string);
if ((driver_id = ao_default_driver_id()) == -1) { if ((driver_id = ao_default_driver_id()) == -1) {
#else Com_Printf("ao: no default driver found\n");
if ((driver_id = ao_driver_id("wav")) == -1) {
#endif
Com_Printf("Couldn't find a default driver for sound output\n");
return 0; return 0;
} }
}
/*ao_append_option(&options, "debug", "");*/ format.bits = si->dma->samplebits = si->bits->value;
format.rate = si->dma->speed = 44100;
format.bits = dma.samplebits = sndbits->value; format.channels = si->dma->channels = si->channels->value;
format.rate = dma.speed = 44100;
format.channels = dma.channels = sndchannels->value;
format.byte_format = AO_FMT_NATIVE; format.byte_format = AO_FMT_NATIVE;
switch (dma.speed) { switch (si->dma->speed) {
case 44100: case 44100:
dma.samples = 2048 * dma.channels; si->dma->samples = 2048 * si->dma->channels;
break; break;
case 22050: case 22050:
dma.samples = 1024 * dma.channels; si->dma->samples = 1024 * si->dma->channels;
break; break;
default: default:
dma.samples = 512 * dma.channels; si->dma->samples = 512 * si->dma->channels;
break; break;
} }
#if 1
if ((device = ao_open_live(driver_id, &format, options)) == NULL) { 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) { switch (errno) {
case AO_ENODRIVER: case AO_ENODRIVER:
Com_Printf("W: No ao driver for %d\n", driver_id); Com_Printf("ao: no driver for %d\n", driver_id);
break; break;
case AO_ENOTLIVE: case AO_ENOTLIVE:
Com_Printf("W: Not a valid live output device\n"); Com_Printf("ao: not a valid live output device\n");
break; break;
case AO_EBADOPTION: case AO_EBADOPTION:
Com_Printf("W: Valid option has invalid key\n"); Com_Printf("ao: valid option has invalid key\n");
break; break;
case AO_EOPENDEVICE: case AO_EOPENDEVICE:
Com_Printf("W: Cannot open device\n"); Com_Printf("ao: cannot open device\n");
break; break;
case AO_EFAIL: case AO_EFAIL:
Com_Printf("W: Something broke during ao_open_live\n"); Com_Printf("ao: something broke during ao_open_live\n");
break; break;
case AO_ENOTFILE: case AO_ENOTFILE:
Com_Printf("W: Not a file\n"); Com_Printf("ao: not a file\n");
break; break;
case AO_EOPENFILE: case AO_EOPENFILE:
Com_Printf("W: Can't open file\n"); Com_Printf("ao: can't open file\n");
break; break;
case AO_EFILEEXISTS: case AO_EFILEEXISTS:
Com_Printf("W: File exists already\n"); Com_Printf("ao: file exists already\n");
break; break;
default: default:
Com_Printf("W: whoa, bad trip dude\n"); Com_Printf("ao: whoa, bad trip dude\n");
break; break;
} }
return 0; return 0;
} }
samplesize = dma.samplebits >> 3; samplesize = si->dma->samplebits >> 3;
dma.buffer = malloc(dma.samples * samplesize); si->dma->buffer = malloc(si->dma->samples * samplesize);
memset(dma.buffer, 0, dma.samples * samplesize); memset(si->dma->buffer, 0, si->dma->samples * samplesize);
si->dma->samplepos = 0;
si->dma->submission_chunk = 1;
si->Com_Printf("ao: buffer size is %d, %d samples\n", si->dma->samples * samplesize, si->dma->samples);
snd_inited = 1; snd_inited = 1;
dma.samplepos = 0;
dma.submission_chunk = 1;
return 1; return 1;
} }
@ -137,7 +129,7 @@ qboolean SNDDMA_Init(void) {
*/ */
int SNDDMA_GetDMAPos(void) { int SNDDMA_GetDMAPos(void) {
if (snd_inited) if (snd_inited)
return dma.samplepos; return si->dma->samplepos;
else else
Com_Printf("Sound not initialised\n"); Com_Printf("Sound not initialised\n");
@ -150,8 +142,8 @@ void SNDDMA_Shutdown(void) {
if (snd_inited) { if (snd_inited) {
ao_close(device); ao_close(device);
ao_shutdown(); ao_shutdown();
free(dma.buffer); free(si->dma->buffer);
dma.buffer = 0; si->dma->buffer = 0;
snd_inited = 0; snd_inited = 0;
} }
} }
@ -164,14 +156,14 @@ void SNDDMA_Submit(void) {
/* ao_play returns success, not number of samples successfully output /* ao_play returns success, not number of samples successfully output
* unlike alsa or arts, so we can only assume that the whole buffer * unlike alsa or arts, so we can only assume that the whole buffer
* made it out... though this makes updating dma.samplepos easy */ * made it out... though this makes updating si->dma->samplepos easy */
if (ao_play(device, dma.buffer, dma.samples * samplesize) == 0) { if (ao_play(device, si->dma->buffer, si->dma->samples * samplesize) == 0) {
Com_Printf("W: error occurred while playing buffer\n"); Com_Printf("W: error occurred while playing buffer\n");
ao_close(device); ao_close(device);
ao_shutdown(); ao_shutdown();
snd_inited = 0; snd_inited = 0;
} }
dma.samplepos += dma.samples; si->dma->samplepos += si->dma->samples;
} }
void SNDDMA_BeginPainting(void) { void SNDDMA_BeginPainting(void) {

View file

@ -21,6 +21,19 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_DLOPEN
# include <dlfcn.h>
#endif
#include "client.h" #include "client.h"
#include "snd_loc.h" #include "snd_loc.h"
@ -80,11 +93,23 @@ cvar_t *s_khz;
cvar_t *s_show; cvar_t *s_show;
cvar_t *s_mixahead; cvar_t *s_mixahead;
cvar_t *s_primary; cvar_t *s_primary;
cvar_t * snddriver;
int s_rawend; int s_rawend;
portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
static void * snddriver_library = NULL;
qboolean snddriver_active = 0;
/* dlsymbols */
qboolean (*SNDDMA_Init)(struct sndinfo *);
int (*SNDDMA_GetDMAPos)(void);
void (*SNDDMA_Shutdown)(void);
void (*SNDDMA_BeginPainting)(void);
void (*SNDDMA_Submit)(void);
struct sndinfo si;
// ==================================================================== // ====================================================================
// User-setable variables // User-setable variables
@ -99,7 +124,7 @@ void S_SoundInfo_f(void)
return; return;
} }
Com_Printf("%5d stereo\n", dma.channels - 1); Com_Printf("%5d channels\n", dma.channels);
Com_Printf("%5d samples\n", dma.samples); Com_Printf("%5d samples\n", dma.samples);
Com_Printf("%5d samplepos\n", dma.samplepos); Com_Printf("%5d samplepos\n", dma.samplepos);
Com_Printf("%5d samplebits\n", dma.samplebits); Com_Printf("%5d samplebits\n", dma.samplebits);
@ -134,7 +159,51 @@ void S_Init (void)
s_testsound = Cvar_Get ("s_testsound", "0", 0); s_testsound = Cvar_Get ("s_testsound", "0", 0);
s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE); // win32 specific s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE); // win32 specific
if (!SNDDMA_Init()) {
char fn[MAX_OSPATH];
struct stat st;
/* load sound driver */
snddriver = Cvar_Get("snddriver", "oss", CVAR_ARCHIVE);
Com_Printf("loading %s sound output driver", snddriver->string);
snprintf(fn, MAX_OSPATH, PKGLIBDIR"/snd_%s.so", snddriver->string);
if (stat(fn, &st) == -1) {
Com_Printf("\nload %s failed: %s\n", fn, strerror(errno));
return;
}
if ((snddriver_library = dlopen(fn, RTLD_LAZY)) == 0) {
Com_Printf("\nload %s failed: %s\n", fn, dlerror());
return;
}
Com_Printf(", ok\n");
if ((SNDDMA_Init = dlsym(snddriver_library, "SNDDMA_Init")) == 0)
Com_Error(ERR_FATAL, "dlsym failed loading SNDDMA_Init\n");
if ((SNDDMA_Shutdown = dlsym(snddriver_library, "SNDDMA_Shutdown")) == 0)
Com_Error(ERR_FATAL, "dlsym failed loading SNDDMA_Shutdown\n");
if ((SNDDMA_GetDMAPos = dlsym(snddriver_library, "SNDDMA_GetDMAPos")) == 0)
Com_Error(ERR_FATAL, "dlsym failed loading SNDDMA_GetDMAPos\n");
if ((SNDDMA_BeginPainting = dlsym(snddriver_library, "SNDDMA_BeginPainting")) == 0)
Com_Error(ERR_FATAL, "dlsym failed loading SNDDMA_BeginPainting\n");
if ((SNDDMA_Submit = dlsym(snddriver_library, "SNDDMA_Submit")) == 0)
Com_Error(ERR_FATAL, "dlsym failed loading SNDDMA_Submit\n");
snddriver_active = true;
}
si.dma = &dma;
si.bits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
si.speed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
si.channels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
si.device = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
si.Com_Printf = Com_Printf;
if (!SNDDMA_Init(&si))
return; return;
Cmd_AddCommand("play", S_Play); Cmd_AddCommand("play", S_Play);
@ -191,6 +260,19 @@ void S_Shutdown(void)
} }
num_sfx = 0; num_sfx = 0;
if (snddriver_library) {
SNDDMA_Init = NULL;
SNDDMA_Shutdown = NULL;
SNDDMA_Submit = NULL;
SNDDMA_GetDMAPos = NULL;
SNDDMA_BeginPainting = NULL;
dlclose(snddriver_library);
memset(&si, 0, sizeof(struct sndinfo));
snddriver_library = NULL;
snddriver_active = false;
memset(&dma, 0, sizeof(dma_t));
}
} }
@ -776,7 +858,8 @@ void S_ClearBuffer (void)
SNDDMA_BeginPainting (); SNDDMA_BeginPainting ();
if (dma.buffer) { if (dma.buffer) {
/* buffer may be read-only, clear manually */ /* buffer may be read-only, clear manually */
/* memset(dma.buffer, clear, dma.samples * dma.samplebits/8); */ memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
/*
int i; int i;
unsigned char * ptr = (unsigned char *) dma.buffer; unsigned char * ptr = (unsigned char *) dma.buffer;
@ -785,6 +868,7 @@ void S_ClearBuffer (void)
*ptr = clear; *ptr = clear;
ptr++; ptr++;
} }
*/
} }
SNDDMA_Submit (); SNDDMA_Submit ();
} }

View file

@ -122,18 +122,32 @@ typedef struct {
==================================================================== ====================================================================
*/ */
#if 0
// initializes cycling through a DMA buffer and returns information on it // initializes cycling through a DMA buffer and returns information on it
qboolean SNDDMA_Init(void); /* qboolean SNDDMA_Init(void); */
// gets the current DMA position // gets the current DMA position
int SNDDMA_GetDMAPos(void); int SNDDMA_GetDMAPos(void);
// shutdown the DMA xfer. // shutdown the DMA xfer.
void SNDDMA_Shutdown(void); /* void SNDDMA_Shutdown(void); */
void SNDDMA_BeginPainting (void); void SNDDMA_BeginPainting (void);
void SNDDMA_Submit(void); void SNDDMA_Submit(void);
#endif
/* struct for passing info to the sound driver dlls */
struct sndinfo {
dma_t * dma;
cvar_t * bits;
cvar_t * speed;
cvar_t * channels;
cvar_t * device;
void (*Com_Printf)(char * fmt, ...);
};
//==================================================================== //====================================================================

View file

@ -78,15 +78,13 @@ static int tryrates[] = { 11025, 22051, 44100, 48000, 8000 };
#endif #endif
cvar_t *sndbits;
cvar_t *sndspeed;
cvar_t *sndchannels;
cvar_t *snddevice;
/* irix cvars -- jaq */ /* irix cvars -- jaq */
cvar_t * s_loadas8bit; cvar_t * s_loadas8bit;
cvar_t * s_khz; cvar_t * s_khz;
qboolean SNDDMA_Init(void) { struct sndinfo * si;
qboolean SNDDMA_Init(struct sndinfo * s) {
/* merged in from snd_irix.c -- jaq */ /* merged in from snd_irix.c -- jaq */
#ifdef __sgi #ifdef __sgi
ALconfig ac = NULL; ALconfig ac = NULL;
@ -94,54 +92,54 @@ qboolean SNDDMA_Init(void) {
s_loadas8bit = Cvar_Get("s_loadas8bit", "16", CVAR_ARCHIVE); s_loadas8bit = Cvar_Get("s_loadas8bit", "16", CVAR_ARCHIVE);
if ((int) s_loadas8bit->value) if ((int) s_loadas8bit->value)
dma.samplebits = 8; si->dma->samplebits = 8;
else else
dma.samplebits = 16; si->dma->samplebits = 16;
if (dma.samplebits != 16) { if (si->dma->samplebits != 16) {
Com_Printf("Don't currently support %i-bit data. Forcing 16-bit\n", dma.samplebits); si->Com_Printf("Don't currently support %i-bit data. Forcing 16-bit\n", si->dma->samplebits);
dma.samplebits = 16; si->dma->samplebits = 16;
Cvar_SetValue("s_loadas8bit", false); Cvar_SetValue("s_loadas8bit", false);
} }
s_khz = Cvar_Get("s_khz", "0", CVAR_ARCHIVE); s_khz = Cvar_Get("s_khz", "0", CVAR_ARCHIVE);
switch ((int) s_khz->value) { switch ((int) s_khz->value) {
case 48: case 48:
dma.speed = AL_RATE_48000; si->dma->speed = AL_RATE_48000;
break; break;
case 44: case 44:
dma.speed = AL_RATE_44100; si->dma->speed = AL_RATE_44100;
break; break;
case 32: case 32:
dma.speed = AL_RATE_32000; si->dma->speed = AL_RATE_32000;
break; break;
case 22: case 22:
dma.speed = AL_RATE_22050; si->dma->speed = AL_RATE_22050;
break; break;
case 16: case 16:
dma.speed = AL_RATE_16000; si->dma->speed = AL_RATE_16000;
break; break;
case 11: case 11:
dma.speed = AL_RATE_11025; si->dma->speed = AL_RATE_11025;
break; break;
case 8: case 8:
dma.speed = AL_RATE_8000; si->dma->speed = AL_RATE_8000;
break; break;
default: default:
dma.speed = AL_RATE_22050; si->dma->speed = AL_RATE_22050;
Com_Printf("Don't currently support %ikHz sample rate, using %i.\n", (int) s_khz->value, (int) (dma.speed/1000)); si->Com_Printf("Don't currently support %ikHz sample rate, using %i.\n", (int) s_khz->value, (int) (si->dma->speed/1000));
} }
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); /* si->channels = Cvar_Get("s", "2", CVAR_ARCHIVE);*/
dma.channels = (int) sndchannels->value; si->dma->channels = (int) si->channels->value;
if (dma.channels != 2) if (si->dma->channels != 2)
Com_Printf("Don't currently support %i sound channels, try 2.\n", dma.channels); si->Com_Printf("Don't currently support %i sound channels, try 2.\n", si->dma->channels);
ac = alNewConfig(); ac = alNewConfig();
alSetChannels(ac, AL_STEREO); alSetChannels(ac, AL_STEREO);
alSetStampFmt(ac, AL_SAMPFMT_TWOSCOMP); alSetStampFmt(ac, AL_SAMPFMT_TWOSCOMP);
alSetQueueSize(ac, QSND_BUFFER_FRAMES); alSetQueueSize(ac, QSND_BUFFER_FRAMES);
if (dma.samplebits == 8) if (si->dma->samplebits == 8)
alSetWidth(ac, AL_SAMPLE_8); alSetWidth(ac, AL_SAMPLE_8);
else else
alSetWidth(ac, AL_SAMPLE_16); alSetWidth(ac, AL_SAMPLE_16);
@ -155,19 +153,19 @@ qboolean SNDDMA_Init(void) {
pvbuf[0].param = AL_MASTER_CLOCK; pvbuf[0].param = AL_MASTER_CLOCK;
pvbuf[0].value.i = AL_CRYSTAL_MCLK_TYPE; pvbuf[0].value.i = AL_CRYSTAL_MCLK_TYPE;
pvbuf[1].param = AL_RATE; pvbuf[1].param = AL_RATE;
pvbuf[1].value.ll = alIntToFixed(dma.speed); pvbuf[1].value.ll = alIntToFixed(si->dma->speed);
alSetParams(alGetResource(sgisnd_aport), pvbuf, 2); alSetParams(alGetResource(sgisnd_aport), pvbuf, 2);
if (pvbuf[1].sizeOut < 0) if (pvbuf[1].sizeOut < 0)
printf("illegal sample rate %d\n", dma.speed); printf("illegal sample rate %d\n", si->dma->speed);
sgisnd_frames_per_ns = dma.speed * 1.0e-9; sgisnd_frames_per_ns = si->dma->speed * 1.0e-9;
dma.samples = sizeof(dma_buffer) / (dma.samplebits / 8); si->dma->samples = sizeof(dma_buffer) / (si->dma->samplebits / 8);
dma.submission_chunk = 1; si->dma->submission_chunk = 1;
dma.buffer = (unsigned char *) dma_buffer; si->dma->buffer = (unsigned char *) dma_buffer;
dma.samplepos = 0; si->dma->samplepos = 0;
alFreeConfig(ac); alFreeConfig(ac);
return true; return true;
@ -178,37 +176,35 @@ qboolean SNDDMA_Init(void) {
int i; int i;
struct audio_buf_info info; struct audio_buf_info info;
int caps; int caps;
/*
extern uid_t saved_euid; extern uid_t saved_euid;
*/
if (snd_inited) if (snd_inited)
return 1; return 1;
snd_inited = 0; snd_inited = 0;
if (!snddevice) { si = s;
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);
}
// open /dev/dsp, confirm 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)" */ /* snd_bsd.c had "if (!audio_fd)" */
if (audio_fd == -1) if (audio_fd == -1)
{ {
seteuid(saved_euid); /* seteuid(saved_euid);*/
audio_fd = open(snddevice->string, O_RDWR); audio_fd = open(si->device->string, O_RDWR);
/* moved from below in snd_bsd.c -- jaq */ /* moved from below in snd_bsd.c -- jaq */
seteuid(getuid()); /*seteuid(getuid());*/
if (audio_fd == -1) if (audio_fd == -1)
{ {
perror(snddevice->string); perror(si->device->string);
seteuid(getuid()); /*
Com_Printf("SNDDMA_Init: Could not open %s.\n", snddevice->string); seteuid(getuid());*/
si->Com_Printf("SNDDMA_Init: Could not open %s.\n", si->device->string);
return 0; return 0;
} }
/* /*
@ -219,8 +215,8 @@ qboolean SNDDMA_Init(void) {
rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0); rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
if (rc == -1) /* snd_bsd has "rc < 0" */ if (rc == -1) /* snd_bsd has "rc < 0" */
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not reset %s.\n", snddevice->string); si->Com_Printf("SNDDMA_Init: Could not reset %s.\n", si->device->string);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -228,8 +224,8 @@ qboolean SNDDMA_Init(void) {
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1) if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Sound driver too old.\n"); si->Com_Printf("SNDDMA_Init: Sound driver too old.\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -237,7 +233,7 @@ qboolean SNDDMA_Init(void) {
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) 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); si->Com_Printf("SNDDMA_Init: Sorry, but your soundcard doesn't support trigger or mmap. (%08x)\n", caps);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -246,7 +242,7 @@ qboolean SNDDMA_Init(void) {
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
{ {
perror("GETOSPACE"); perror("GETOSPACE");
Com_Printf("SNDDMA_Init: GETOSPACE ioctl failed.\n"); si->Com_Printf("SNDDMA_Init: GETOSPACE ioctl failed.\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -254,51 +250,51 @@ qboolean SNDDMA_Init(void) {
// set sample bits & speed // set sample bits & speed
dma.samplebits = (int)sndbits->value; si->dma->samplebits = (int)si->bits->value;
if (dma.samplebits != 16 && dma.samplebits != 8) { if (si->dma->samplebits != 16 && si->dma->samplebits != 8) {
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt); ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
#ifdef HAVE_AFMT_S16_NE #ifdef HAVE_AFMT_S16_NE
if (fmt & AFMT_S16_NE) if (fmt & AFMT_S16_NE)
#else #else
if (fmt & AFMT_S16_LE) if (fmt & AFMT_S16_LE)
#endif #endif
dma.samplebits = 16; si->dma->samplebits = 16;
else if (fmt & AFMT_U8) dma.samplebits = 8; else if (fmt & AFMT_U8) si->dma->samplebits = 8;
} }
/* in relnev 0.9, from here until the next RELNEV 0.9 comment has been moved /* in relnev 0.9, from here until the next RELNEV 0.9 comment has been moved
* down to the following RELNEV 0.9 comment -- jaq */ * down to the following RELNEV 0.9 comment -- jaq */
dma.speed = (int)sndspeed->value; si->dma->speed = (int)si->speed->value;
if (!dma.speed) { if (!si->dma->speed) {
for (i=0 ; i<sizeof(tryrates)/4 ; i++) for (i=0 ; i<sizeof(tryrates)/4 ; i++)
if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
break; break;
dma.speed = tryrates[i]; si->dma->speed = tryrates[i];
} }
dma.channels = (int)sndchannels->value; si->dma->channels = (int)si->channels->value;
if (dma.channels < 1 || dma.channels > 2) if (si->dma->channels < 1 || si->dma->channels > 2)
dma.channels = 2; si->dma->channels = 2;
tmp = 0; tmp = 0;
if (dma.channels == 2) if (si->dma->channels == 2)
tmp = 1; tmp = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0) if (rc < 0)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not set %s to stereo=%d.", snddevice->string, dma.channels); si->Com_Printf("SNDDMA_Init: Could not set %s to stereo=%d.", si->device->string, si->dma->channels);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
} }
if (tmp) if (tmp)
dma.channels = 2; si->dma->channels = 2;
else else
dma.channels = 1; si->dma->channels = 1;
/* RELNEV 0.9 end deletion */ /* RELNEV 0.9 end deletion */
if (dma.samplebits == 16) if (si->dma->samplebits == 16)
{ {
#ifdef HAVE_AFMT_S16_NE #ifdef HAVE_AFMT_S16_NE
rc = AFMT_S16_NE; rc = AFMT_S16_NE;
@ -308,21 +304,21 @@ qboolean SNDDMA_Init(void) {
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) if (rc < 0)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not support 16-bit data. Try 8-bit.\n"); si->Com_Printf("SNDDMA_Init: Could not support 16-bit data. Try 8-bit.\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
} }
} }
else if (dma.samplebits == 8) else if (si->dma->samplebits == 8)
{ {
rc = AFMT_U8; rc = AFMT_U8;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) if (rc < 0)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not support 8-bit data.\n"); si->Com_Printf("SNDDMA_Init: Could not support 8-bit data.\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -330,8 +326,8 @@ qboolean SNDDMA_Init(void) {
} }
else else
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: %d-bit sound not supported.", dma.samplebits); si->Com_Printf("SNDDMA_Init: %d-bit sound not supported.", si->dma->samplebits);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -339,11 +335,11 @@ qboolean SNDDMA_Init(void) {
/* RELNEV 0.9 insert some here */ /* RELNEV 0.9 insert some here */
rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed); rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &si->dma->speed);
if (rc < 0) if (rc < 0)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not set %s speed to %d.", snddevice->string, dma.speed); si->Com_Printf("SNDDMA_Init: Could not set %s speed to %d.", si->device->string, si->dma->speed);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -355,13 +351,13 @@ qboolean SNDDMA_Init(void) {
tmp = 0; tmp = 0;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8); si->dma->samples = info.fragstotal * info.fragsize / (si->dma->samplebits/8);
dma.submission_chunk = 1; si->dma->submission_chunk = 1;
// memory map the dma buffer // memory map the dma buffer
if (!dma.buffer) { if (!si->dma->buffer) {
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize, si->dma->buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize,
#if defined(__FreeBSD__) && (__FreeBSD_version < 500000) #if defined(__FreeBSD__) && (__FreeBSD_version < 500000)
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
#else #else
@ -369,17 +365,17 @@ qboolean SNDDMA_Init(void) {
#endif #endif
MAP_FILE|MAP_SHARED, audio_fd, 0); MAP_FILE|MAP_SHARED, audio_fd, 0);
} }
if (!dma.buffer || dma.buffer == MAP_FAILED) { if (!si->dma->buffer || si->dma->buffer == MAP_FAILED) {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not mmap %s.\n", snddevice->string); si->Com_Printf("SNDDMA_Init: Could not mmap %s.\n", si->device->string);
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
} }
if (rc < 0) { if (rc < 0) {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not toggle. (1)\n"); si->Com_Printf("SNDDMA_Init: Could not toggle. (1)\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
@ -387,14 +383,16 @@ qboolean SNDDMA_Init(void) {
tmp = PCM_ENABLE_OUTPUT; tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) { if (rc < 0) {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_Init: Could not toggle. (2)\n"); si->Com_Printf("SNDDMA_Init: Could not toggle. (2)\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
return 0; return 0;
} }
dma.samplepos = 0; si->Com_Printf("oss: buffer size is %d, %d samples\n", info.fragstotal * info.fragsize, si->dma->samples);
si->dma->samplepos = 0;
snd_inited = 1; snd_inited = 1;
return 1; return 1;
#endif /* !__sgi */ #endif /* !__sgi */
@ -428,18 +426,18 @@ int SNDDMA_GetDMAPos(void) {
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
{ {
perror(snddevice->string); perror(si->device->string);
Com_Printf("SNDDMA_GetDMAPos: GETOPTR failed.\n"); si->Com_Printf("SNDDMA_GetDMAPos: GETOPTR failed.\n");
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
snd_inited = 0; snd_inited = 0;
return 0; return 0;
} }
// dma.samplepos = (count.bytes / (dma.samplebits / 8)) & (dma.samples-1); // si->dma->samplepos = (count.bytes / (si->dma->samplebits / 8)) & (si->dma->samples-1);
// fprintf(stderr, "%d \r", count.ptr); // fprintf(stderr, "%d \r", count.ptr);
dma.samplepos = count.ptr / (dma.samplebits / 8); si->dma->samplepos = count.ptr / (si->dma->samplebits / 8);
return dma.samplepos; return si->dma->samplepos;
#endif /* __sgi */ #endif /* __sgi */
} }
@ -457,8 +455,8 @@ void SNDDMA_Shutdown(void) {
} }
#else #else
if (snd_inited) { if (snd_inited) {
munmap (dma.buffer, dma.samples *dma.samplebits / 8); munmap (si->dma->buffer, si->dma->samples *si->dma->samplebits / 8);
dma.buffer = 0L; si->dma->buffer = 0L;
close(audio_fd); close(audio_fd);
audio_fd = -1; audio_fd = -1;
@ -492,7 +490,7 @@ void SNDDMA_Submit(void) {
nFillable = alGetFillable(sgisnd_aport); nFillable = alGetFillable(sgisnd_aport);
nFilled = QSND_BUFFER_FRAMES - nFillable; nFilled = QSND_BUFFER_FRAMES - nFillable;
nFrames = dma.samples >> (dma.channels - 1); nFrames = si->dma->samples >> (si->dma->channels - 1);
if (paintedtime - soundtime < nFrames) if (paintedtime - soundtime < nFrames)
nFrames = paintedtime - soundtime; nFrames = paintedtime - soundtime;
@ -516,8 +514,8 @@ void SNDDMA_Submit(void) {
/* account for stereo */ /* account for stereo */
nFramesLeft = nFrames; nFramesLeft = nFrames;
if (nPos + nFrames * dma.channels > QSND_BUFFER_SIZE) { if (nPos + nFrames * si->dma->channels > QSND_BUFFER_SIZE) {
int nFramesAtEnd = (QSND_BUFFER_SIZE - nPos) >> (dma.channels - 1); int nFramesAtEnd = (QSND_BUFFER_SIZE - nPos) >> (si->dma->channels - 1);
alWriteFrames(sgisnd_aport, &dma_buffer[nPos], nFramesAtEnd); alWriteFrames(sgisnd_aport, &dma_buffer[nPos], nFramesAtEnd);
nPos = 0; nPos = 0;