Move sound targets into a library. Still doesn't pick one at runtime though.

This commit is contained in:
Adam Olsen 2001-04-10 09:40:09 +00:00
parent 27d177f978
commit 69022c7ffb
23 changed files with 6346 additions and 72 deletions

View file

@ -1395,6 +1395,7 @@ AC_OUTPUT(
libs/Makefile
libs/audio/Makefile
libs/audio/cd/Makefile
libs/audio/targets/Makefile
libs/gamecode/Makefile
libs/util/Makefile
qw/include/Makefile

View file

@ -34,6 +34,13 @@
#include "QF/cvar.h"
#include "QF/zone.h"
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
#define NUM_AMBIENTS 4 // automatic ambient sounds
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{

View file

@ -1,4 +1,4 @@
SUBDIRS= cd
SUBDIRS= cd targets
clean-local:
rm -f *.a

View file

@ -0,0 +1,41 @@
lib_LTLIBRARIES = libQFsound.la
libQFsound_la_LDFLAGS = -version-info 1:0:0 $(CD_LIBS)
#if ASM_ARCH
sound_ASM= snd_mixa.S
#endif
#
# ... Audio targets
#
if SNDTYPE_SDL
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sdl.c $(sound_ASM)
endif
if SNDTYPE_ALSA_0_5
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c $(sound_ASM)
endif
if SNDTYPE_ALSA_0_9
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_9.c $(sound_ASM)
endif
# No idea what this is. it's in configure.in though...
#if SNDTYPE_MME
#libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_mme.c $(sound_ASM)
#endif
if SNDTYPE_OSS
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_oss.c $(sound_ASM)
endif
if SNDTYPE_SGI
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sgi.c $(sound_ASM)
endif
if SNDTYPE_SUN
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sun.c $(sound_ASM)
endif
if SNDTYPE_WIN32
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_win.c $(sound_ASM)
endif
if SNDTYPE_NULL
libQFsound_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_null.c $(sound_ASM)
endif
LIBLIST = libQFsound.la @LIBRARY_SEARCH_PATH@

View file

@ -0,0 +1,358 @@
/*
snd_alsa_0_5.c
Support for ALSA 0.5, the old stable version of ALSA.
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#if defined HAVE_SYS_SOUNDCARD_H
# include <sys/soundcard.h>
#elif defined HAVE_LINUX_SOUNDCARD_H
# include <linux/soundcard.h>
#elif HAVE_MACHINE_SOUNDCARD_H
# include <machine/soundcard.h>
#endif
#include <sys/asoundlib.h>
#include "QF/console.h"
#include "QF/qargs.h"
#include "QF/sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void*)-1)
#endif
static int snd_inited;
static snd_pcm_t *pcm_handle;
static struct snd_pcm_channel_info cinfo;
static struct snd_pcm_channel_params params;
static struct snd_pcm_channel_setup setup;
static snd_pcm_mmap_control_t *mmap_control = NULL;
static char *mmap_data = NULL;
static int card = -1, dev = -1;
int
check_card (int card)
{
snd_ctl_t *handle;
snd_ctl_hw_info_t info;
int rc;
if ((rc = snd_ctl_open (&handle, card)) < 0) {
Con_Printf ("Error: control open (%i): %s\n", card, snd_strerror (rc));
return rc;
}
if ((rc = snd_ctl_hw_info (handle, &info)) < 0) {
Con_Printf ("Error: control hardware info (%i): %s\n", card,
snd_strerror (rc));
snd_ctl_close (handle);
return rc;
}
snd_ctl_close (handle);
if (dev == -1) {
for (dev = 0; dev < info.pcmdevs; dev++) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
} else {
if (dev >= 0 && dev < info.pcmdevs) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
}
return 1;
}
qboolean
SNDDMA_Init (void)
{
int rc = 0, i;
char *err_msg = "";
int rate = -1, format = -1, bps, stereo = -1, frag_size;
unsigned int mask;
mask = snd_cards_mask ();
if (!mask) {
Con_Printf ("No sound cards detected\n");
return 0;
}
if (snd_device->string[0]) {
sscanf (snd_device->string, "%d,%d", &card, &dev);
}
if (snd_bits->int_val) {
i = snd_bits->int_val;
if (i == 16) {
format = SND_PCM_SFMT_S16_LE;
} else if (i == 8) {
format = SND_PCM_SFMT_U8;
} else {
Con_Printf ("Error: invalid sample bits: %d\n", i);
return 0;
}
}
if (snd_rate->int_val) {
rate = snd_rate->int_val;
if (rate != 44100 && rate != 22050 && rate != 11025) {
Con_Printf ("Error: invalid sample rate: %d\n", rate);
return 0;
}
}
stereo = snd_stereo->int_val;
if (card == -1) {
for (card = 0; card < SND_CARDS; card++) {
if (!(mask & (1 << card)))
continue;
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
}
} else {
if (dev == -1) {
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
} else {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) < 0) {
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
}
goto dev_openned;
}
}
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
dev_openned:
Con_Printf ("Using card %d, device %d.\n", card, dev);
memset (&cinfo, 0, sizeof (cinfo));
cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
snd_pcm_channel_info (pcm_handle, &cinfo);
Con_Printf ("%08x %08x %08x\n", cinfo.flags, cinfo.formats, cinfo.rates);
if ((rate == -1 || rate == 44100) && cinfo.rates & SND_PCM_RATE_44100) {
rate = 44100;
frag_size = 512; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 22050)
&& cinfo.rates & SND_PCM_RATE_22050) {
rate = 22050;
frag_size = 256; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 11025)
&& cinfo.rates & SND_PCM_RATE_11025) {
rate = 11025;
frag_size = 128; /* assuming stereo 8 bit */
} else {
Con_Printf ("ALSA: desired rates not supported\n");
goto error_2;
}
if ((format == -1 || format == SND_PCM_SFMT_S16_LE)
&& cinfo.formats & SND_PCM_FMT_S16_LE) {
format = SND_PCM_SFMT_S16_LE;
bps = 16;
frag_size *= 2;
} else if ((format == -1 || format == SND_PCM_SFMT_U8)
&& cinfo.formats & SND_PCM_FMT_U8) {
format = SND_PCM_SFMT_U8;
bps = 8;
} else {
Con_Printf ("ALSA: desired formats not supported\n");
goto error_2;
}
if (stereo && cinfo.max_voices >= 2) {
stereo = 1;
} else {
stereo = 0;
frag_size /= 2;
}
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio munmap";
if ((rc = snd_pcm_munmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
goto error;
memset (&params, 0, sizeof (params));
params.channel = SND_PCM_CHANNEL_PLAYBACK;
params.mode = SND_PCM_MODE_BLOCK;
params.format.interleave = 1;
params.format.format = format;
params.format.rate = rate;
params.format.voices = stereo + 1;
params.start_mode = SND_PCM_START_GO;
params.stop_mode = SND_PCM_STOP_ROLLOVER;
params.buf.block.frag_size = frag_size;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = -1;
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio params";
if ((rc = snd_pcm_channel_params (pcm_handle, &params)) < 0)
goto error;
err_msg = "audio mmap";
if (
(rc =
snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
(void **) &mmap_data)) < 0)
goto error;
err_msg = "audio prepare";
if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
0) goto error;
memset (&setup, 0, sizeof (setup));
setup.mode = SND_PCM_MODE_BLOCK;
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
err_msg = "audio setup";
if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
goto error;
shm = &sn;
memset ((dma_t *) shm, 0, sizeof (*shm));
shm->splitbuffer = 0;
shm->channels = setup.format.voices;
shm->submission_chunk = 128; // don't mix less than this #
shm->samplepos = 0; // in mono samples
shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
shm->samples =
setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8); // mono
//
// samples
// in
// buffer
shm->speed = setup.format.rate;
shm->buffer = (unsigned char *) mmap_data;
Con_Printf ("%5d stereo\n", shm->channels - 1);
Con_Printf ("%5d samples\n", shm->samples);
Con_Printf ("%5d samplepos\n", shm->samplepos);
Con_Printf ("%5d samplebits\n", shm->samplebits);
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf ("%5d speed\n", shm->speed);
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
Con_Printf ("%5d total_channels\n", total_channels);
snd_inited = 1;
return 1;
error:
Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
error_2:
snd_pcm_close (pcm_handle);
return 0;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return 0;
shm->samplepos =
(mmap_control->status.frag_io +
1) * setup.buf.block.frag_size / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
snd_pcm_close (pcm_handle);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int count = paintedtime - soundtime;
int i, s, e;
int rc;
count += setup.buf.block.frag_size - 1;
count /= setup.buf.block.frag_size;
s = soundtime / setup.buf.block.frag_size;
e = s + count;
for (i = s; i < e; i++)
mmap_control->fragments[i % setup.buf.block.frags].data = 1;
switch (mmap_control->status.status) {
case SND_PCM_STATUS_PREPARED:
if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK))
< 0) {
fprintf (stderr, "unable to start playback. %s\n",
snd_strerror (rc));
exit (1);
}
break;
case SND_PCM_STATUS_RUNNING:
break;
case SND_PCM_STATUS_UNDERRUN:
if (
(rc =
snd_pcm_plugin_prepare (pcm_handle,
SND_PCM_CHANNEL_PLAYBACK)) < 0) {
fprintf (stderr,
"underrun: playback channel prepare error. %s\n",
snd_strerror (rc));
exit (1);
}
break;
default:
break;
}
}

View file

@ -0,0 +1,313 @@
/*
snd_alsa_0_9.c
Support for ALSA 0.9 sound driver (cvs development version)
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <sys/asoundlib.h>
#include "QF/qtypes.h"
#include "QF/sound.h"
#include "QF/qargs.h"
#include "QF/console.h"
static int snd_inited;
static snd_pcm_t *pcm;
static const snd_pcm_channel_area_t *mmap_areas;
static char *pcmname = NULL;
size_t buffer_size;
qboolean
SNDDMA_Init (void)
{
int err;
int rate = -1, bps = -1, stereo = -1, frag_size;
snd_pcm_hw_params_t *hw;
snd_pcm_sw_params_t *sw;
snd_pcm_hw_params_alloca (&hw);
snd_pcm_sw_params_alloca (&sw);
if (snd_device->string[0])
pcmname = snd_device->string;
if (snd_bits->int_val) {
bps = snd_bits->int_val;
if (bps != 16 && bps != 8) {
Con_Printf ("Error: invalid sample bits: %d\n", bps);
return 0;
}
}
if (snd_rate->int_val) {
rate = snd_rate->int_val;
if (rate != 44100 && rate != 22050 && rate != 11025) {
Con_Printf ("Error: invalid sample rate: %d\n", rate);
return 0;
}
}
stereo = snd_stereo->int_val;
if (!pcmname)
pcmname = "plug:0,0";
if ((err = snd_pcm_open (&pcm, pcmname,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
Con_Printf ("Error: audio open error: %s\n", snd_strerror (err));
return 0;
}
Con_Printf ("Using PCM %s.\n", pcmname);
snd_pcm_hw_params_any (pcm, hw);
switch (rate) {
case -1:
if (snd_pcm_hw_params_set_rate_near (pcm, hw, 44100, 0) >= 0) {
frag_size = 256; /* assuming stereo 8 bit */
rate = 44100;
} else if (snd_pcm_hw_params_set_rate_near (pcm, hw, 22050, 0) >= 0) {
frag_size = 128; /* assuming stereo 8 bit */
rate = 22050;
} else if (snd_pcm_hw_params_set_rate_near (pcm, hw, 11025, 0) >= 0) {
frag_size = 64; /* assuming stereo 8 bit */
rate = 11025;
} else {
Con_Printf ("ALSA: no useable rates\n");
goto error;
}
break;
case 11025:
case 22050:
case 44100:
if (snd_pcm_hw_params_set_rate_near (pcm, hw, rate, 0) >= 0) {
frag_size = 64 * rate / 11025; /* assuming stereo 8 bit */
break;
}
/* Fall through */
default:
Con_Printf ("ALSA: desired rate not supported\n");
goto error;
}
switch (bps) {
case -1:
if (snd_pcm_hw_params_set_format (pcm, hw, SND_PCM_FORMAT_S16_LE) >=
0) {
bps = 16;
} else if (snd_pcm_hw_params_set_format (pcm, hw, SND_PCM_FORMAT_U8)
>= 0) {
bps = 8;
} else {
Con_Printf ("ALSA: no useable formats\n");
goto error;
}
break;
case 8:
case 16:
if (snd_pcm_hw_params_set_format (pcm, hw,
bps == 8 ? SND_PCM_FORMAT_U8 :
SND_PCM_FORMAT_S16) >= 0) {
break;
}
/* Fall through */
default:
Con_Printf ("ALSA: desired format not supported\n");
goto error;
}
if (snd_pcm_hw_params_set_access (pcm, hw,
SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
Con_Printf ("ALSA: interleaved is not supported\n");
goto error;
}
switch (stereo) {
case -1:
if (snd_pcm_hw_params_set_channels (pcm, hw, 2) >= 0) {
stereo = 1;
} else if (snd_pcm_hw_params_set_channels (pcm, hw, 1) >= 0) {
stereo = 0;
} else {
Con_Printf ("ALSA: no useable channels\n");
goto error;
}
break;
case 0:
case 1:
if (snd_pcm_hw_params_set_channels (pcm, hw, stereo ? 2 : 1) >= 0)
break;
/* Fall through */
default:
Con_Printf ("ALSA: desired channels not supported\n");
goto error;
}
snd_pcm_hw_params_set_period_size_near (pcm, hw, frag_size, 0);
err = snd_pcm_hw_params (pcm, hw);
if (err < 0) {
Con_Printf ("ALSA: unable to install hw params\n");
goto error;
}
snd_pcm_sw_params_current (pcm, sw);
snd_pcm_sw_params_set_start_mode (pcm, sw, SND_PCM_START_EXPLICIT);
snd_pcm_sw_params_set_xrun_mode (pcm, sw, SND_PCM_XRUN_NONE);
err = snd_pcm_sw_params (pcm, sw);
if (err < 0) {
Con_Printf ("ALSA: unable to install sw params\n");
goto error;
}
mmap_areas = snd_pcm_mmap_running_areas (pcm);
shm = &sn;
memset ((dma_t *) shm, 0, sizeof (*shm));
shm->splitbuffer = 0;
shm->channels = stereo + 1;
shm->submission_chunk = snd_pcm_hw_params_get_period_size (hw, 0); // don't
// mix
// less
// than
// this
// #
shm->samplepos = 0; // in mono samples
shm->samplebits = bps;
buffer_size = snd_pcm_hw_params_get_buffer_size (hw);
shm->samples = buffer_size * shm->channels; // mono samples in buffer
shm->speed = rate;
shm->buffer = (unsigned char *) mmap_areas->addr;
Con_Printf ("%5d stereo\n", shm->channels - 1);
Con_Printf ("%5d samples\n", shm->samples);
Con_Printf ("%5d samplepos\n", shm->samplepos);
Con_Printf ("%5d samplebits\n", shm->samplebits);
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf ("%5d speed\n", shm->speed);
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
Con_Printf ("%5d total_channels\n", total_channels);
snd_inited = 1;
return 1;
error:
snd_pcm_close (pcm);
return 0;
}
static inline int
get_hw_ptr ()
{
size_t app_ptr;
snd_pcm_sframes_t delay;
int hw_ptr;
if (snd_pcm_state (pcm) != SND_PCM_STATE_RUNNING)
return 0;
app_ptr = snd_pcm_mmap_offset (pcm);
snd_pcm_delay (pcm, &delay);
hw_ptr = app_ptr - delay;
if (hw_ptr < 0)
hw_ptr += buffer_size;
return hw_ptr;
}
int
SNDDMA_GetDMAPos (void)
{
int hw_ptr;
if (!snd_inited)
return 0;
hw_ptr = get_hw_ptr ();
hw_ptr *= shm->channels;
shm->samplepos = hw_ptr;
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
snd_pcm_close (pcm);
snd_inited = 0;
}
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void
SNDDMA_Submit (void)
{
int count = paintedtime - soundtime;
int avail;
int missed;
int state;
int hw_ptr;
int offset;
state = snd_pcm_state (pcm);
switch (state) {
case SND_PCM_STATE_PREPARED:
snd_pcm_mmap_forward (pcm, count);
snd_pcm_start (pcm);
break;
case SND_PCM_STATE_RUNNING:
hw_ptr = get_hw_ptr ();
missed = hw_ptr - shm->samplepos / shm->channels;
if (missed < 0)
missed += buffer_size;
count -= missed;
offset = snd_pcm_mmap_offset (pcm);
if (offset > hw_ptr)
count -= (offset - hw_ptr);
else
count -= (buffer_size - hw_ptr + offset);
if (count < 0) {
snd_pcm_rewind (pcm, -count);
} else {
avail = snd_pcm_avail_update (pcm);
if (avail < 0)
avail = buffer_size;
if (count > avail)
count = avail;
snd_pcm_mmap_forward (pcm, count);
}
break;
default:
break;
}
}

View file

@ -0,0 +1,108 @@
/*
snd_disk.c
write sound to a disk file
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include "QF/console.h"
#include "QF/sound.h"
#include "QF/qargs.h"
static int snd_inited;
QFile *snd_file;
qboolean
SNDDMA_Init (void)
{
shm = &sn;
memset ((dma_t *) shm, 0, sizeof (*shm));
shm->splitbuffer = 0;
shm->channels = 2;
shm->submission_chunk = 1; // don't mix less than this #
shm->samplepos = 0; // in mono samples
shm->samplebits = 16;
shm->samples = 16384; // mono samples in buffer
shm->speed = 44100;
shm->buffer = malloc (shm->samples * shm->channels * shm->samplebits / 8);
Con_Printf ("%5d stereo\n", shm->channels - 1);
Con_Printf ("%5d samples\n", shm->samples);
Con_Printf ("%5d samplepos\n", shm->samplepos);
Con_Printf ("%5d samplebits\n", shm->samplebits);
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf ("%5d speed\n", shm->speed);
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
Con_Printf ("%5d total_channels\n", total_channels);
if (!(snd_file = Qopen ("qf.raw", "wb")))
return 0;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
shm->samplepos = 0;
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
Qclose (snd_file);
snd_file = 0;
free (shm->buffer);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int count = (paintedtime - soundtime) * shm->samplebits / 8;
Qwrite (snd_file, shm->buffer, count);
}

1020
libs/audio/targets/snd_dma.c Normal file

File diff suppressed because it is too large Load diff

1281
libs/audio/targets/snd_gus.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,405 @@
/*
snd_mem.c
sound caching
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/console.h"
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/sound.h"
#include "QF/sys.h"
int cache_full_cycle;
byte *S_Alloc (int size);
/*
ResampleSfx
*/
void
ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte * data)
{
int outcount;
int srcsample;
float stepscale;
int i;
int sample, samplefrac, fracstep;
sfxcache_t *sc;
short *is, *os;
unsigned char *ib, *ob;
sc = Cache_Check (&sfx->cache);
if (!sc)
return;
is = (short *) data;
os = (short *) sc->data;
ib = data;
ob = sc->data;
stepscale = (float) inrate / shm->speed; // this is usually 0.5, 1, or
//
// 2
outcount = sc->length / stepscale;
sc->speed = shm->speed;
if (loadas8bit->int_val)
sc->width = 1;
else
sc->width = 2;
sc->stereo = 0;
// resample / decimate to the current source rate
if (stepscale == 1) {
if (inwidth == 1 && sc->width == 1) {
for (i = 0; i < outcount; i++) {
*ob++ = *ib++ - 128;
}
} else if (inwidth == 1 && sc->width == 2) {
for (i = 0; i < outcount; i++) {
*os++ = (*ib++ - 128) << 8;
}
} else if (inwidth == 2 && sc->width == 1) {
for (i = 0; i < outcount; i++) {
*ob++ = LittleShort (*is++) >> 8;
}
} else if (inwidth == 2 && sc->width == 2) {
for (i = 0; i < outcount; i++) {
*os++ = LittleShort (*is++);
}
}
} else {
// general case
if (snd_interp->int_val && stepscale < 1) {
int points = 1 / stepscale;
int j;
for (i = 0; i < sc->length; i++) {
int s1, s2;
if (inwidth == 2) {
s2 = s1 = LittleShort (is[0]);
if (i < sc->length - 1)
s2 = LittleShort (is[1]);
is++;
} else {
s2 = s1 = (ib[0] - 128) << 8;
if (i < sc->length - 1)
s2 = (ib[1] - 128) << 8;
ib++;
}
for (j = 0; j < points; j++) {
sample = s1 + (s2 - s1) * ((float) j) / points;
if (sc->width == 2) {
os[j] = sample;
} else {
ob[j] = sample >> 8;
}
}
if (sc->width == 2) {
os += points;
} else {
ob += points;
}
}
} else {
samplefrac = 0;
fracstep = stepscale * 256;
for (i = 0; i < outcount; i++) {
srcsample = samplefrac >> 8;
samplefrac += fracstep;
if (inwidth == 2)
sample = LittleShort (((short *) data)[srcsample]);
else
sample =
(int) ((unsigned char) (data[srcsample]) - 128) << 8;
if (sc->width == 2)
((short *) sc->data)[i] = sample;
else
((signed char *) sc->data)[i] = sample >> 8;
}
}
}
sc->length = outcount;
if (sc->loopstart != -1)
sc->loopstart = sc->loopstart / stepscale;
}
//=============================================================================
/*
S_LoadSound
*/
sfxcache_t *
S_LoadSound (sfx_t *s)
{
char namebuffer[256];
byte *data;
wavinfo_t info;
int len;
float stepscale;
sfxcache_t *sc;
byte stackbuf[1 * 1024]; // avoid dirtying the cache heap
// see if still in memory
sc = Cache_Check (&s->cache);
if (sc)
return sc;
//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf);
// load it in
strcpy (namebuffer, "sound/");
strncat (namebuffer, s->name, sizeof (namebuffer) - strlen (namebuffer));
// Con_Printf ("loading %s\n",namebuffer);
data = COM_LoadStackFile (namebuffer, stackbuf, sizeof (stackbuf));
if (!data) {
Con_Printf ("Couldn't load %s\n", namebuffer);
return NULL;
}
info = GetWavinfo (s->name, data, com_filesize);
if (info.channels != 1) {
Con_Printf ("%s is a stereo sample\n", s->name);
return NULL;
}
stepscale = (float) info.rate / shm->speed;
len = info.samples / stepscale;
if (loadas8bit->int_val) {
len = len * info.channels;
} else {
len = len * 2 * info.channels;
}
sc = Cache_Alloc (&s->cache, len + sizeof (sfxcache_t), s->name);
if (!sc)
return NULL;
sc->length = info.samples;
sc->loopstart = info.loopstart;
sc->speed = info.rate;
sc->width = info.width;
sc->stereo = info.channels;
ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);
return sc;
}
/*
WAV loading
*/
byte *data_p;
byte *iff_end;
byte *last_chunk;
byte *iff_data;
int iff_chunk_len;
short
GetLittleShort (void)
{
short val = 0;
val = *data_p;
val = val + (*(data_p + 1) << 8);
data_p += 2;
return val;
}
int
GetLittleLong (void)
{
int val = 0;
val = *data_p;
val = val + (*(data_p + 1) << 8);
val = val + (*(data_p + 2) << 16);
val = val + (*(data_p + 3) << 24);
data_p += 4;
return val;
}
void
FindNextChunk (char *name)
{
while (1) {
data_p = last_chunk;
if (data_p >= iff_end) { // didn't find the chunk
data_p = NULL;
return;
}
data_p += 4;
iff_chunk_len = GetLittleLong ();
if (iff_chunk_len < 0) {
data_p = NULL;
return;
}
// if (iff_chunk_len > 1024*1024)
// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
data_p -= 8;
last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
if (!strncmp (data_p, name, 4))
return;
}
}
void
FindChunk (char *name)
{
last_chunk = iff_data;
FindNextChunk (name);
}
void
DumpChunks (void)
{
char str[5];
str[4] = 0;
data_p = iff_data;
do {
memcpy (str, data_p, 4);
data_p += 4;
iff_chunk_len = GetLittleLong ();
Con_Printf ("0x%x : %s (%d)\n", (int) (data_p - 4), str, iff_chunk_len);
data_p += (iff_chunk_len + 1) & ~1;
} while (data_p < iff_end);
}
/*
GetWavinfo
*/
wavinfo_t
GetWavinfo (char *name, byte * wav, int wavlength)
{
wavinfo_t info;
int i;
int format;
int samples;
memset (&info, 0, sizeof (info));
if (!wav)
return info;
iff_data = wav;
iff_end = wav + wavlength;
// find "RIFF" chunk
FindChunk ("RIFF");
if (!(data_p && !strncmp (data_p + 8, "WAVE", 4))) {
Con_Printf ("Missing RIFF/WAVE chunks\n");
return info;
}
// get "fmt " chunk
iff_data = data_p + 12;
// DumpChunks ();
FindChunk ("fmt ");
if (!data_p) {
Con_Printf ("Missing fmt chunk\n");
return info;
}
data_p += 8;
format = GetLittleShort ();
if (format != 1) {
Con_Printf ("Microsoft PCM format only\n");
return info;
}
info.channels = GetLittleShort ();
info.rate = GetLittleLong ();
data_p += 4 + 2;
info.width = GetLittleShort () / 8;
// get cue chunk
FindChunk ("cue ");
if (data_p) {
data_p += 32;
info.loopstart = GetLittleLong ();
// Con_Printf("loopstart=%d\n", sfx->loopstart);
// if the next chunk is a LIST chunk, look for a cue length marker
FindNextChunk ("LIST");
if (data_p) {
if (!strncmp (data_p + 28, "mark", 4)) { // this is not a
// proper parse, but
// it works with
// cooledit...
data_p += 24;
i = GetLittleLong (); // samples in loop
info.samples = info.loopstart + i;
// Con_Printf("looped length: %i\n", i);
}
}
} else
info.loopstart = -1;
// find data chunk
FindChunk ("data");
if (!data_p) {
Con_Printf ("Missing data chunk\n");
return info;
}
data_p += 4;
samples = GetLittleLong () / info.width;
if (info.samples) {
if (samples < info.samples)
Sys_Error ("Sound %s has a bad loop length", name);
} else
info.samples = samples;
info.dataofs = data_p - wav;
return info;
}

View file

@ -0,0 +1,429 @@
/*
snd_mix.c
portable code to mix sounds for snd_dma.c
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/compat.h"
#include "QF/console.h"
#include "QF/sound.h"
#ifdef _WIN32
# include "winquake.h"
#else
# define DWORD unsigned long
#endif
#define PAINTBUFFER_SIZE 512
portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE * 2];
int max_overpaint; // number of extra samples painted
// due to phase shift
int snd_scaletable[32][256];
int *snd_p, snd_linear_count, snd_vol;
short *snd_out;
void Snd_WriteLinearBlastStereo16 (void);
#ifndef USE_INTEL_ASM
void
Snd_WriteLinearBlastStereo16 (void)
{
int i;
int val;
for (i = 0; i < snd_linear_count; i += 2) {
val = (snd_p[i] * snd_vol) >> 8;
if (val > 0x7fff)
snd_out[i] = 0x7fff;
else if (val < (short) 0x8000)
snd_out[i] = (short) 0x8000;
else
snd_out[i] = val;
val = (snd_p[i + 1] * snd_vol) >> 8;
if (val > 0x7fff)
snd_out[i + 1] = 0x7fff;
else if (val < (short) 0x8000)
snd_out[i + 1] = (short) 0x8000;
else
snd_out[i + 1] = val;
}
}
#endif
void
S_TransferStereo16 (int endtime)
{
int lpos;
int lpaintedtime;
DWORD *pbuf;
snd_vol = volume->value * 256;
snd_p = (int *) paintbuffer;
lpaintedtime = paintedtime;
#ifdef _WIN32
if (pDSBuf) {
pbuf = DSOUND_LockBuffer (true);
if (!pbuf) {
Con_Printf ("DSOUND_LockBuffer fails!\n");
return;
}
} else
#endif
{
pbuf = (DWORD *) shm->buffer;
}
while (lpaintedtime < endtime) {
// handle recirculating buffer issues
lpos = lpaintedtime & ((shm->samples >> 1) - 1);
snd_out = (short *) pbuf + (lpos << 1);
snd_linear_count = (shm->samples >> 1) - lpos;
if (lpaintedtime + snd_linear_count > endtime)
snd_linear_count = endtime - lpaintedtime;
snd_linear_count <<= 1;
// write a linear blast of samples
Snd_WriteLinearBlastStereo16 ();
snd_p += snd_linear_count;
lpaintedtime += (snd_linear_count >> 1);
}
#ifdef _WIN32
if (pDSBuf)
DSOUND_LockBuffer (false);
#endif
}
void
S_TransferPaintBuffer (int endtime)
{
int out_idx;
int count;
int out_mask;
int *p;
int step;
int val;
int snd_vol;
DWORD *pbuf;
if (shm->samplebits == 16 && shm->channels == 2) {
S_TransferStereo16 (endtime);
return;
}
p = (int *) paintbuffer;
count = (endtime - paintedtime) * shm->channels;
out_mask = shm->samples - 1;
out_idx = paintedtime * shm->channels & out_mask;
step = 3 - shm->channels;
snd_vol = volume->value * 256;
#ifdef _WIN32
if (pDSBuf) {
pbuf = DSOUND_LockBuffer (true);
if (!pbuf) {
Con_Printf ("DSOUND_LockBuffer fails!\n");
return;
}
} else
#endif
{
pbuf = (DWORD *) shm->buffer;
}
if (shm->samplebits == 16) {
short *out = (short *) pbuf;
while (count--) {
val = (*p * snd_vol) >> 8;
p += step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short) 0x8000)
val = (short) 0x8000;
out[out_idx] = val;
out_idx = (out_idx + 1) & out_mask;
}
} else if (shm->samplebits == 8) {
unsigned char *out = (unsigned char *) pbuf;
while (count--) {
val = (*p * snd_vol) >> 8;
p += step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < (short) 0x8000)
val = (short) 0x8000;
out[out_idx] = (val >> 8) + 128;
out_idx = (out_idx + 1) & out_mask;
}
}
#ifdef _WIN32
if (pDSBuf)
DSOUND_LockBuffer (false);
#endif
}
/*
CHANNEL MIXING
*/
void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
void
S_PaintChannels (int endtime)
{
int i;
int end;
channel_t *ch;
sfxcache_t *sc;
int ltime, count;
while (paintedtime < endtime) {
// if paintbuffer is smaller than DMA buffer
end = endtime;
if (endtime - paintedtime > PAINTBUFFER_SIZE)
end = paintedtime + PAINTBUFFER_SIZE;
// clear the paint buffer
// memset (paintbuffer, 0,
// (end - paintedtime) * sizeof (portable_samplepair_t));
max_overpaint = 0;
// paint in the channels.
ch = channels;
for (i = 0; i < total_channels; i++, ch++) {
if (!ch->sfx)
continue;
if (!ch->leftvol && !ch->rightvol)
continue;
sc = S_LoadSound (ch->sfx);
if (!sc)
continue;
ltime = paintedtime;
while (ltime < end) { // paint up to end
if (ch->end < end)
count = ch->end - ltime;
else
count = end - ltime;
if (count > 0) {
if (sc->width == 1)
SND_PaintChannelFrom8 (ch, sc, count);
else
SND_PaintChannelFrom16 (ch, sc, count);
ltime += count;
}
// if at end of loop, restart
if (ltime >= ch->end) {
if (sc->loopstart >= 0) {
ch->pos = sc->loopstart;
ch->end = ltime + sc->length - ch->pos;
} else { // channel just stopped
ch->sfx = NULL;
break;
}
}
}
}
// transfer out according to DMA format
S_TransferPaintBuffer (end);
memmove (paintbuffer, paintbuffer + end - paintedtime,
max_overpaint * sizeof (paintbuffer[0]));
memset (paintbuffer + max_overpaint, 0, sizeof (paintbuffer)
- max_overpaint * sizeof (paintbuffer[0]));
paintedtime = end;
}
}
void
SND_InitScaletable (void)
{
int i, j;
for (i = 0; i < 32; i++)
for (j = 0; j < 256; j++)
snd_scaletable[i][j] = ((signed char) j) * i * 8;
}
#ifndef USE_INTEL_ASM
void
SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
{
int data;
int *lscale, *rscale;
unsigned char *sfx;
int i;
if (ch->leftvol > 255)
ch->leftvol = 255;
if (ch->rightvol > 255)
ch->rightvol = 255;
lscale = snd_scaletable[ch->leftvol >> 3];
rscale = snd_scaletable[ch->rightvol >> 3];
sfx = (signed char *) sc->data + ch->pos;
for (i = 0; i < count; i++) {
data = sfx[i];
paintbuffer[i].left += lscale[data];
paintbuffer[i].right += rscale[data];
}
ch->pos += count;
}
#endif // !USE_INTEL_ASM
void
SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
{
int data;
int left, right;
int leftvol, rightvol;
signed short *sfx;
unsigned int i = 0;
unsigned int left_phase, right_phase; // Never allowed < 0 anyway
leftvol = ch->leftvol;
rightvol = ch->rightvol;
max_overpaint = max (abs (ch->phase),
max (abs (ch->oldphase), max_overpaint));
sfx = (signed short *) sc->data + ch->pos;
ch->pos += count;
if (ch->phase >= 0) {
left_phase = ch->phase;
right_phase = 0;
} else {
left_phase = 0;
right_phase = -ch->phase;
}
if (ch->oldphase != ch->phase) {
unsigned int old_phase_left, old_phase_right;
unsigned int new_phase_left, new_phase_right;
unsigned int count_left, count_right, c;
if (ch->oldphase >= 0) {
old_phase_left = ch->oldphase;
old_phase_right = 0;
} else {
old_phase_left = 0;
old_phase_right = -ch->oldphase;
}
new_phase_left = left_phase;
new_phase_right = right_phase;
if (new_phase_left > old_phase_left)
count_left = 2 * (new_phase_left - old_phase_left);
else
count_left = old_phase_left - new_phase_left;
if (new_phase_right > old_phase_right)
count_right = 2 * (new_phase_right - old_phase_right);
else
count_right = old_phase_right - new_phase_right;
c = min (count, max (count_right, count_left));
count -= c;
while (c) {
int data = sfx[i];
int left = (data * leftvol) >> 8;
int right = (data * rightvol) >> 8;
if (new_phase_left < old_phase_left) {
if (!(count_left & 1)) {
paintbuffer[i + old_phase_left].left += left;
old_phase_left--;
}
count_left--;
} else if (new_phase_left > old_phase_left) {
paintbuffer[i + old_phase_left].left += left;
old_phase_left++;
paintbuffer[i + old_phase_left].left += left;
} else {
paintbuffer[i + old_phase_left].left += left;
}
if (new_phase_right < old_phase_right) {
if (!(count_right & 1)) {
paintbuffer[i + old_phase_right].right += right;
old_phase_right--;
}
count_right--;
} else if (new_phase_right > old_phase_right) {
paintbuffer[i + old_phase_right].right += right;
old_phase_right++;
paintbuffer[i + old_phase_right].right += right;
} else {
paintbuffer[i + old_phase_right].right += right;
}
c--;
i++;
}
}
for (i = 0; i < count; i++) {
data = sfx[i];
left = (data * leftvol) >> 8;
right = (data * rightvol) >> 8;
paintbuffer[i + left_phase].left += left;
paintbuffer[i + right_phase].right += right;
}
}

View file

@ -0,0 +1,232 @@
/*
snd_mixa.S
x86 assembly-language sound code
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
// #include "quakeasm.h"
#ifdef USE_INTEL_ASM
.text
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
#define ch 4+16
#define sc 8+16
#define count 12+16
.globl C(SND_PaintChannelFrom8)
C(SND_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
movl ch(%esp),%ebx
movl sc(%esp),%esi
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $(sfxc_data),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
testl $1,%ecx
jz LMix8Loop
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
decl %ecx
jz LDone
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
// }
subl $2,%ecx
jnz LMix8Loop
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
.globl C(Snd_WriteLinearBlastStereo16)
C(Snd_WriteLinearBlastStereo16):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_vol),%esi
movl C(snd_out),%edi
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
// val = (snd_p[i]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i] = (short)0x8000;
// else
// snd_out[i] = val;
movl -8(%ebx,%ecx,4),%eax
imull %esi,%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
// val = (snd_p[i+1]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i+1] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i+1] = (short)0x8000;
// else
// snd_out[i+1] = val;
movl -4(%ebx,%ecx,4),%edx
imull %esi,%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
// }
subl $2,%ecx
jnz LWLBLoopTop
// snd_p += snd_linear_count;
popl %ebx
popl %edi
popl %esi
ret
#endif // USE_INTEL_ASM

View file

@ -0,0 +1,145 @@
/*
snd_null.c
include this instead of all the other snd_* files to have no sound
code whatsoever
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#include "QF/qtypes.h"
#include "QF/sound.h"
// =======================================================================
// Various variables also defined in snd_dma.c
// FIXME - should be put in one place
// =======================================================================
channel_t channels[MAX_CHANNELS];
int total_channels;
volatile dma_t *shm = 0;
cvar_t *loadas8bit;
int paintedtime; // sample PAIRS
cvar_t *bgmvolume;
cvar_t *volume;
void
S_Init (void)
{
S_Init_Cvars ();
}
void
S_Init_Cvars (void)
{
volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, 0, "Volume level of sounds");
loadas8bit =
Cvar_Get ("loadas8bit", "0", CVAR_NONE, 0, "Load samples as 8-bit");
bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, 0, "CD music volume");
}
void
S_AmbientOff (void)
{
}
void
S_AmbientOn (void)
{
}
void
S_Shutdown (void)
{
}
void
S_TouchSound (char *sample)
{
}
void
S_ClearBuffer (void)
{
}
void
S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
}
void
S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
float attenuation)
{
}
void
S_StopSound (int entnum, int entchannel)
{
}
sfx_t *
S_PrecacheSound (char *sample)
{
return NULL;
}
void
S_ClearPrecache (void)
{
}
void
S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
{
}
void
S_StopAllSounds (qboolean clear)
{
}
void
S_BeginPrecaching (void)
{
}
void
S_EndPrecaching (void)
{
}
void
S_ExtraUpdate (void)
{
}
void
S_LocalSound (char *s)
{
}

View file

@ -0,0 +1,297 @@
/*
snd_oss.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#if defined HAVE_SYS_SOUNDCARD_H
# include <sys/soundcard.h>
#elif defined HAVE_LINUX_SOUNDCARD_H
# include <linux/soundcard.h>
#elif HAVE_MACHINE_SOUNDCARD_H
# include <machine/soundcard.h>
#endif
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/qargs.h"
#include "QF/sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void *) -1)
#endif
static int audio_fd;
static int snd_inited;
static char *snd_dev = "/dev/dsp";
static int tryrates[] = { 11025, 22050, 22051, 44100, 8000 };
qboolean
SNDDMA_Init (void)
{
int rc;
int fmt;
int tmp;
int i;
struct audio_buf_info info;
int caps;
int retries = 3;
snd_inited = 0;
// open snd_dev, confirm capability to mmap, and get size of dma buffer
if (snd_device->string[0])
snd_dev = snd_device->string;
audio_fd = open (snd_dev, O_RDWR);
if (audio_fd < 0) { // Failed open, retry up to 3 times
// if it's busy
while ((audio_fd < 0) && retries-- &&
((errno == EAGAIN) || (errno == EBUSY))) {
sleep (1);
audio_fd = open (snd_dev, O_RDWR);
}
if (audio_fd < 0) {
perror (snd_dev);
Con_Printf ("Could not open %s\n", snd_dev);
return 0;
}
}
if ((rc = ioctl (audio_fd, SNDCTL_DSP_RESET, 0)) < 0) {
perror (snd_dev);
Con_Printf ("Could not reset %s\n", snd_dev);
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
perror (snd_dev);
Con_Printf ("Sound driver too old\n");
close (audio_fd);
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
Con_Printf ("Sound device can't do memory-mapped I/O.\n");
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror ("GETOSPACE");
Con_Printf ("Um, can't do GETOSPACE?\n");
close (audio_fd);
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
// set sample bits & speed
shm->samplebits = snd_bits->int_val;
if (shm->samplebits != 16 && shm->samplebits != 8) {
ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE) { // little-endian 16-bit signed
shm->samplebits = 16;
} else {
if (fmt & AFMT_U8) { // unsigned 8-bit ulaw
shm->samplebits = 8;
}
}
}
if (snd_rate->int_val) {
shm->speed = snd_rate->int_val;
} else {
for (i = 0; i < (sizeof (tryrates) / 4); i++)
if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
break;
shm->speed = tryrates[i];
}
if (!snd_stereo->int_val) {
shm->channels = 1;
} else {
shm->channels = 2;
}
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits / 8);
shm->submission_chunk = 1;
// memory map the dma buffer
shm->buffer = (unsigned char *) mmap (NULL, info.fragstotal
* info.fragsize,
PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, audio_fd, 0);
if (shm->buffer == MAP_FAILED) {
perror (snd_dev);
Con_Printf ("Could not mmap %s\n", snd_dev);
close (audio_fd);
return 0;
}
tmp = 0;
if (shm->channels == 2)
tmp = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s to stereo=%d", snd_dev, shm->channels);
close (audio_fd);
return 0;
}
if (tmp)
shm->channels = 2;
else
shm->channels = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s speed to %d", snd_dev, shm->speed);
close (audio_fd);
return 0;
}
if (shm->samplebits == 16) {
rc = AFMT_S16_LE;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 16-bit data. Try 8-bit.\n");
close (audio_fd);
return 0;
}
} else if (shm->samplebits == 8) {
rc = AFMT_U8;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 8-bit data.\n");
close (audio_fd);
return 0;
}
} else {
perror (snd_dev);
Con_Printf ("%d-bit sound not supported.", shm->samplebits);
close (audio_fd);
return 0;
}
// toggle the trigger & start her up
tmp = 0;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
shm->samplepos = 0;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
struct count_info count;
if (!snd_inited)
return 0;
if (ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
perror (snd_dev);
Con_Printf ("Uh, sound dead.\n");
close (audio_fd);
snd_inited = 0;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

@ -0,0 +1,158 @@
/*
snd_sdl.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <SDL_audio.h>
#include <SDL_byteorder.h>
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/qargs.h"
#include "QF/sound.h"
static dma_t the_shm;
static int snd_inited;
extern int desired_speed;
extern int desired_bits;
static void
paint_audio (void *unused, Uint8 * stream, int len)
{
if (shm) {
shm->buffer = stream;
shm->samplepos += len / (shm->samplebits / 8);
// Check for samplepos overflow?
S_PaintChannels (shm->samplepos);
}
}
qboolean
SNDDMA_Init (void)
{
SDL_AudioSpec desired, obtained;
snd_inited = 0;
/* Set up the desired format */
desired.freq = desired_speed;
switch (desired_bits) {
case 8:
desired.format = AUDIO_U8;
break;
case 16:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
desired.format = AUDIO_S16MSB;
else
desired.format = AUDIO_S16LSB;
break;
default:
Con_Printf ("Unknown number of audio bits: %d\n", desired_bits);
return 0;
}
desired.channels = 2;
desired.samples = 512;
desired.callback = paint_audio;
/* Open the audio device */
if (SDL_OpenAudio (&desired, &obtained) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
/* Make sure we can support the audio format */
switch (obtained.format) {
case AUDIO_U8:
/* Supported */
break;
case AUDIO_S16LSB:
case AUDIO_S16MSB:
if (((obtained.format == AUDIO_S16LSB) &&
(SDL_BYTEORDER == SDL_LIL_ENDIAN)) ||
((obtained.format == AUDIO_S16MSB) &&
(SDL_BYTEORDER == SDL_BIG_ENDIAN))) {
/* Supported */
break;
}
/* Unsupported, fall through */ ;
default:
/* Not supported -- force SDL to do our bidding */
SDL_CloseAudio ();
if (SDL_OpenAudio (&desired, NULL) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
memcpy (&obtained, &desired, sizeof (desired));
break;
}
SDL_PauseAudio (0);
/* Fill the audio DMA information block */
shm = &the_shm;
shm->splitbuffer = 0;
shm->samplebits = (obtained.format & 0xFF);
shm->speed = obtained.freq;
shm->channels = obtained.channels;
shm->samples = obtained.samples * shm->channels;
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = NULL;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
SDL_CloseAudio ();
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

@ -0,0 +1,311 @@
/*
snd_sgi.c
sound support for sgi
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
#include <limits.h>
#include <dmedia/audio.h>
#include "QF/console.h"
#include "QF/qtypes.h"
#include "QF/qargs.h"
#include "QF/sound.h"
static int snd_inited = 0;
static ALconfig alc;
static ALport alp;
static int tryrates[] = { 11025, 22050, 44100, 8000 };
static unsigned char *dma_buffer, *write_buffer;
static int bufsize;
static int wbufp;
static int framecount;
qboolean
SNDDMA_Init (void)
{
ALpv alpv;
int i;
char *s;
alc = alNewConfig ();
if (!alc) {
Con_Printf ("Could not make an new sound config: %s\n",
alGetErrorString (oserror ()));
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
/* get & probe settings */
/* sample format */
if (alSetSampFmt (alc, AL_SAMPFMT_TWOSCOMP) < 0) {
Con_Printf ("Could not sample format of default output to two's "
"complement\n");
alFreeConfig (alc);
return 0;
}
/* sample bits */
s = getenv ("QUAKE_SOUND_SAMPLEBITS");
if (s)
shm->samplebits = atoi (s);
else if ((i = COM_CheckParm ("-sndbits")) != 0)
shm->samplebits = atoi (com_argv[i + 1]);
if (shm->samplebits != 16 && shm->samplebits != 8) {
alpv.param = AL_WORDSIZE;
if (alGetParams (AL_DEFAULT_OUTPUT, &alpv, 1) < 0) {
Con_Printf ("Could not get supported wordsize of default "
"output: %s\n", alGetErrorString (oserror ()));
return 0;
}
if (alpv.value.i >= 16) {
shm->samplebits = 16;
} else {
if (alpv.value.i >= 8)
shm->samplebits = 8;
else {
Con_Printf ("Sound disabled since interface "
"doesn't even support 8 bit.");
alFreeConfig (alc);
return 0;
}
}
}
/* sample rate */
s = getenv ("QUAKE_SOUND_SPEED");
if (s)
shm->speed = atoi (s);
else if ((i = COM_CheckParm ("-sndspeed")) != 0)
shm->speed = atoi (com_argv[i + 1]);
else {
alpv.param = AL_RATE;
for (i = 0; i < sizeof (tryrates) / sizeof (int); i++) {
alpv.value.ll = alDoubleToFixed (tryrates[i]);
if (alSetParams (AL_DEFAULT_OUTPUT, &alpv, 1) >= 0)
break;
}
if (i >= sizeof (tryrates) / sizeof (int)) {
Con_Printf ("Sound disabled since interface doesn't even "
"support a sample rate of %d\n", tryrates[i - 1]);
alFreeConfig (alc);
return 0;
}
shm->speed = tryrates[i];
}
/* channels */
s = getenv ("QUAKE_SOUND_CHANNELS");
if (s)
shm->channels = atoi (s);
else if ((i = COM_CheckParm ("-sndmono")) != 0)
shm->channels = 1;
else if ((i = COM_CheckParm ("-sndstereo")) != 0)
shm->channels = 2;
else
shm->channels = 2;
/* set 'em */
/* channels */
while (shm->channels > 0) {
if (alSetChannels (alc, shm->channels) < 0) {
Con_Printf ("Unable to set number of channels to %d, trying half\n",
shm->channels);
shm->channels /= 2;
} else
break;
}
if (shm->channels <= 0) {
Con_Printf ("Sound disabled since interface doesn't even support 1 "
"channel\n");
alFreeConfig (alc);
return 0;
}
/* sample rate */
alpv.param = AL_RATE;
alpv.value.ll = alDoubleToFixed (shm->speed);
if (alSetParams (AL_DEFAULT_OUTPUT, &alpv, 1) < 0) {
Con_Printf ("Could not set samplerate of default output to %d: %s\n",
shm->speed, alGetErrorString (oserror ()));
alFreeConfig (alc);
return 0;
}
/* set sizes of buffers relative to sizes of those for ** the 'standard'
frequency of 11025 ** ** use *huge* buffers since at least my indigo2
has enough ** to do to get sound on the way anyway */
bufsize = 32768 * (int) ((double) shm->speed / 11025.0);
dma_buffer = malloc (bufsize);
if (dma_buffer == NULL) {
Con_Printf ("Could not get %d bytes of memory for audio dma buffer\n",
bufsize);
alFreeConfig (alc);
return 0;
}
write_buffer = malloc (bufsize);
if (write_buffer == NULL) {
Con_Printf ("Could not get %d bytes of memory for audio write buffer\n",
bufsize);
free (dma_buffer);
alFreeConfig (alc);
return 0;
}
/* sample bits */
switch (shm->samplebits) {
case 24:
i = AL_SAMPLE_24;
break;
case 16:
i = AL_SAMPLE_16;
break;
default:
i = AL_SAMPLE_8;
break;
}
if (alSetWidth (alc, i) < 0) {
Con_Printf ("Could not set wordsize of default output to %d: %s\n",
shm->samplebits, alGetErrorString (oserror ()));
free (write_buffer);
free (dma_buffer);
alFreeConfig (alc);
return 0;
}
alp = alOpenPort ("quakeforge", "w", alc);
if (!alp) {
Con_Printf ("Could not open sound port: %s\n",
alGetErrorString (oserror ()));
free (write_buffer);
free (dma_buffer);
alFreeConfig (alc);
return 0;
}
shm->soundalive = true;
shm->samples = bufsize / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = dma_buffer;
framecount = 0;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
/* Con_Printf("framecount: %d %d\n", (framecount * shm->channels) %
shm->samples, alGetFilled(alp)); */
shm->samplepos = ((framecount - alGetFilled (alp))
* shm->channels) % shm->samples;
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
free (write_buffer);
free (dma_buffer);
alClosePort (alp);
alFreeConfig (alc);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int bsize;
int bytes, b;
unsigned char *p;
int idx;
int stop = paintedtime;
if (paintedtime < wbufp)
wbufp = 0; // reset
bsize = shm->channels * (shm->samplebits / 8);
bytes = (paintedtime - wbufp) * bsize;
if (!bytes)
return;
if (bytes > bufsize) {
bytes = bufsize;
stop = wbufp + bytes / bsize;
}
p = write_buffer;
idx = (wbufp * bsize) & (bufsize - 1);
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (bufsize - 1);
}
wbufp = stop;
alWriteFrames (alp, write_buffer, bytes / bsize);
framecount += bytes / bsize;
}
/* end of file */

View file

@ -0,0 +1,228 @@
/*
snd_sun.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 1999,2000 contributors of the QuakeForge project
Please see the file "AUTHORS" for a list of contributors
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/audioio.h>
#include <errno.h>
#include "QF/qtypes.h"
#include "QF/sound.h"
#include "QF/qargs.h"
#include "QF/console.h"
int audio_fd;
int snd_inited;
static int wbufp;
static audio_info_t info;
#define BUFFER_SIZE 8192
unsigned char dma_buffer[BUFFER_SIZE];
unsigned char pend_buffer[BUFFER_SIZE];
int pending;
qboolean
SNDDMA_Init (void)
{
if (snd_inited) {
printf ("Sound already init'd\n");
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
audio_fd = open ("/dev/audio", O_WRONLY | O_NDELAY);
if (audio_fd < 0) {
if (errno == EBUSY) {
Con_Printf ("Audio device is being used by another process\n");
}
perror ("/dev/audio");
Con_Printf ("Could not open /dev/audio\n");
return (0);
}
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
return 0;
}
//
// set to nonblock
//
if (fcntl (audio_fd, F_SETFL, O_NONBLOCK) < 0) {
perror ("/dev/audio");
close (audio_fd);
return 0;
}
AUDIO_INITINFO (&info);
shm->speed = 11025;
// try 16 bit stereo
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 2;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 1;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
Con_Printf ("Incapable sound hardware.\n");
close (audio_fd);
return 0;
}
Con_Printf ("16 bit mono sound initialized\n");
shm->samplebits = 16;
shm->channels = 1;
} else { // 16 bit stereo
Con_Printf ("16 bit stereo sound initialized\n");
shm->samplebits = 16;
shm->channels = 2;
}
shm->soundalive = true;
shm->samples = sizeof (dma_buffer) / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return ((info.play.samples * shm->channels) % shm->samples);
}
int
SNDDMA_GetSamples (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return info.play.samples;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int bsize;
int bytes, b;
static unsigned char writebuf[1024];
unsigned char *p;
int idx;
int stop = paintedtime;
if (paintedtime < wbufp)
wbufp = 0; // reset
bsize = shm->channels * (shm->samplebits / 8);
bytes = (paintedtime - wbufp) * bsize;
if (!bytes)
return;
if (bytes > sizeof (writebuf)) {
bytes = sizeof (writebuf);
stop = wbufp + bytes / bsize;
}
p = writebuf;
idx = (wbufp * bsize) & (BUFFER_SIZE - 1);
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (BUFFER_SIZE - 1);
}
wbufp = stop;
if (write (audio_fd, writebuf, bytes) < bytes)
printf ("audio can't keep up!\n");
}

View file

@ -0,0 +1,725 @@
/*
snd_win.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define CINTERFACE
#include "winquake.h"
#include "QF/qargs.h"
#include "QF/console.h"
#include "QF/sound.h"
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
HRESULT (WINAPI * pDirectSoundCreate) (GUID FAR * lpGUID,
LPDIRECTSOUND FAR * lplpDS,
IUnknown FAR * pUnkOuter);
// 64K is > 1 second at 16-bit, 22050 Hz
#define WAV_BUFFERS 64
#define WAV_MASK 0x3F
#define WAV_BUFFER_SIZE 0x0400
#define SECONDARY_BUFFER_SIZE 0x10000
typedef enum { SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL } sndinitstat;
static qboolean wavonly;
static qboolean dsound_init;
static qboolean wav_init;
static qboolean snd_firsttime = true, snd_isdirect, snd_iswave;
static qboolean primary_format_set;
static int sample16;
static int snd_sent, snd_completed;
/*
* Global variables. Must be visible to window-procedure function
* so it can unlock and free the data block after it has been played.
*/
HANDLE hData;
HPSTR lpData, lpData2;
HGLOBAL hWaveHdr;
LPWAVEHDR lpWaveHdr;
HWAVEOUT hWaveOut;
WAVEOUTCAPS wavecaps;
DWORD gSndBufSize;
MMTIME mmstarttime;
LPDIRECTSOUND pDS;
LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
HINSTANCE hInstDS;
sndinitstat SNDDMA_InitDirect (void);
qboolean SNDDMA_InitWav (void);
/*
S_BlockSound
*/
void
S_BlockSound (void)
{
// DirectSound takes care of blocking itself
if (snd_iswave) {
snd_blocked++;
if (snd_blocked == 1)
waveOutReset (hWaveOut);
}
}
/*
S_UnblockSound
*/
void
S_UnblockSound (void)
{
// DirectSound takes care of blocking itself
if (snd_iswave) {
snd_blocked--;
}
}
/*
FreeSound
*/
void
FreeSound (void)
{
int i;
if (pDSBuf) {
IDirectSoundBuffer_Stop (pDSBuf);
IDirectSound_Release (pDSBuf);
}
// only release primary buffer if it's not also the mixing buffer we just released
if (pDSPBuf && (pDSBuf != pDSPBuf)) {
IDirectSound_Release (pDSPBuf);
}
if (pDS) {
IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL);
IDirectSound_Release (pDS);
}
if (hWaveOut) {
waveOutReset (hWaveOut);
if (lpWaveHdr) {
for (i = 0; i < WAV_BUFFERS; i++)
waveOutUnprepareHeader (hWaveOut, lpWaveHdr + i,
sizeof (WAVEHDR));
}
waveOutClose (hWaveOut);
if (hWaveHdr) {
GlobalUnlock (hWaveHdr);
GlobalFree (hWaveHdr);
}
if (hData) {
GlobalUnlock (hData);
GlobalFree (hData);
}
}
pDS = NULL;
pDSBuf = NULL;
pDSPBuf = NULL;
hWaveOut = 0;
hData = 0;
hWaveHdr = 0;
lpData = NULL;
lpWaveHdr = NULL;
dsound_init = false;
wav_init = false;
}
/*
SNDDMA_InitDirect
Direct-Sound support
*/
sndinitstat SNDDMA_InitDirect (void)
{
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
DWORD dwSize, dwWrite;
DSCAPS dscaps;
WAVEFORMATEX format, pformat;
HRESULT hresult;
int reps;
memset ((void *) &sn, 0, sizeof (sn));
shm = &sn;
shm->channels = 2;
shm->samplebits = 16;
shm->speed = 11025;
memset (&format, 0, sizeof (format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
if (!hInstDS) {
hInstDS = LoadLibrary ("dsound.dll");
if (hInstDS == NULL) {
Con_Printf ("Couldn't load dsound.dll\n");
return SIS_FAILURE;
}
pDirectSoundCreate =
(void *) GetProcAddress (hInstDS, "DirectSoundCreate");
if (!pDirectSoundCreate) {
Con_Printf ("Couldn't get DS proc addr\n");
return SIS_FAILURE;
}
}
while ((hresult = iDirectSoundCreate (NULL, &pDS, NULL)) != DS_OK) {
if (hresult != DSERR_ALLOCATED) {
Con_Printf ("DirectSound create failed\n");
return SIS_FAILURE;
}
Con_Printf ("DirectSoundCreate failure\n"
" hardware already in use\n");
return SIS_NOTAVAIL;
}
dscaps.dwSize = sizeof (dscaps);
if (DS_OK != IDirectSound_GetCaps (pDS, &dscaps)) {
Con_Printf ("Couldn't get DS caps\n");
}
if (dscaps.dwFlags & DSCAPS_EMULDRIVER) {
Con_Printf ("No DirectSound driver installed\n");
FreeSound ();
return SIS_FAILURE;
}
if (DS_OK !=
IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) {
Con_Printf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
memset (&dsbuf, 0, sizeof (dsbuf));
dsbuf.dwSize = sizeof (DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
memset (&dsbcaps, 0, sizeof (dsbcaps));
dsbcaps.dwSize = sizeof (dsbcaps);
primary_format_set = false;
if (!COM_CheckParm ("-snoforceformat")) {
if (DS_OK ==
IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSPBuf, NULL)) {
pformat = format;
if (DS_OK != IDirectSoundBuffer_SetFormat (pDSPBuf, &pformat)) {
} else
primary_format_set = true;
}
}
if (!primary_format_set || !COM_CheckParm ("-primarysound")) {
// create the secondary buffer we'll actually work with
memset (&dsbuf, 0, sizeof (dsbuf));
dsbuf.dwSize = sizeof (DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
dsbuf.lpwfxFormat = &format;
memset (&dsbcaps, 0, sizeof (dsbcaps));
dsbcaps.dwSize = sizeof (dsbcaps);
if (DS_OK !=
IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSBuf, NULL)) {
Con_Printf ("DS:CreateSoundBuffer Failed");
FreeSound ();
return SIS_FAILURE;
}
shm->channels = format.nChannels;
shm->samplebits = format.wBitsPerSample;
shm->speed = format.nSamplesPerSec;
if (DS_OK != IDirectSound_GetCaps (pDSBuf, &dsbcaps)) {
Con_Printf ("DS:GetCaps failed\n");
FreeSound ();
return SIS_FAILURE;
}
} else {
if (DS_OK !=
IDirectSound_SetCooperativeLevel (pDS, mainwindow,
DSSCL_WRITEPRIMARY)) {
Con_Printf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (DS_OK != IDirectSound_GetCaps (pDSPBuf, &dsbcaps)) {
Con_Printf ("DS:GetCaps failed\n");
return SIS_FAILURE;
}
pDSBuf = pDSPBuf;
}
// Make sure mixer is active
IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);
gSndBufSize = dsbcaps.dwBufferBytes;
// initialize the buffer
reps = 0;
while ((hresult = IDirectSoundBuffer_Lock (pDSBuf, 0, gSndBufSize,
(LPVOID *) & lpData, &dwSize,
NULL, NULL, 0)) != DS_OK) {
if (hresult != DSERR_BUFFERLOST) {
Con_Printf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (++reps > 10000) {
Con_Printf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
FreeSound ();
return SIS_FAILURE;
}
}
memset (lpData, 0, dwSize);
// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging
IDirectSoundBuffer_Unlock (pDSBuf, lpData, dwSize, NULL, 0);
/* we don't want anyone to access the buffer directly w/o locking it
first. */
lpData = NULL;
IDirectSoundBuffer_Stop (pDSBuf);
IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmstarttime.u.sample,
&dwWrite);
IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = gSndBufSize / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits / 8) - 1;
dsound_init = true;
return SIS_SUCCESS;
}
/*
SNDDM_InitWav
Crappy windows multimedia base
*/
qboolean
SNDDMA_InitWav (void)
{
WAVEFORMATEX format;
int i;
HRESULT hr;
snd_sent = 0;
snd_completed = 0;
shm = &sn;
shm->channels = 2;
shm->samplebits = 16;
shm->speed = 11025;
memset (&format, 0, sizeof (format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
/* Open a waveform device for output using window callback. */
while ((hr = waveOutOpen ((LPHWAVEOUT) & hWaveOut, WAVE_MAPPER,
&format, 0, 0L,
CALLBACK_NULL)) != MMSYSERR_NOERROR) {
if (hr != MMSYSERR_ALLOCATED) {
Con_Printf ("waveOutOpen failed\n");
return false;
}
Con_Printf ("waveOutOpen failure;\n" " hardware already in use\n");
return false;
}
/*
* Allocate and lock memory for the waveform data. The memory
* for waveform data must be globally allocated with
* GMEM_MOVEABLE and GMEM_SHARE flags.
*/
gSndBufSize = WAV_BUFFERS * WAV_BUFFER_SIZE;
hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
if (!hData) {
Con_Printf ("Sound: Out of memory.\n");
FreeSound ();
return false;
}
lpData = GlobalLock (hData);
if (!lpData) {
Con_Printf ("Sound: Failed to lock.\n");
FreeSound ();
return false;
}
memset (lpData, 0, gSndBufSize);
/*
* Allocate and lock memory for the header. This memory must
* also be globally allocated with GMEM_MOVEABLE and
* GMEM_SHARE flags.
*/
hWaveHdr = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE,
(DWORD) sizeof (WAVEHDR) * WAV_BUFFERS);
if (hWaveHdr == NULL) {
Con_Printf ("Sound: Failed to Alloc header.\n");
FreeSound ();
return false;
}
lpWaveHdr = (LPWAVEHDR) GlobalLock (hWaveHdr);
if (lpWaveHdr == NULL) {
Con_Printf ("Sound: Failed to lock header.\n");
FreeSound ();
return false;
}
memset (lpWaveHdr, 0, sizeof (WAVEHDR) * WAV_BUFFERS);
/* After allocation, set up and prepare headers. */
for (i = 0; i < WAV_BUFFERS; i++) {
lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
lpWaveHdr[i].lpData = lpData + i * WAV_BUFFER_SIZE;
if (waveOutPrepareHeader (hWaveOut, lpWaveHdr + i, sizeof (WAVEHDR)) !=
MMSYSERR_NOERROR) {
Con_Printf ("Sound: failed to prepare wave headers\n");
FreeSound ();
return false;
}
}
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = gSndBufSize / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits / 8) - 1;
wav_init = true;
return true;
}
/*
SNDDMA_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
*/
qboolean
SNDDMA_Init (void)
{
sndinitstat stat;
if (COM_CheckParm ("-wavonly"))
wavonly = true;
dsound_init = wav_init = 0;
stat = SIS_FAILURE; // assume DirectSound won't
// initialize
/* Init DirectSound */
if (!wavonly) {
if (snd_firsttime || snd_isdirect) {
stat = SNDDMA_InitDirect ();;
if (stat == SIS_SUCCESS) {
snd_isdirect = true;
if (snd_firsttime)
Con_Printf ("DirectSound initialized\n");
} else {
snd_isdirect = false;
Con_Printf ("DirectSound failed to init\n");
}
}
}
// if DirectSound didn't succeed in initializing, try to initialize
// waveOut sound, unless DirectSound failed because the hardware is
// already allocated (in which case the user has already chosen not
// to have sound)
if (!dsound_init && (stat != SIS_NOTAVAIL)) {
if (snd_firsttime || snd_iswave) {
snd_iswave = SNDDMA_InitWav ();
if (snd_iswave) {
if (snd_firsttime)
Con_Printf ("Wave sound initialized\n");
} else {
Con_Printf ("Wave sound failed to init\n");
}
}
}
snd_firsttime = false;
if (!dsound_init && !wav_init) {
if (snd_firsttime)
Con_Printf ("No sound device initialized\n");
return 0;
}
return 1;
}
/*
SNDDMA_GetDMAPos
return the current sample position (in mono samples read)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
*/
int
SNDDMA_GetDMAPos (void)
{
MMTIME mmtime;
int s = 0;
DWORD dwWrite;
if (dsound_init) {
mmtime.wType = TIME_SAMPLES;
IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmtime.u.sample,
&dwWrite);
s = mmtime.u.sample - mmstarttime.u.sample;
} else if (wav_init) {
s = snd_sent * WAV_BUFFER_SIZE;
}
s >>= sample16;
s &= (shm->samples - 1);
return s;
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
LPWAVEHDR h;
int wResult;
if (!wav_init)
return;
//
// find which sound blocks have completed
//
while (1) {
if (snd_completed == snd_sent) {
Con_DPrintf ("Sound overrun\n");
break;
}
if (!(lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE)) {
break;
}
snd_completed++; // this buffer has been played
}
//
// submit two new sound blocks
//
while (((snd_sent - snd_completed) >> sample16) < 4) {
h = lpWaveHdr + (snd_sent & WAV_MASK);
snd_sent++;
/*
* Now the data block can be sent to the output device. The
* waveOutWrite function returns immediately and waveform
* data is sent to the output device in the background.
*/
wResult = waveOutWrite (hWaveOut, h, sizeof (WAVEHDR));
if (wResult != MMSYSERR_NOERROR) {
Con_Printf ("Failed to write block to device\n");
FreeSound ();
return;
}
}
}
/*
SNDDMA_Shutdown
Reset the sound device for exiting
*/
void
SNDDMA_Shutdown (void)
{
FreeSound ();
}
DWORD *
DSOUND_LockBuffer (qboolean lockit)
{
int reps;
static DWORD dwSize;
static DWORD dwSize2;
static DWORD *pbuf1;
static DWORD *pbuf2;
HRESULT hresult;
if (!pDSBuf)
return NULL;
if (lockit) {
reps = 0;
while ((hresult = IDirectSoundBuffer_Lock (pDSBuf, 0, gSndBufSize,
(LPVOID *) & pbuf1, &dwSize,
(LPVOID *) & pbuf2, &dwSize2,
0)) != DS_OK) {
if (hresult != DSERR_BUFFERLOST) {
Con_Printf
("S_TransferStereo16: DS::Lock Sound Buffer Failed\n");
S_Shutdown ();
S_Startup ();
return NULL;
}
if (++reps > 10000) {
Con_Printf
("S_TransferStereo16: DS: couldn't restore buffer\n");
S_Shutdown ();
S_Startup ();
return NULL;
}
}
} else {
IDirectSoundBuffer_Unlock (pDSBuf, pbuf1, dwSize, NULL, 0);
pbuf1 = NULL;
pbuf2 = NULL;
dwSize = 0;
dwSize2 = 0;
}
return (pbuf1);
}
void
DSOUND_ClearBuffer (int clear)
{
DWORD *pData;
// FIXME: this should be called with 2nd pbuf2 = NULL, dwsize =0
pData = DSOUND_LockBuffer (true);
memset (pData, clear, shm->samples * shm->samplebits / 8);
DSOUND_LockBuffer (false);
}
void
DSOUND_Restore (void)
{
// if the buffer was lost or stopped, restore it and/or restart it
DWORD dwStatus;
if (!pDSBuf)
return;
if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DD_OK)
Con_Printf ("Couldn't get sound buffer status\n");
if (dwStatus & DSBSTATUS_BUFFERLOST)
IDirectSoundBuffer_Restore (pDSBuf);
if (!(dwStatus & DSBSTATUS_PLAYING))
IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);
return;
}

View file

@ -38,14 +38,13 @@ bin_PROGRAMS = @NQ_TARGETS@
EXTRA_PROGRAMS= nq-3dfx nq-fbdev nq-glx nq-mgl nq-sdl \
nq-sgl nq-svga nq-wgl nq-x11 nq-server
noinst_LIBRARIES= libqfsys.a libqfsnd.a libqfjs.a libqfnet.a
noinst_LIBRARIES= libqfsys.a libqfjs.a libqfnet.a
#if ASM_ARCH
math_ASM= cl_math.S
soft_ASM= d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S \
d_varsa.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S sw_redgea.S sw_rvarsa.S \
surf16.S surf8.S
sound_ASM= snd_mixa.S
common_ASM= sys_ia32.S worlda.S $(math_ASM)
#endif
@ -64,34 +63,6 @@ libqfsys_a_SOURCES= sys_unix.c
endif
EXTRA_libqfsys_a_SOURCES= dirent.c fnmatch.c sys_unix.c sys_win.c
#
# ... Digital audio
#
if SNDTYPE_ALSA_0_5
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c $(sound_ASM)
endif
if SNDTYPE_ALSA_0_9
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_9.c $(sound_ASM)
endif
if SNDTYPE_MME
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_mme.c $(sound_ASM)
endif
if SNDTYPE_OSS
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_oss.c $(sound_ASM)
endif
if SNDTYPE_SUN
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sun.c $(sound_ASM)
endif
if SNDTYPE_WIN32
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_win.c $(sound_ASM)
endif
if SNDTYPE_NULL
libqfsnd_a_SOURCES= snd_null.c $(sound_ASM)
endif
EXTRA_libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c \
snd_alsa_0_9.c snd_oss.c snd_sun.c snd_win.c snd_null.c \
$(sound_ASM)
#
# ... Joystick
#
@ -116,8 +87,9 @@ EXTRA_libqfnet_a_SOURCES=net_dos.c net_bw.c net_ipx.c net_mp.c net_ser.c \
client_LIBS= $(top_builddir)/libs/gamecode/libQFgamecode.la \
$(top_builddir)/libs/util/libQFutil.la \
$(top_builddir)/libs/audio/cd/libQFcd.la \
-L. -lqfsys -lqfsnd -lqfjs -lqfnet $(SOUND_LIBS) $(NET_LIBS)
client_LIB_DEPS= libqfsys.a libqfsnd.a libqfjs.a libqfnet.a
$(top_builddir)/libs/audio/targets/libQFsound.la \
-L. -lqfsys -lqfjs -lqfnet $(SOUND_LIBS) $(NET_LIBS)
client_LIB_DEPS= libqfsys.a libqfjs.a libqfnet.a
client_SOURCES= cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_parse.c \
cl_tent.c console.c keys.c sbar.c r_part.c r_view.c \

