mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Move sound targets into a library. Still doesn't pick one at runtime though.
This commit is contained in:
parent
27d177f978
commit
69022c7ffb
23 changed files with 6346 additions and 72 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS= cd
|
||||
SUBDIRS= cd targets
|
||||
|
||||
clean-local:
|
||||
rm -f *.a
|
||||
|
|
41
libs/audio/targets/Makefile.am
Normal file
41
libs/audio/targets/Makefile.am
Normal 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@
|
358
libs/audio/targets/snd_alsa_0_5.c
Normal file
358
libs/audio/targets/snd_alsa_0_5.c
Normal 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 (¶ms, 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, ¶ms)) < 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;
|
||||
}
|
||||
}
|
313
libs/audio/targets/snd_alsa_0_9.c
Normal file
313
libs/audio/targets/snd_alsa_0_9.c
Normal 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;
|
||||
}
|
||||
}
|
108
libs/audio/targets/snd_disk.c
Normal file
108
libs/audio/targets/snd_disk.c
Normal 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
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
1281
libs/audio/targets/snd_gus.c
Normal file
File diff suppressed because it is too large
Load diff
405
libs/audio/targets/snd_mem.c
Normal file
405
libs/audio/targets/snd_mem.c
Normal 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;
|
||||
}
|
429
libs/audio/targets/snd_mix.c
Normal file
429
libs/audio/targets/snd_mix.c
Normal 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;
|
||||
}
|
||||
}
|
232
libs/audio/targets/snd_mixa.S
Normal file
232
libs/audio/targets/snd_mixa.S
Normal 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
|
||||
|
145
libs/audio/targets/snd_null.c
Normal file
145
libs/audio/targets/snd_null.c
Normal 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)
|
||||
{
|
||||
}
|
297
libs/audio/targets/snd_oss.c
Normal file
297
libs/audio/targets/snd_oss.c
Normal 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)
|
||||
{
|
||||
}
|
158
libs/audio/targets/snd_sdl.c
Normal file
158
libs/audio/targets/snd_sdl.c
Normal 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)
|
||||
{
|
||||
}
|
311
libs/audio/targets/snd_sgi.c
Normal file
311
libs/audio/targets/snd_sgi.c
Normal 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 */
|
228
libs/audio/targets/snd_sun.c
Normal file
228
libs/audio/targets/snd_sun.c
Normal 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");
|
||||
|
||||
}
|
725
libs/audio/targets/snd_win.c
Normal file
725
libs/audio/targets/snd_win.c
Normal 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;
|
||||
}
|
|
@ -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 \
|
||||
|
|
|
@ -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
262
qw/include/bspfile.h
Normal 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_
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue