Removed old files

This commit is contained in:
Adam Olsen 2001-04-10 09:44:36 +00:00
parent 69022c7ffb
commit dcd924c355
30 changed files with 0 additions and 12733 deletions

View file

@ -1,358 +0,0 @@
/*
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 "sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void*)-1)
#endif
static int snd_inited;
static snd_pcm_t *pcm_handle;
static struct snd_pcm_channel_info cinfo;
static struct snd_pcm_channel_params params;
static struct snd_pcm_channel_setup setup;
static snd_pcm_mmap_control_t *mmap_control = NULL;
static char *mmap_data = NULL;
static int card = -1, dev = -1;
int
check_card (int card)
{
snd_ctl_t *handle;
snd_ctl_hw_info_t info;
int rc;
if ((rc = snd_ctl_open (&handle, card)) < 0) {
Con_Printf ("Error: control open (%i): %s\n", card, snd_strerror (rc));
return rc;
}
if ((rc = snd_ctl_hw_info (handle, &info)) < 0) {
Con_Printf ("Error: control hardware info (%i): %s\n", card,
snd_strerror (rc));
snd_ctl_close (handle);
return rc;
}
snd_ctl_close (handle);
if (dev == -1) {
for (dev = 0; dev < info.pcmdevs; dev++) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
} else {
if (dev >= 0 && dev < info.pcmdevs) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
}
return 1;
}
qboolean
SNDDMA_Init (void)
{
int rc = 0, i;
char *err_msg = "";
int rate = -1, format = -1, bps, stereo = -1, frag_size;
unsigned int mask;
mask = snd_cards_mask ();
if (!mask) {
Con_Printf ("No sound cards detected\n");
return 0;
}
if (snd_device->string[0]) {
sscanf (snd_device->string, "%d,%d", &card, &dev);
}
if (snd_bits->int_val) {
i = snd_bits->int_val;
if (i == 16) {
format = SND_PCM_SFMT_S16_LE;
} else if (i == 8) {
format = SND_PCM_SFMT_U8;
} else {
Con_Printf ("Error: invalid sample bits: %d\n", i);
return 0;
}
}
if (snd_rate->int_val) {
rate = snd_rate->int_val;
if (rate != 44100 && rate != 22050 && rate != 11025) {
Con_Printf ("Error: invalid sample rate: %d\n", rate);
return 0;
}
}
stereo = snd_stereo->int_val;
if (card == -1) {
for (card = 0; card < SND_CARDS; card++) {
if (!(mask & (1 << card)))
continue;
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
}
} else {
if (dev == -1) {
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
} else {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) < 0) {
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
}
goto dev_openned;
}
}
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
dev_openned:
Con_Printf ("Using card %d, device %d.\n", card, dev);
memset (&cinfo, 0, sizeof (cinfo));
cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
snd_pcm_channel_info (pcm_handle, &cinfo);
Con_Printf ("%08x %08x %08x\n", cinfo.flags, cinfo.formats, cinfo.rates);
if ((rate == -1 || rate == 44100) && cinfo.rates & SND_PCM_RATE_44100) {
rate = 44100;
frag_size = 512; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 22050)
&& cinfo.rates & SND_PCM_RATE_22050) {
rate = 22050;
frag_size = 256; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 11025)
&& cinfo.rates & SND_PCM_RATE_11025) {
rate = 11025;
frag_size = 128; /* assuming stereo 8 bit */
} else {
Con_Printf ("ALSA: desired rates not supported\n");
goto error_2;
}
if ((format == -1 || format == SND_PCM_SFMT_S16_LE)
&& cinfo.formats & SND_PCM_FMT_S16_LE) {
format = SND_PCM_SFMT_S16_LE;
bps = 16;
frag_size *= 2;
} else if ((format == -1 || format == SND_PCM_SFMT_U8)
&& cinfo.formats & SND_PCM_FMT_U8) {
format = SND_PCM_SFMT_U8;
bps = 8;
} else {
Con_Printf ("ALSA: desired formats not supported\n");
goto error_2;
}
if (stereo && cinfo.max_voices >= 2) {
stereo = 1;
} else {
stereo = 0;
frag_size /= 2;
}
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio munmap";
if ((rc = snd_pcm_munmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
goto error;
memset (&params, 0, sizeof (params));
params.channel = SND_PCM_CHANNEL_PLAYBACK;
params.mode = SND_PCM_MODE_BLOCK;
params.format.interleave = 1;
params.format.format = format;
params.format.rate = rate;
params.format.voices = stereo + 1;
params.start_mode = SND_PCM_START_GO;
params.stop_mode = SND_PCM_STOP_ROLLOVER;
params.buf.block.frag_size = frag_size;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = -1;
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio params";
if ((rc = snd_pcm_channel_params (pcm_handle, &params)) < 0)
goto error;
err_msg = "audio mmap";
if (
(rc =
snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
(void **) &mmap_data)) < 0)
goto error;
err_msg = "audio prepare";
if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
0) goto error;
memset (&setup, 0, sizeof (setup));
setup.mode = SND_PCM_MODE_BLOCK;
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
err_msg = "audio setup";
if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
goto error;
shm = &sn;
memset ((dma_t *) shm, 0, sizeof (*shm));
shm->splitbuffer = 0;
shm->channels = setup.format.voices;
shm->submission_chunk = 128; // don't mix less than this #
shm->samplepos = 0; // in mono samples
shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
shm->samples =
setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8); // mono
//
// samples
// in
// buffer
shm->speed = setup.format.rate;
shm->buffer = (unsigned char *) mmap_data;
Con_Printf ("%5d stereo\n", shm->channels - 1);
Con_Printf ("%5d samples\n", shm->samples);
Con_Printf ("%5d samplepos\n", shm->samplepos);
Con_Printf ("%5d samplebits\n", shm->samplebits);
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf ("%5d speed\n", shm->speed);
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
Con_Printf ("%5d total_channels\n", total_channels);
snd_inited = 1;
return 1;
error:
Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
error_2:
snd_pcm_close (pcm_handle);
return 0;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return 0;
shm->samplepos =
(mmap_control->status.frag_io +
1) * setup.buf.block.frag_size / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
snd_pcm_close (pcm_handle);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int count = paintedtime - soundtime;
int i, s, e;
int rc;
count += setup.buf.block.frag_size - 1;
count /= setup.buf.block.frag_size;
s = soundtime / setup.buf.block.frag_size;
e = s + count;
for (i = s; i < e; i++)
mmap_control->fragments[i % setup.buf.block.frags].data = 1;
switch (mmap_control->status.status) {
case SND_PCM_STATUS_PREPARED:
if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK))
< 0) {
fprintf (stderr, "unable to start playback. %s\n",
snd_strerror (rc));
exit (1);
}
break;
case SND_PCM_STATUS_RUNNING:
break;
case SND_PCM_STATUS_UNDERRUN:
if (
(rc =
snd_pcm_plugin_prepare (pcm_handle,
SND_PCM_CHANNEL_PLAYBACK)) < 0) {
fprintf (stderr,
"underrun: playback channel prepare error. %s\n",
snd_strerror (rc));
exit (1);
}
break;
default:
break;
}
}

View file

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

View file

@ -1,108 +0,0 @@
/*
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 "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);
}

File diff suppressed because it is too large Load diff

View file

@ -1,648 +0,0 @@
/*
snd_dos.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 "dosisms.h"
int BLASTER_GetDMAPos (void);
/*
===============================================================================
GUS SUPPORT
===============================================================================
*/
qboolean GUS_Init (void);
int GUS_GetDMAPos (void);
void GUS_Shutdown (void);
/*
===============================================================================
BLASTER SUPPORT
===============================================================================
*/
short *dma_buffer = 0;
static int dma_size;
static int dma;
static int dsp_port;
static int irq;
static int low_dma;
static int high_dma;
static int mixer_port;
static int mpu401_port;
int dsp_version;
int dsp_minor_version;
int timeconstant = -1;
void
PrintBits (byte b)
{
int i;
char str[9];
for (i = 0; i < 8; i++)
str[i] = '0' + ((b & (1 << (7 - i))) > 0);
str[8] = 0;
Con_Printf ("%s (%i)", str, b);
}
void
SB_Info_f (void)
{
Con_Printf ("BLASTER=%s\n", getenv ("BLASTER"));
Con_Printf ("dsp version=%d.%d\n", dsp_version, dsp_minor_version);
Con_Printf ("dma=%d\n", dma);
if (timeconstant != -1)
Con_Printf ("timeconstant=%d\n", timeconstant);
Con_Printf ("dma position:%i\n", BLASTER_GetDMAPos ());
}
// =======================================================================
// Interprets BLASTER variable
// =======================================================================
int
GetBLASTER (void)
{
char *BLASTER;
char *param;
BLASTER = getenv ("BLASTER");
if (!BLASTER)
return 0;
param = strchr (BLASTER, 'A');
if (!param)
param = strchr (BLASTER, 'a');
if (!param)
return 0;
sscanf (param + 1, "%x", &dsp_port);
param = strchr (BLASTER, 'I');
if (!param)
param = strchr (BLASTER, 'i');
if (!param)
return 0;
sscanf (param + 1, "%d", &irq);
param = strchr (BLASTER, 'D');
if (!param)
param = strchr (BLASTER, 'd');
if (!param)
return 0;
sscanf (param + 1, "%d", &low_dma);
param = strchr (BLASTER, 'H');
if (!param)
param = strchr (BLASTER, 'h');
if (param)
sscanf (param + 1, "%d", &high_dma);
param = strchr (BLASTER, 'M');
if (!param)
param = strchr (BLASTER, 'm');
if (param)
sscanf (param + 1, "%x", &mixer_port);
else
mixer_port = dsp_port;
param = strchr (BLASTER, 'P');
if (!param)
param = strchr (BLASTER, 'p');
if (param)
sscanf (param + 1, "%x", &mpu401_port);
return 1;
}
// ==================================================================
// Resets DSP. Returns 0 on success.
// ==================================================================
int
ResetDSP (void)
{
volatile int i;
dos_outportb (dsp_port + 6, 1);
for (i = 65536; i; i--);
dos_outportb (dsp_port + 6, 0);
for (i = 65536; i; i--) {
if (!(dos_inportb (dsp_port + 0xe) & 0x80))
continue;
if (dos_inportb (dsp_port + 0xa) == 0xaa)
break;
}
if (i)
return 0;
else
return 1;
}
int
ReadDSP (void)
{
while (!(dos_inportb (dsp_port + 0xe) & 0x80));
return dos_inportb (dsp_port + 0xa);
}
void
WriteDSP (int val)
{
while ((dos_inportb (dsp_port + 0xc) & 0x80));
dos_outportb (dsp_port + 0xc, val);
}
int
ReadMixer (int addr)
{
dos_outportb (mixer_port + 4, addr);
return dos_inportb (mixer_port + 5);
}
void
WriteMixer (int addr, int val)
{
dos_outportb (mixer_port + 4, addr);
dos_outportb (mixer_port + 5, val);
}
int oldmixervalue;
/*
================
StartSB
================
*/
void
StartSB (void)
{
int i;
// version 4.xx startup code
if (dsp_version >= 4) {
Con_Printf ("Version 4 SB startup\n");
WriteDSP (0xd1); // turn on speaker
WriteDSP (0x41);
WriteDSP (shm->speed >> 8);
WriteDSP (shm->speed & 0xff);
WriteDSP (0xb6); // 16-bit output
WriteDSP (0x30); // stereo
WriteDSP ((shm->samples - 1) & 0xff); // # of samples - 1
WriteDSP ((shm->samples - 1) >> 8);
}
// version 3.xx startup code
else if (dsp_version == 3) {
Con_Printf ("Version 3 SB startup\n");
WriteDSP (0xd1); // turn on speaker
oldmixervalue = ReadMixer (0xe);
WriteMixer (0xe, oldmixervalue | 0x2); // turn on stereo
WriteDSP (0x14); // send one byte
WriteDSP (0x0);
WriteDSP (0x0);
for (i = 0; i < 0x10000; i++)
dos_inportb (dsp_port + 0xe); // ack the dsp
timeconstant = 65536 - (256000000 / (shm->channels * shm->speed));
WriteDSP (0x40);
WriteDSP (timeconstant >> 8);
WriteMixer (0xe, ReadMixer (0xe) | 0x20); // turn off filter
WriteDSP (0x48);
WriteDSP ((shm->samples - 1) & 0xff); // # of samples - 1
WriteDSP ((shm->samples - 1) >> 8);
WriteDSP (0x90); // high speed 8 bit stereo
}
// normal speed mono
else {
Con_Printf ("Version 2 SB startup\n");
WriteDSP (0xd1); // turn on speaker
timeconstant = 65536 - (256000000 / (shm->channels * shm->speed));
WriteDSP (0x40);
WriteDSP (timeconstant >> 8);
WriteDSP (0x48);
WriteDSP ((shm->samples - 1) & 0xff); // # of samples - 1
WriteDSP ((shm->samples - 1) >> 8);
WriteDSP (0x1c); // normal speed 8 bit mono
}
}
static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
static int mode_reg;
static int flipflop_reg;
static int disable_reg;
static int clear_reg;
/*
================
StartDMA
================
*/
void
StartDMA (void)
{
int mode;
int realaddr;
realaddr = ptr2real (dma_buffer);
// use a high dma channel if specified
if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma
dma = high_dma;
else
dma = low_dma;
Con_Printf ("Using DMA channel %i\n", dma);
if (dma > 3) {
mode_reg = 0xd6;
flipflop_reg = 0xd8;
disable_reg = 0xd4;
clear_reg = 0xdc;
} else {
mode_reg = 0xb;
flipflop_reg = 0xc;
disable_reg = 0xa;
clear_reg = 0xe;
}
dos_outportb (disable_reg, dma | 4); // disable channel
// set mode- see "undocumented pc", p.876
mode = (1 << 6) // single-cycle
+ (0 << 5) // address increment
+ (1 << 4) // auto-init dma
+ (2 << 2) // read
+ (dma & 3); // channel #
dos_outportb (mode_reg, mode);
// set address
// set page
dos_outportb (page_reg[dma], realaddr >> 16);
if (dma > 3) { // address is in words
dos_outportb (flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb (addr_reg[dma], (realaddr >> 1) & 0xff);
dos_outportb (addr_reg[dma], (realaddr >> 9) & 0xff);
dos_outportb (flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb (count_reg[dma], ((dma_size >> 1) - 1) & 0xff);
dos_outportb (count_reg[dma], ((dma_size >> 1) - 1) >> 8);
} else { // address is in bytes
dos_outportb (flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb (addr_reg[dma], realaddr & 0xff);
dos_outportb (addr_reg[dma], (realaddr >> 8) & 0xff);
dos_outportb (flipflop_reg, 0); // prepare to send 16-bit value
dos_outportb (count_reg[dma], (dma_size - 1) & 0xff);
dos_outportb (count_reg[dma], (dma_size - 1) >> 8);
}
dos_outportb (clear_reg, 0); // clear write mask
dos_outportb (disable_reg, dma & ~4);
}
/*
==================
BLASTER_Init
Returns false if nothing is found.
==================
*/
qboolean
BLASTER_Init (void)
{
int size;
int realaddr;
int rc;
int p;
shm = 0;
rc = 0;
//
// must have a blaster variable set
//
if (!GetBLASTER ()) {
Con_NotifyBox ("The BLASTER environment variable\n"
"is not set, sound effects are\n"
"disabled. See README.TXT for help.\n");
return 0;
}
if (ResetDSP ()) {
Con_Printf ("Could not reset SB");
return 0;
}
//
// get dsp version
//
WriteDSP (0xe1);
dsp_version = ReadDSP ();
dsp_minor_version = ReadDSP ();
// we need at least v2 for auto-init dma
if (dsp_version < 2) {
Con_Printf ("Sound blaster must be at least v2.0\n");
return 0;
}
// allow command line parm to set quality down
p = COM_CheckParm ("-dsp");
if (p && p < com_argc - 1) {
p = Q_atoi (com_argv[p + 1]);
if (p < 2 || p > 4)
Con_Printf ("-dsp parameter can only be 2, 3, or 4\n");
else if (p > dsp_version)
Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version);
else
dsp_version = p;
}
// everyone does 11khz sampling rate unless told otherwise
shm = &sn;
shm->speed = 11025;
rc = COM_CheckParm ("-sspeed");
if (rc)
shm->speed = Q_atoi (com_argv[rc + 1]);
// version 4 cards (sb 16) do 16 bit stereo
if (dsp_version >= 4) {
shm->channels = 2;
shm->samplebits = 16;
}
// version 3 cards (sb pro) do 8 bit stereo
else if (dsp_version == 3) {
shm->channels = 2;
shm->samplebits = 8;
}
// v2 cards do 8 bit mono
else {
shm->channels = 1;
shm->samplebits = 8;
}
Cmd_AddCommand ("sbinfo", SB_Info_f, "No Description");
size = 4096;
// allocate 8k and get a 4k-aligned buffer from it
dma_buffer = dos_getmemory (size * 2);
if (!dma_buffer) {
Con_Printf ("Couldn't allocate sound dma buffer");
return false;
}
realaddr = ptr2real (dma_buffer);
realaddr = (realaddr + size) & ~(size - 1);
dma_buffer = (short *) real2ptr (realaddr);
dma_size = size;
memset (dma_buffer, 0, dma_size);
shm->soundalive = true;
shm->splitbuffer = false;
shm->samples = size / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
shm->samples = size / (shm->samplebits / 8);
StartDMA ();
StartSB ();
return true;
}
/*
==============
BLASTER_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
BLASTER_GetDMAPos (void)
{
int count;
// this function is called often. acknowledge the transfer completions
// all the time so that it loops
if (dsp_version >= 4)
dos_inportb (dsp_port + 0xf); // 16 bit audio
else
dos_inportb (dsp_port + 0xe); // 8 bit audio
// clear 16-bit reg flip-flop
// load the current dma count register
if (dma < 4) {
dos_outportb (0xc, 0);
count = dos_inportb (dma * 2 + 1);
count += dos_inportb (dma * 2 + 1) << 8;
if (shm->samplebits == 16)
count /= 2;
count = shm->samples - (count + 1);
} else {
dos_outportb (0xd8, 0);
count = dos_inportb (0xc0 + (dma - 4) * 4 + 2);
count += dos_inportb (0xc0 + (dma - 4) * 4 + 2) << 8;
if (shm->samplebits == 8)
count *= 2;
count = shm->samples - (count + 1);
}
// Con_Printf("DMA pos = 0x%x\n", count);
shm->samplepos = count & (shm->samples - 1);
return shm->samplepos;
}
/*
==============
BLASTER_Shutdown
Reset the sound device for exiting
===============
*/
void
BLASTER_Shutdown (void)
{
if (dsp_version >= 4) {
} else if (dsp_version == 3) {
ResetDSP (); // stop high speed mode
WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on
} else {
}
WriteDSP (0xd3); // turn off speaker
ResetDSP ();
dos_outportb (disable_reg, dma | 4); // disable dma channel
}
/*
===============================================================================
INTERFACE
===============================================================================
*/
typedef enum {
dma_none,
dma_blaster,
dma_gus
} dmacard_t;
dmacard_t dmacard;
/*
==================
SNDDM_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
Returns true and fills in the "shm" structure with information for the mixer.
==================
*/
qboolean
SNDDMA_Init (void)
{
if (GUS_Init ()) {
dmacard = dma_gus;
return true;
}
if (BLASTER_Init ()) {
dmacard = dma_blaster;
return true;
}
dmacard = dma_none;
return false;
}
/*
==============
SNDDMA_GetDMAPos
return the current sample position (in mono samples, not stereo)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int
SNDDMA_GetDMAPos (void)
{
switch (dmacard) {
case dma_blaster:
return BLASTER_GetDMAPos ();
case dma_gus:
return GUS_GetDMAPos ();
case dma_none:
break;
}
return 0;
}
/*
==============
SNDDMA_Shutdown
Reset the sound device for exiting
===============
*/
void
SNDDMA_Shutdown (void)
{
switch (dmacard) {
case dma_blaster:
BLASTER_Shutdown ();
break;
case dma_gus:
GUS_Shutdown ();
break;
case dma_none:
break;
}
dmacard = dma_none;
return;
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void
SNDDMA_Submit (void)
{
}

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -1,232 +0,0 @@
/*
snd_mixa.S
x86 assembly-language sound code
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
// #include "quakeasm.h"
#ifdef USE_INTEL_ASM
.text
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
#define ch 4+16
#define sc 8+16
#define count 12+16
.globl C(SND_PaintChannelFrom8)
C(SND_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
movl ch(%esp),%ebx
movl sc(%esp),%esi
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $(sfxc_data),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
testl $1,%ecx
jz LMix8Loop
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
decl %ecx
jz LDone
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
// }
subl $2,%ecx
jnz LMix8Loop
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
.globl C(Snd_WriteLinearBlastStereo16)
C(Snd_WriteLinearBlastStereo16):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_vol),%esi
movl C(snd_out),%edi
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
// val = (snd_p[i]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i] = (short)0x8000;
// else
// snd_out[i] = val;
movl -8(%ebx,%ecx,4),%eax
imull %esi,%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
// val = (snd_p[i+1]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i+1] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i+1] = (short)0x8000;
// else
// snd_out[i+1] = val;
movl -4(%ebx,%ecx,4),%edx
imull %esi,%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
// }
subl $2,%ecx
jnz LWLBLoopTop
// snd_p += snd_linear_count;
popl %ebx
popl %edi
popl %esi
ret
#endif // USE_INTEL_ASM

View file

@ -1,73 +0,0 @@
/*
snd_next.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
extern int desired_speed;
extern int desired_bits;
qboolean
SNDDMA_Init (void)
{
int size;
size = 16384 + sizeof (dma_t);
shm = malloc (size);
memset ((void *) shm, 0, size);
shm->buffer = (char *) shm + sizeof (dma_t);
shm->channels = 2;
shm->speed = desired_speed;
shm->samplebits = desired_bits;
shm->samples = 16384 / (desired_bits / 8);
shm->submission_chunk = 1;
return true;
}
// return the current sample position (in mono samples read)
// inside the recirculating dma buffer
int
SNDDMA_GetDMAPos (void)
{
shm->samplepos =
(int) (realtime * shm->speed * shm->channels) & (shm->samples - 1);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
}

View file

@ -1,145 +0,0 @@
/*
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 "sound.h"
// =======================================================================
// Various variables also defined in snd_dma.c
// FIXME - should be put in one place
// =======================================================================
channel_t channels[MAX_CHANNELS];
int total_channels;
volatile dma_t *shm = 0;
cvar_t *loadas8bit;
int paintedtime; // sample PAIRS
cvar_t *bgmvolume;
cvar_t *volume;
void
S_Init (void)
{
S_Init_Cvars ();
}
void
S_Init_Cvars (void)
{
volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, 0, "Volume level of sounds");
loadas8bit =
Cvar_Get ("loadas8bit", "0", CVAR_NONE, 0, "Load samples as 8-bit");
bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, 0, "CD music volume");
}
void
S_AmbientOff (void)
{
}
void
S_AmbientOn (void)
{
}
void
S_Shutdown (void)
{
}
void
S_TouchSound (char *sample)
{
}
void
S_ClearBuffer (void)
{
}
void
S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
}
void
S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
float attenuation)
{
}
void
S_StopSound (int entnum, int entchannel)
{
}
sfx_t *
S_PrecacheSound (char *sample)
{
return NULL;
}
void
S_ClearPrecache (void)
{
}
void
S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
{
}
void
S_StopAllSounds (qboolean clear)
{
}
void
S_BeginPrecaching (void)
{
}
void
S_EndPrecaching (void)
{
}
void
S_ExtraUpdate (void)
{
}
void
S_LocalSound (char *s)
{
}

View file

@ -1,297 +0,0 @@
/*
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 "sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void *) -1)
#endif
static int audio_fd;
static int snd_inited;
static char *snd_dev = "/dev/dsp";
static int tryrates[] = { 11025, 22050, 22051, 44100, 8000 };
qboolean
SNDDMA_Init (void)
{
int rc;
int fmt;
int tmp;
int i;
struct audio_buf_info info;
int caps;
int retries = 3;
snd_inited = 0;
// open snd_dev, confirm capability to mmap, and get size of dma buffer
if (snd_device->string[0])
snd_dev = snd_device->string;
audio_fd = open (snd_dev, O_RDWR);
if (audio_fd < 0) { // Failed open, retry up to 3 times
// if it's busy
while ((audio_fd < 0) && retries-- &&
((errno == EAGAIN) || (errno == EBUSY))) {
sleep (1);
audio_fd = open (snd_dev, O_RDWR);
}
if (audio_fd < 0) {
perror (snd_dev);
Con_Printf ("Could not open %s\n", snd_dev);
return 0;
}
}
if ((rc = ioctl (audio_fd, SNDCTL_DSP_RESET, 0)) < 0) {
perror (snd_dev);
Con_Printf ("Could not reset %s\n", snd_dev);
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
perror (snd_dev);
Con_Printf ("Sound driver too old\n");
close (audio_fd);
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
Con_Printf ("Sound device can't do memory-mapped I/O.\n");
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror ("GETOSPACE");
Con_Printf ("Um, can't do GETOSPACE?\n");
close (audio_fd);
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
// set sample bits & speed
shm->samplebits = snd_bits->int_val;
if (shm->samplebits != 16 && shm->samplebits != 8) {
ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE) { // little-endian 16-bit signed
shm->samplebits = 16;
} else {
if (fmt & AFMT_U8) { // unsigned 8-bit ulaw
shm->samplebits = 8;
}
}
}
if (snd_rate->int_val) {
shm->speed = snd_rate->int_val;
} else {
for (i = 0; i < (sizeof (tryrates) / 4); i++)
if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
break;
shm->speed = tryrates[i];
}
if (!snd_stereo->int_val) {
shm->channels = 1;
} else {
shm->channels = 2;
}
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits / 8);
shm->submission_chunk = 1;
// memory map the dma buffer
shm->buffer = (unsigned char *) mmap (NULL, info.fragstotal
* info.fragsize,
PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, audio_fd, 0);
if (shm->buffer == MAP_FAILED) {
perror (snd_dev);
Con_Printf ("Could not mmap %s\n", snd_dev);
close (audio_fd);
return 0;
}
tmp = 0;
if (shm->channels == 2)
tmp = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s to stereo=%d", snd_dev, shm->channels);
close (audio_fd);
return 0;
}
if (tmp)
shm->channels = 2;
else
shm->channels = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s speed to %d", snd_dev, shm->speed);
close (audio_fd);
return 0;
}
if (shm->samplebits == 16) {
rc = AFMT_S16_LE;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 16-bit data. Try 8-bit.\n");
close (audio_fd);
return 0;
}
} else if (shm->samplebits == 8) {
rc = AFMT_U8;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 8-bit data.\n");
close (audio_fd);
return 0;
}
} else {
perror (snd_dev);
Con_Printf ("%d-bit sound not supported.", shm->samplebits);
close (audio_fd);
return 0;
}
// toggle the trigger & start her up
tmp = 0;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
shm->samplepos = 0;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
struct count_info count;
if (!snd_inited)
return 0;
if (ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
perror (snd_dev);
Con_Printf ("Uh, sound dead.\n");
close (audio_fd);
snd_inited = 0;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

@ -1,158 +0,0 @@
/*
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 "sound.h"
static dma_t the_shm;
static int snd_inited;
extern int desired_speed;
extern int desired_bits;
static void
paint_audio (void *unused, Uint8 * stream, int len)
{
if (shm) {
shm->buffer = stream;
shm->samplepos += len / (shm->samplebits / 8);
// Check for samplepos overflow?
S_PaintChannels (shm->samplepos);
}
}
qboolean
SNDDMA_Init (void)
{
SDL_AudioSpec desired, obtained;
snd_inited = 0;
/* Set up the desired format */
desired.freq = desired_speed;
switch (desired_bits) {
case 8:
desired.format = AUDIO_U8;
break;
case 16:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
desired.format = AUDIO_S16MSB;
else
desired.format = AUDIO_S16LSB;
break;
default:
Con_Printf ("Unknown number of audio bits: %d\n", desired_bits);
return 0;
}
desired.channels = 2;
desired.samples = 512;
desired.callback = paint_audio;
/* Open the audio device */
if (SDL_OpenAudio (&desired, &obtained) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
/* Make sure we can support the audio format */
switch (obtained.format) {
case AUDIO_U8:
/* Supported */
break;
case AUDIO_S16LSB:
case AUDIO_S16MSB:
if (((obtained.format == AUDIO_S16LSB) &&
(SDL_BYTEORDER == SDL_LIL_ENDIAN)) ||
((obtained.format == AUDIO_S16MSB) &&
(SDL_BYTEORDER == SDL_BIG_ENDIAN))) {
/* Supported */
break;
}
/* Unsupported, fall through */ ;
default:
/* Not supported -- force SDL to do our bidding */
SDL_CloseAudio ();
if (SDL_OpenAudio (&desired, NULL) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
memcpy (&obtained, &desired, sizeof (desired));
break;
}
SDL_PauseAudio (0);
/* Fill the audio DMA information block */
shm = &the_shm;
shm->splitbuffer = 0;
shm->samplebits = (obtained.format & 0xFF);
shm->speed = obtained.freq;
shm->channels = obtained.channels;
shm->samples = obtained.samples * shm->channels;
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = NULL;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
SDL_CloseAudio ();
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

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

View file

@ -1,228 +0,0 @@
/*
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 "sound.h"
#include "QF/qargs.h"
#include "QF/console.h"
int audio_fd;
int snd_inited;
static int wbufp;
static audio_info_t info;
#define BUFFER_SIZE 8192
unsigned char dma_buffer[BUFFER_SIZE];
unsigned char pend_buffer[BUFFER_SIZE];
int pending;
qboolean
SNDDMA_Init (void)
{
if (snd_inited) {
printf ("Sound already init'd\n");
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
audio_fd = open ("/dev/audio", O_WRONLY | O_NDELAY);
if (audio_fd < 0) {
if (errno == EBUSY) {
Con_Printf ("Audio device is being used by another process\n");
}
perror ("/dev/audio");
Con_Printf ("Could not open /dev/audio\n");
return (0);
}
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
return 0;
}
//
// set to nonblock
//
if (fcntl (audio_fd, F_SETFL, O_NONBLOCK) < 0) {
perror ("/dev/audio");
close (audio_fd);
return 0;
}
AUDIO_INITINFO (&info);
shm->speed = 11025;
// try 16 bit stereo
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 2;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 1;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
Con_Printf ("Incapable sound hardware.\n");
close (audio_fd);
return 0;
}
Con_Printf ("16 bit mono sound initialized\n");
shm->samplebits = 16;
shm->channels = 1;
} else { // 16 bit stereo
Con_Printf ("16 bit stereo sound initialized\n");
shm->samplebits = 16;
shm->channels = 2;
}
shm->soundalive = true;
shm->samples = sizeof (dma_buffer) / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return ((info.play.samples * shm->channels) % shm->samples);
}
int
SNDDMA_GetSamples (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return info.play.samples;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int bsize;
int bytes, b;
static unsigned char writebuf[1024];
unsigned char *p;
int idx;
int stop = paintedtime;
if (paintedtime < wbufp)
wbufp = 0; // reset
bsize = shm->channels * (shm->samplebits / 8);
bytes = (paintedtime - wbufp) * bsize;
if (!bytes)
return;
if (bytes > sizeof (writebuf)) {
bytes = sizeof (writebuf);
stop = wbufp + bytes / bsize;
}
p = writebuf;
idx = (wbufp * bsize) & (BUFFER_SIZE - 1);
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (BUFFER_SIZE - 1);
}
wbufp = stop;
if (write (audio_fd, writebuf, bytes) < bytes)
printf ("audio can't keep up!\n");
}

View file

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

View file

@ -1,358 +0,0 @@
/*
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 "sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void*)-1)
#endif
static int snd_inited;
static snd_pcm_t *pcm_handle;
static struct snd_pcm_channel_info cinfo;
static struct snd_pcm_channel_params params;
static struct snd_pcm_channel_setup setup;
static snd_pcm_mmap_control_t *mmap_control = NULL;
static char *mmap_data = NULL;
static int card = -1, dev = -1;
int
check_card (int card)
{
snd_ctl_t *handle;
snd_ctl_hw_info_t info;
int rc;
if ((rc = snd_ctl_open (&handle, card)) < 0) {
Con_Printf ("Error: control open (%i): %s\n", card, snd_strerror (rc));
return rc;
}
if ((rc = snd_ctl_hw_info (handle, &info)) < 0) {
Con_Printf ("Error: control hardware info (%i): %s\n", card,
snd_strerror (rc));
snd_ctl_close (handle);
return rc;
}
snd_ctl_close (handle);
if (dev == -1) {
for (dev = 0; dev < info.pcmdevs; dev++) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
} else {
if (dev >= 0 && dev < info.pcmdevs) {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) == 0) {
return 0;
}
}
}
return 1;
}
qboolean
SNDDMA_Init (void)
{
int rc = 0, i;
char *err_msg = "";
int rate = -1, format = -1, bps, stereo = -1, frag_size;
unsigned int mask;
mask = snd_cards_mask ();
if (!mask) {
Con_Printf ("No sound cards detected\n");
return 0;
}
if (snd_device->string[0]) {
sscanf (snd_device->string, "%d,%d", &card, &dev);
}
if (snd_bits->int_val) {
i = snd_bits->int_val;
if (i == 16) {
format = SND_PCM_SFMT_S16_LE;
} else if (i == 8) {
format = SND_PCM_SFMT_U8;
} else {
Con_Printf ("Error: invalid sample bits: %d\n", i);
return 0;
}
}
if (snd_rate->int_val) {
rate = snd_rate->int_val;
if (rate != 44100 && rate != 22050 && rate != 11025) {
Con_Printf ("Error: invalid sample rate: %d\n", rate);
return 0;
}
}
stereo = snd_stereo->int_val;
if (card == -1) {
for (card = 0; card < SND_CARDS; card++) {
if (!(mask & (1 << card)))
continue;
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
}
} else {
if (dev == -1) {
rc = check_card (card);
if (rc < 0)
return 0;
if (!rc)
goto dev_openned;
} else {
if ((rc = snd_pcm_open (&pcm_handle, card, dev,
SND_PCM_OPEN_PLAYBACK
| SND_PCM_OPEN_NONBLOCK)) < 0) {
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
}
goto dev_openned;
}
}
Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
return 0;
dev_openned:
Con_Printf ("Using card %d, device %d.\n", card, dev);
memset (&cinfo, 0, sizeof (cinfo));
cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
snd_pcm_channel_info (pcm_handle, &cinfo);
Con_Printf ("%08x %08x %08x\n", cinfo.flags, cinfo.formats, cinfo.rates);
if ((rate == -1 || rate == 44100) && cinfo.rates & SND_PCM_RATE_44100) {
rate = 44100;
frag_size = 512; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 22050)
&& cinfo.rates & SND_PCM_RATE_22050) {
rate = 22050;
frag_size = 256; /* assuming stereo 8 bit */
} else if ((rate == -1 || rate == 11025)
&& cinfo.rates & SND_PCM_RATE_11025) {
rate = 11025;
frag_size = 128; /* assuming stereo 8 bit */
} else {
Con_Printf ("ALSA: desired rates not supported\n");
goto error_2;
}
if ((format == -1 || format == SND_PCM_SFMT_S16_LE)
&& cinfo.formats & SND_PCM_FMT_S16_LE) {
format = SND_PCM_SFMT_S16_LE;
bps = 16;
frag_size *= 2;
} else if ((format == -1 || format == SND_PCM_SFMT_U8)
&& cinfo.formats & SND_PCM_FMT_U8) {
format = SND_PCM_SFMT_U8;
bps = 8;
} else {
Con_Printf ("ALSA: desired formats not supported\n");
goto error_2;
}
if (stereo && cinfo.max_voices >= 2) {
stereo = 1;
} else {
stereo = 0;
frag_size /= 2;
}
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio munmap";
if ((rc = snd_pcm_munmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
goto error;
memset (&params, 0, sizeof (params));
params.channel = SND_PCM_CHANNEL_PLAYBACK;
params.mode = SND_PCM_MODE_BLOCK;
params.format.interleave = 1;
params.format.format = format;
params.format.rate = rate;
params.format.voices = stereo + 1;
params.start_mode = SND_PCM_START_GO;
params.stop_mode = SND_PCM_STOP_ROLLOVER;
params.buf.block.frag_size = frag_size;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = -1;
// err_msg="audio flush";
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
// goto error;
err_msg = "audio params";
if ((rc = snd_pcm_channel_params (pcm_handle, &params)) < 0)
goto error;
err_msg = "audio mmap";
if (
(rc =
snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
(void **) &mmap_data)) < 0)
goto error;
err_msg = "audio prepare";
if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
0) goto error;
memset (&setup, 0, sizeof (setup));
setup.mode = SND_PCM_MODE_BLOCK;
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
err_msg = "audio setup";
if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
goto error;
shm = &sn;
memset ((dma_t *) shm, 0, sizeof (*shm));
shm->splitbuffer = 0;
shm->channels = setup.format.voices;
shm->submission_chunk = 128; // don't mix less than this #
shm->samplepos = 0; // in mono samples
shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
shm->samples =
setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8); // mono
//
// samples
// in
// buffer
shm->speed = setup.format.rate;
shm->buffer = (unsigned char *) mmap_data;
Con_Printf ("%5d stereo\n", shm->channels - 1);
Con_Printf ("%5d samples\n", shm->samples);
Con_Printf ("%5d samplepos\n", shm->samplepos);
Con_Printf ("%5d samplebits\n", shm->samplebits);
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf ("%5d speed\n", shm->speed);
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
Con_Printf ("%5d total_channels\n", total_channels);
snd_inited = 1;
return 1;
error:
Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
error_2:
snd_pcm_close (pcm_handle);
return 0;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return 0;
shm->samplepos =
(mmap_control->status.frag_io +
1) * setup.buf.block.frag_size / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
snd_pcm_close (pcm_handle);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int count = paintedtime - soundtime;
int i, s, e;
int rc;
count += setup.buf.block.frag_size - 1;
count /= setup.buf.block.frag_size;
s = soundtime / setup.buf.block.frag_size;
e = s + count;
for (i = s; i < e; i++)
mmap_control->fragments[i % setup.buf.block.frags].data = 1;
switch (mmap_control->status.status) {
case SND_PCM_STATUS_PREPARED:
if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK))
< 0) {
fprintf (stderr, "unable to start playback. %s\n",
snd_strerror (rc));
exit (1);
}
break;
case SND_PCM_STATUS_RUNNING:
break;
case SND_PCM_STATUS_UNDERRUN:
if (
(rc =
snd_pcm_plugin_prepare (pcm_handle,
SND_PCM_CHANNEL_PLAYBACK)) < 0) {
fprintf (stderr,
"underrun: playback channel prepare error. %s\n",
snd_strerror (rc));
exit (1);
}
break;
default:
break;
}
}

View file

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

View file

@ -1,108 +0,0 @@
/*
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 "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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -1,232 +0,0 @@
/*
snd_mixa.S
x86 assembly-language sound code
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "QF/asm_i386.h"
// #include "quakeasm.h"
#ifdef USE_INTEL_ASM
.text
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
#define ch 4+16
#define sc 8+16
#define count 12+16
.globl C(SND_PaintChannelFrom8)
C(SND_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
movl ch(%esp),%ebx
movl sc(%esp),%esi
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $(sfxc_data),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
testl $1,%ecx
jz LMix8Loop
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
decl %ecx
jz LDone
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
// }
subl $2,%ecx
jnz LMix8Loop
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
.globl C(Snd_WriteLinearBlastStereo16)
C(Snd_WriteLinearBlastStereo16):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_vol),%esi
movl C(snd_out),%edi
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
// val = (snd_p[i]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i] = (short)0x8000;
// else
// snd_out[i] = val;
movl -8(%ebx,%ecx,4),%eax
imull %esi,%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
// val = (snd_p[i+1]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i+1] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i+1] = (short)0x8000;
// else
// snd_out[i+1] = val;
movl -4(%ebx,%ecx,4),%edx
imull %esi,%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
// }
subl $2,%ecx
jnz LWLBLoopTop
// snd_p += snd_linear_count;
popl %ebx
popl %edi
popl %esi
ret
#endif // USE_INTEL_ASM

View file

@ -1,145 +0,0 @@
/*
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 "sound.h"
// =======================================================================
// Various variables also defined in snd_dma.c
// FIXME - should be put in one place
// =======================================================================
channel_t channels[MAX_CHANNELS];
int total_channels;
volatile dma_t *shm = 0;
cvar_t *loadas8bit;
int paintedtime; // sample PAIRS
cvar_t *bgmvolume;
cvar_t *volume;
void
S_Init (void)
{
S_Init_Cvars ();
}
void
S_Init_Cvars (void)
{
volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, 0, "Volume level of sounds");
loadas8bit =
Cvar_Get ("loadas8bit", "0", CVAR_NONE, 0, "Load samples as 8-bit");
bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, 0, "CD music volume");
}
void
S_AmbientOff (void)
{
}
void
S_AmbientOn (void)
{
}
void
S_Shutdown (void)
{
}
void
S_TouchSound (char *sample)
{
}
void
S_ClearBuffer (void)
{
}
void
S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
}
void
S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
float attenuation)
{
}
void
S_StopSound (int entnum, int entchannel)
{
}
sfx_t *
S_PrecacheSound (char *sample)
{
return NULL;
}
void
S_ClearPrecache (void)
{
}
void
S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
{
}
void
S_StopAllSounds (qboolean clear)
{
}
void
S_BeginPrecaching (void)
{
}
void
S_EndPrecaching (void)
{
}
void
S_ExtraUpdate (void)
{
}
void
S_LocalSound (char *s)
{
}

View file

@ -1,297 +0,0 @@
/*
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 "sound.h"
#ifndef MAP_FAILED
# define MAP_FAILED ((void *) -1)
#endif
static int audio_fd;
static int snd_inited;
static char *snd_dev = "/dev/dsp";
static int tryrates[] = { 11025, 22050, 22051, 44100, 8000 };
qboolean
SNDDMA_Init (void)
{
int rc;
int fmt;
int tmp;
int i;
struct audio_buf_info info;
int caps;
int retries = 3;
snd_inited = 0;
// open snd_dev, confirm capability to mmap, and get size of dma buffer
if (snd_device->string[0])
snd_dev = snd_device->string;
audio_fd = open (snd_dev, O_RDWR);
if (audio_fd < 0) { // Failed open, retry up to 3 times
// if it's busy
while ((audio_fd < 0) && retries-- &&
((errno == EAGAIN) || (errno == EBUSY))) {
sleep (1);
audio_fd = open (snd_dev, O_RDWR);
}
if (audio_fd < 0) {
perror (snd_dev);
Con_Printf ("Could not open %s\n", snd_dev);
return 0;
}
}
if ((rc = ioctl (audio_fd, SNDCTL_DSP_RESET, 0)) < 0) {
perror (snd_dev);
Con_Printf ("Could not reset %s\n", snd_dev);
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
perror (snd_dev);
Con_Printf ("Sound driver too old\n");
close (audio_fd);
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
Con_Printf ("Sound device can't do memory-mapped I/O.\n");
close (audio_fd);
return 0;
}
if (ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror ("GETOSPACE");
Con_Printf ("Um, can't do GETOSPACE?\n");
close (audio_fd);
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
// set sample bits & speed
shm->samplebits = snd_bits->int_val;
if (shm->samplebits != 16 && shm->samplebits != 8) {
ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE) { // little-endian 16-bit signed
shm->samplebits = 16;
} else {
if (fmt & AFMT_U8) { // unsigned 8-bit ulaw
shm->samplebits = 8;
}
}
}
if (snd_rate->int_val) {
shm->speed = snd_rate->int_val;
} else {
for (i = 0; i < (sizeof (tryrates) / 4); i++)
if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
break;
shm->speed = tryrates[i];
}
if (!snd_stereo->int_val) {
shm->channels = 1;
} else {
shm->channels = 2;
}
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits / 8);
shm->submission_chunk = 1;
// memory map the dma buffer
shm->buffer = (unsigned char *) mmap (NULL, info.fragstotal
* info.fragsize,
PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, audio_fd, 0);
if (shm->buffer == MAP_FAILED) {
perror (snd_dev);
Con_Printf ("Could not mmap %s\n", snd_dev);
close (audio_fd);
return 0;
}
tmp = 0;
if (shm->channels == 2)
tmp = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s to stereo=%d", snd_dev, shm->channels);
close (audio_fd);
return 0;
}
if (tmp)
shm->channels = 2;
else
shm->channels = 1;
rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not set %s speed to %d", snd_dev, shm->speed);
close (audio_fd);
return 0;
}
if (shm->samplebits == 16) {
rc = AFMT_S16_LE;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 16-bit data. Try 8-bit.\n");
close (audio_fd);
return 0;
}
} else if (shm->samplebits == 8) {
rc = AFMT_U8;
rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not support 8-bit data.\n");
close (audio_fd);
return 0;
}
} else {
perror (snd_dev);
Con_Printf ("%d-bit sound not supported.", shm->samplebits);
close (audio_fd);
return 0;
}
// toggle the trigger & start her up
tmp = 0;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl (audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror (snd_dev);
Con_Printf ("Could not toggle.\n");
close (audio_fd);
return 0;
}
shm->samplepos = 0;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
struct count_info count;
if (!snd_inited)
return 0;
if (ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
perror (snd_dev);
Con_Printf ("Uh, sound dead.\n");
close (audio_fd);
snd_inited = 0;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

@ -1,158 +0,0 @@
/*
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 "sound.h"
static dma_t the_shm;
static int snd_inited;
extern int desired_speed;
extern int desired_bits;
static void
paint_audio (void *unused, Uint8 * stream, int len)
{
if (shm) {
shm->buffer = stream;
shm->samplepos += len / (shm->samplebits / 8);
// Check for samplepos overflow?
S_PaintChannels (shm->samplepos);
}
}
qboolean
SNDDMA_Init (void)
{
SDL_AudioSpec desired, obtained;
snd_inited = 0;
/* Set up the desired format */
desired.freq = desired_speed;
switch (desired_bits) {
case 8:
desired.format = AUDIO_U8;
break;
case 16:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
desired.format = AUDIO_S16MSB;
else
desired.format = AUDIO_S16LSB;
break;
default:
Con_Printf ("Unknown number of audio bits: %d\n", desired_bits);
return 0;
}
desired.channels = 2;
desired.samples = 512;
desired.callback = paint_audio;
/* Open the audio device */
if (SDL_OpenAudio (&desired, &obtained) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
/* Make sure we can support the audio format */
switch (obtained.format) {
case AUDIO_U8:
/* Supported */
break;
case AUDIO_S16LSB:
case AUDIO_S16MSB:
if (((obtained.format == AUDIO_S16LSB) &&
(SDL_BYTEORDER == SDL_LIL_ENDIAN)) ||
((obtained.format == AUDIO_S16MSB) &&
(SDL_BYTEORDER == SDL_BIG_ENDIAN))) {
/* Supported */
break;
}
/* Unsupported, fall through */ ;
default:
/* Not supported -- force SDL to do our bidding */
SDL_CloseAudio ();
if (SDL_OpenAudio (&desired, NULL) < 0) {
Con_Printf ("Couldn't open SDL audio: %s\n", SDL_GetError ());
return 0;
}
memcpy (&obtained, &desired, sizeof (desired));
break;
}
SDL_PauseAudio (0);
/* Fill the audio DMA information block */
shm = &the_shm;
shm->splitbuffer = 0;
shm->samplebits = (obtained.format & 0xFF);
shm->speed = obtained.freq;
shm->channels = obtained.channels;
shm->samples = obtained.samples * shm->channels;
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = NULL;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
return shm->samplepos;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
SDL_CloseAudio ();
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
}

View file

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

View file

@ -1,228 +0,0 @@
/*
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 "sound.h"
#include "QF/qargs.h"
#include "QF/console.h"
int audio_fd;
int snd_inited;
static int wbufp;
static audio_info_t info;
#define BUFFER_SIZE 8192
unsigned char dma_buffer[BUFFER_SIZE];
unsigned char pend_buffer[BUFFER_SIZE];
int pending;
qboolean
SNDDMA_Init (void)
{
if (snd_inited) {
printf ("Sound already init'd\n");
return 0;
}
shm = &sn;
shm->splitbuffer = 0;
audio_fd = open ("/dev/audio", O_WRONLY | O_NDELAY);
if (audio_fd < 0) {
if (errno == EBUSY) {
Con_Printf ("Audio device is being used by another process\n");
}
perror ("/dev/audio");
Con_Printf ("Could not open /dev/audio\n");
return (0);
}
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
return 0;
}
//
// set to nonblock
//
if (fcntl (audio_fd, F_SETFL, O_NONBLOCK) < 0) {
perror ("/dev/audio");
close (audio_fd);
return 0;
}
AUDIO_INITINFO (&info);
shm->speed = 11025;
// try 16 bit stereo
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 2;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.sample_rate = 11025;
info.play.channels = 1;
info.play.precision = 16;
if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
Con_Printf ("Incapable sound hardware.\n");
close (audio_fd);
return 0;
}
Con_Printf ("16 bit mono sound initialized\n");
shm->samplebits = 16;
shm->channels = 1;
} else { // 16 bit stereo
Con_Printf ("16 bit stereo sound initialized\n");
shm->samplebits = 16;
shm->channels = 2;
}
shm->soundalive = true;
shm->samples = sizeof (dma_buffer) / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) dma_buffer;
snd_inited = 1;
return 1;
}
int
SNDDMA_GetDMAPos (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return ((info.play.samples * shm->channels) % shm->samples);
}
int
SNDDMA_GetSamples (void)
{
if (!snd_inited)
return (0);
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
perror ("/dev/audio");
Con_Printf ("Could not communicate with audio device.\n");
close (audio_fd);
snd_inited = 0;
return (0);
}
return info.play.samples;
}
void
SNDDMA_Shutdown (void)
{
if (snd_inited) {
close (audio_fd);
snd_inited = 0;
}
}
/*
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
*/
void
SNDDMA_Submit (void)
{
int bsize;
int bytes, b;
static unsigned char writebuf[1024];
unsigned char *p;
int idx;
int stop = paintedtime;
if (paintedtime < wbufp)
wbufp = 0; // reset
bsize = shm->channels * (shm->samplebits / 8);
bytes = (paintedtime - wbufp) * bsize;
if (!bytes)
return;
if (bytes > sizeof (writebuf)) {
bytes = sizeof (writebuf);
stop = wbufp + bytes / bsize;
}
p = writebuf;
idx = (wbufp * bsize) & (BUFFER_SIZE - 1);
for (b = bytes; b; b--) {
*p++ = dma_buffer[idx];
idx = (idx + 1) & (BUFFER_SIZE - 1);
}
wbufp = stop;
if (write (audio_fd, writebuf, bytes) < bytes)
printf ("audio can't keep up!\n");
}

View file

@ -1,725 +0,0 @@
/*
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 "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;
}