View file

@ -223,6 +223,8 @@ CL_KeepaliveMessage (void)
SZ_Clear (&cls.message);
}
struct model_s *snd_worldmodel;
/*
==================
CL_ParseServerInfo
@ -326,6 +328,7 @@ CL_ParseServerInfo (void)
// local state
cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
snd_worldmodel = cl.worldmodel;
R_NewMap ();
@ -703,6 +706,7 @@ CL_ParseStaticSound (void)
#define SHOWNET(x) if(cl_shownet->int_val==2)Con_Printf ("%3i:%s\n", net_message->readcount-1, x);
int snd_viewentity;
/*
=====================
CL_ParseServerMessage
@ -806,6 +810,7 @@ CL_ParseServerMessage (void)
case svc_setview:
cl.viewentity = MSG_ReadShort (net_message);
snd_viewentity = cl.viewentity; // FIXME: evil hack
break;
case svc_lightstyle:

262
qw/include/bspfile.h Normal file
View file

@ -0,0 +1,262 @@
/*
bspfile.h
BSP (Binary Space Partitioning) file definitions
Copyright (C) 1996-1997 Id Software, Inc.
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __bspfile_h_
#define __bspfile_h_
#include "QF/qtypes.h"
#include "QF/sound.h"
// upper design bounds
#define MAX_MAP_HULLS 4
#define MAX_MAP_MODELS 256
#define MAX_MAP_BRUSHES 4096
#define MAX_MAP_ENTITIES 1024
#define MAX_MAP_ENTSTRING 65536
#define MAX_MAP_PLANES 8192
#define MAX_MAP_NODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 32767 //
#define MAX_MAP_LEAFS 32767 //
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
#define MAX_MAP_TEXINFO 4096
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_MIPTEX 0x200000
#define MAX_MAP_LIGHTING 0x100000
#define MAX_MAP_VISIBILITY 0x100000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
#define BSPVERSION 29
typedef struct {
int fileofs;
int filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_TEXTURES 2
#define LUMP_VERTEXES 3
#define LUMP_VISIBILITY 4
#define LUMP_NODES 5
#define LUMP_TEXINFO 6
#define LUMP_FACES 7
#define LUMP_LIGHTING 8
#define LUMP_CLIPNODES 9
#define LUMP_LEAFS 10
#define LUMP_MARKSURFACES 11
#define LUMP_EDGES 12
#define LUMP_SURFEDGES 13
#define LUMP_MODELS 14
#define HEADER_LUMPS 15
typedef struct {
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} dmodel_t;
typedef struct {
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct {
int nummiptex;
int dataofs[4]; // [nummiptex]
} dmiptexlump_t;
#define MIPLEVELS 4
typedef struct miptex_s {
char name[16];
unsigned int width, height;
unsigned int offsets[MIPLEVELS]; // four mip maps stored
} miptex_t;
typedef struct {
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
typedef struct {
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
#define CONTENTS_EMPTY -1
#define CONTENTS_SOLID -2
#define CONTENTS_WATER -3
#define CONTENTS_SLIME -4
#define CONTENTS_LAVA -5
#define CONTENTS_SKY -6
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct {
int planenum;
short children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct {
int planenum;
short children[2]; // negative numbers are contents
} dclipnode_t;
typedef struct texinfo_s {
float vecs[2][4]; // [s/t][xyz offset]
int miptex;
int flags;
} texinfo_t;
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct {
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct {
short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct {
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
byte ambient_level[NUM_AMBIENTS];
} dleaf_t;
//============================================================================
#ifndef QUAKE_GAME
// the utilities get to be lazy and just use large static arrays
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int visdatasize;
extern byte dvisdata[MAX_MAP_VISIBILITY];
extern int lightdatasize;
extern byte dlightdata[MAX_MAP_LIGHTING];
extern int texdatasize;
extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
extern int entdatasize;
extern char dentdata[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t dleafs[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t dvertexes[MAX_MAP_VERTS];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern int numtexinfo;
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
extern int numfaces;
extern dface_t dfaces[MAX_MAP_FACES];
extern int numclipnodes;
extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES];
extern int numedges;
extern dedge_t dedges[MAX_MAP_EDGES];
extern int nummarksurfaces;
extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES];
extern int numsurfedges;
extern int dsurfedges[MAX_MAP_SURFEDGES];
void LoadBSPFile (char *filename);
void WriteBSPFile (char *filename);
void PrintBSPFileSizes (void);
#endif
#endif // __bspfile_h_

View file

@ -40,7 +40,7 @@ EXTRA_PROGRAMS= qw-client-3dfx qw-client-fbdev \
qw-client-sgl qw-client-svga qw-client-wgl \
qw-client-x11 qw-server
noinst_LIBRARIES= libqfjs.a libqfnet.a libqfsnd.a libqfsys_cl.a libqfsys_sv.a
noinst_LIBRARIES= libqfjs.a libqfnet.a libqfsys_cl.a libqfsys_sv.a
if PACKETLOG
packetlogger = net_packetlog.c
@ -103,40 +103,6 @@ libqfsys_cl_a_SOURCES= cl_sys_unix.c
endif
EXTRA_libqfsys_cl_a_SOURCES= cl_sys_sdl.c cl_sys_unix.c cl_sys_win.c sys_win.c fnmatch.c dirent.c
#
# ... Digital audio
#
if SNDTYPE_ALSA_0_5
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c
endif
if SNDTYPE_ALSA_0_9
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_9.c
endif
if SNDTYPE_MME
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_mme.c
endif
if SNDTYPE_OSS
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_oss.c
endif
if SNDTYPE_SDL
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sdl.c
endif
if SNDTYPE_SGI
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sgi.c
endif
if SNDTYPE_SUN
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_sun.c
endif
if SNDTYPE_WIN32
libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_win.c
endif
if SNDTYPE_NULL
libqfsnd_a_SOURCES= snd_null.c
endif
EXTRA_libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c \
snd_alsa_0_9.c snd_oss.c snd_sdl.c snd_sgi.c \
snd_sun.c snd_win.c snd_null.c
#
# ... Joystick
#
@ -155,12 +121,13 @@ EXTRA_libqfjs_a_SOURCES= joy_linux.c joy_win.c joy_null.c
CLIENT_LIBS= $(top_builddir)/libs/util/libQFutil.la \
$(top_builddir)/libs/gamecode/libQFgamecode.la \
$(top_builddir)/libs/audio/cd/libQFcd.la \
-L. -lqfnet -lqfsys_cl -lqfsnd -lqfjs \
$(top_builddir)/libs/audio/targets/libQFsound.la \
-L. -lqfnet -lqfsys_cl -lqfjs \
$(SOUND_LIBS) $(NET_LIBS) $(JOY_LIBS)
CLIENT_LIB_DEPS= libqfnet.a libqfsys_cl.a libqfsnd.a libqfjs.a
CLIENT_LIB_DEPS= libqfnet.a libqfsys_cl.a libqfjs.a
if ASM_ARCH
client_ASM= snd_mixa.S cl_math.S
client_ASM= cl_math.S
endif
client_SOURCES= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \

View file

@ -249,6 +249,7 @@ CL_CheckOrDownloadFile (char *filename)
return false;
}
struct model_s *snd_worldmodel;
/*
Model_NextDownload
*/
@ -301,6 +302,9 @@ Model_NextDownload (void)
// all done
cl.worldmodel = cl.model_precache[1];
// FIXME: evil hack for sound
snd_worldmodel = cl.worldmodel;
R_NewMap ();
Team_NewMap ();
Hunk_Check (); // make sure nothing is hurt
@ -595,6 +599,10 @@ void Draw_ClearCache (void);
void CL_ClearBaselines (void); // LordHavoc: BIG BUG-FIX!
// FIXME: Evil hack that doesn't deserve to see the light of day.
// (pending merge of nq and qw client_stat_t's)
int snd_viewentity;
/*
CL_ParseServerData
*/
@ -658,8 +666,9 @@ CL_ParseServerData (void)
cl.playernum &= ~128;
}
// evil hack so NQ and QW can share sound code
// FIXME: evil hack so NQ and QW can share sound code
cl.viewentity = cl.playernum + 1;
snd_viewentity = cl.playernum + 1;
// get the full level name
str = MSG_ReadString (net_message);