mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
Removed old files
This commit is contained in:
parent
69022c7ffb
commit
dcd924c355
30 changed files with 0 additions and 12733 deletions
|
@ -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 (¶ms, 0, sizeof (params));
|
||||
params.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
params.mode = SND_PCM_MODE_BLOCK;
|
||||
params.format.interleave = 1;
|
||||
params.format.format = format;
|
||||
params.format.rate = rate;
|
||||
params.format.voices = stereo + 1;
|
||||
params.start_mode = SND_PCM_START_GO;
|
||||
params.stop_mode = SND_PCM_STOP_ROLLOVER;
|
||||
params.buf.block.frag_size = frag_size;
|
||||
params.buf.block.frags_min = 1;
|
||||
params.buf.block.frags_max = -1;
|
||||
// err_msg="audio flush";
|
||||
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
|
||||
// goto error;
|
||||
err_msg = "audio params";
|
||||
if ((rc = snd_pcm_channel_params (pcm_handle, ¶ms)) < 0)
|
||||
goto error;
|
||||
|
||||
err_msg = "audio mmap";
|
||||
if (
|
||||
(rc =
|
||||
snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
|
||||
(void **) &mmap_data)) < 0)
|
||||
goto error;
|
||||
err_msg = "audio prepare";
|
||||
if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
|
||||
0) goto error;
|
||||
|
||||
memset (&setup, 0, sizeof (setup));
|
||||
setup.mode = SND_PCM_MODE_BLOCK;
|
||||
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
err_msg = "audio setup";
|
||||
if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
|
||||
goto error;
|
||||
|
||||
shm = &sn;
|
||||
memset ((dma_t *) shm, 0, sizeof (*shm));
|
||||
shm->splitbuffer = 0;
|
||||
shm->channels = setup.format.voices;
|
||||
shm->submission_chunk = 128; // don't mix less than this #
|
||||
shm->samplepos = 0; // in mono samples
|
||||
shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
|
||||
shm->samples =
|
||||
setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8); // mono
|
||||
//
|
||||
// samples
|
||||
// in
|
||||
// buffer
|
||||
shm->speed = setup.format.rate;
|
||||
shm->buffer = (unsigned char *) mmap_data;
|
||||
Con_Printf ("%5d stereo\n", shm->channels - 1);
|
||||
Con_Printf ("%5d samples\n", shm->samples);
|
||||
Con_Printf ("%5d samplepos\n", shm->samplepos);
|
||||
Con_Printf ("%5d samplebits\n", shm->samplebits);
|
||||
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
|
||||
Con_Printf ("%5d speed\n", shm->speed);
|
||||
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
|
||||
Con_Printf ("%5d total_channels\n", total_channels);
|
||||
|
||||
snd_inited = 1;
|
||||
return 1;
|
||||
error:
|
||||
Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
|
||||
error_2:
|
||||
snd_pcm_close (pcm_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SNDDMA_GetDMAPos (void)
|
||||
{
|
||||
if (!snd_inited)
|
||||
return 0;
|
||||
shm->samplepos =
|
||||
(mmap_control->status.frag_io +
|
||||
1) * setup.buf.block.frag_size / (shm->samplebits / 8);
|
||||
return shm->samplepos;
|
||||
}
|
||||
|
||||
void
|
||||
SNDDMA_Shutdown (void)
|
||||
{
|
||||
if (snd_inited) {
|
||||
snd_pcm_close (pcm_handle);
|
||||
snd_inited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
*/
|
||||
void
|
||||
SNDDMA_Submit (void)
|
||||
{
|
||||
int count = paintedtime - soundtime;
|
||||
int i, s, e;
|
||||
int rc;
|
||||
|
||||
count += setup.buf.block.frag_size - 1;
|
||||
count /= setup.buf.block.frag_size;
|
||||
s = soundtime / setup.buf.block.frag_size;
|
||||
e = s + count;
|
||||
for (i = s; i < e; i++)
|
||||
mmap_control->fragments[i % setup.buf.block.frags].data = 1;
|
||||
switch (mmap_control->status.status) {
|
||||
case SND_PCM_STATUS_PREPARED:
|
||||
if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK))
|
||||
< 0) {
|
||||
fprintf (stderr, "unable to start playback. %s\n",
|
||||
snd_strerror (rc));
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
case SND_PCM_STATUS_RUNNING:
|
||||
break;
|
||||
case SND_PCM_STATUS_UNDERRUN:
|
||||
if (
|
||||
(rc =
|
||||
snd_pcm_plugin_prepare (pcm_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK)) < 0) {
|
||||
fprintf (stderr,
|
||||
"underrun: playback channel prepare error. %s\n",
|
||||
snd_strerror (rc));
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
1016
nq/source/snd_dma.c
1016
nq/source/snd_dma.c
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
}
|
1281
nq/source/snd_gus.c
1281
nq/source/snd_gus.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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 */
|
|
@ -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");
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 (¶ms, 0, sizeof (params));
|
||||
params.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
params.mode = SND_PCM_MODE_BLOCK;
|
||||
params.format.interleave = 1;
|
||||
params.format.format = format;
|
||||
params.format.rate = rate;
|
||||
params.format.voices = stereo + 1;
|
||||
params.start_mode = SND_PCM_START_GO;
|
||||
params.stop_mode = SND_PCM_STOP_ROLLOVER;
|
||||
params.buf.block.frag_size = frag_size;
|
||||
params.buf.block.frags_min = 1;
|
||||
params.buf.block.frags_max = -1;
|
||||
// err_msg="audio flush";
|
||||
// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
|
||||
// goto error;
|
||||
err_msg = "audio params";
|
||||
if ((rc = snd_pcm_channel_params (pcm_handle, ¶ms)) < 0)
|
||||
goto error;
|
||||
|
||||
err_msg = "audio mmap";
|
||||
if (
|
||||
(rc =
|
||||
snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
|
||||
(void **) &mmap_data)) < 0)
|
||||
goto error;
|
||||
err_msg = "audio prepare";
|
||||
if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
|
||||
0) goto error;
|
||||
|
||||
memset (&setup, 0, sizeof (setup));
|
||||
setup.mode = SND_PCM_MODE_BLOCK;
|
||||
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
err_msg = "audio setup";
|
||||
if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
|
||||
goto error;
|
||||
|
||||
shm = &sn;
|
||||
memset ((dma_t *) shm, 0, sizeof (*shm));
|
||||
shm->splitbuffer = 0;
|
||||
shm->channels = setup.format.voices;
|
||||
shm->submission_chunk = 128; // don't mix less than this #
|
||||
shm->samplepos = 0; // in mono samples
|
||||
shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
|
||||
shm->samples =
|
||||
setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8); // mono
|
||||
//
|
||||
// samples
|
||||
// in
|
||||
// buffer
|
||||
shm->speed = setup.format.rate;
|
||||
shm->buffer = (unsigned char *) mmap_data;
|
||||
Con_Printf ("%5d stereo\n", shm->channels - 1);
|
||||
Con_Printf ("%5d samples\n", shm->samples);
|
||||
Con_Printf ("%5d samplepos\n", shm->samplepos);
|
||||
Con_Printf ("%5d samplebits\n", shm->samplebits);
|
||||
Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
|
||||
Con_Printf ("%5d speed\n", shm->speed);
|
||||
Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
|
||||
Con_Printf ("%5d total_channels\n", total_channels);
|
||||
|
||||
snd_inited = 1;
|
||||
return 1;
|
||||
error:
|
||||
Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
|
||||
error_2:
|
||||
snd_pcm_close (pcm_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SNDDMA_GetDMAPos (void)
|
||||
{
|
||||
if (!snd_inited)
|
||||
return 0;
|
||||
shm->samplepos =
|
||||
(mmap_control->status.frag_io +
|
||||
1) * setup.buf.block.frag_size / (shm->samplebits / 8);
|
||||
return shm->samplepos;
|
||||
}
|
||||
|
||||
void
|
||||
SNDDMA_Shutdown (void)
|
||||
{
|
||||
if (snd_inited) {
|
||||
snd_pcm_close (pcm_handle);
|
||||
snd_inited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
*/
|
||||
void
|
||||
SNDDMA_Submit (void)
|
||||
{
|
||||
int count = paintedtime - soundtime;
|
||||
int i, s, e;
|
||||
int rc;
|
||||
|
||||
count += setup.buf.block.frag_size - 1;
|
||||
count /= setup.buf.block.frag_size;
|
||||
s = soundtime / setup.buf.block.frag_size;
|
||||
e = s + count;
|
||||
for (i = s; i < e; i++)
|
||||
mmap_control->fragments[i % setup.buf.block.frags].data = 1;
|
||||
switch (mmap_control->status.status) {
|
||||
case SND_PCM_STATUS_PREPARED:
|
||||
if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK))
|
||||
< 0) {
|
||||
fprintf (stderr, "unable to start playback. %s\n",
|
||||
snd_strerror (rc));
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
case SND_PCM_STATUS_RUNNING:
|
||||
break;
|
||||
case SND_PCM_STATUS_UNDERRUN:
|
||||
if (
|
||||
(rc =
|
||||
snd_pcm_plugin_prepare (pcm_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK)) < 0) {
|
||||
fprintf (stderr,
|
||||
"underrun: playback channel prepare error. %s\n",
|
||||
snd_strerror (rc));
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
1016
qw/source/snd_dma.c
1016
qw/source/snd_dma.c
File diff suppressed because it is too large
Load diff
1281
qw/source/snd_gus.c
1281
qw/source/snd_gus.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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 */
|
|
@ -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");
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue