mirror of
https://git.code.sf.net/p/quake/nuq
synced 2024-11-25 05:21:41 +00:00
bring over from newtree
This commit is contained in:
parent
5553c1ab5a
commit
8d1b5efd1d
1 changed files with 63 additions and 62 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
snd_alsa.c
|
snd_alsa_0_6.c
|
||||||
|
|
||||||
(description)
|
(description)
|
||||||
|
|
||||||
|
@ -28,40 +28,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <qtypes.h>
|
|
||||||
#include <sound.h>
|
|
||||||
#include <qargs.h>
|
|
||||||
#include <console.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#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 <sys/asoundlib.h>
|
||||||
|
|
||||||
#ifndef MAP_FAILED
|
#include "qtypes.h"
|
||||||
# define MAP_FAILED ((void*)-1)
|
#include "sound.h"
|
||||||
#endif
|
#include "qargs.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
static int snd_inited;
|
static int snd_inited;
|
||||||
|
|
||||||
|
@ -69,22 +46,17 @@ static snd_pcm_t *pcm_handle;
|
||||||
static snd_pcm_params_info_t cpinfo;
|
static snd_pcm_params_info_t cpinfo;
|
||||||
static snd_pcm_params_t params;
|
static snd_pcm_params_t params;
|
||||||
static snd_pcm_setup_t setup;
|
static snd_pcm_setup_t setup;
|
||||||
static snd_pcm_mmap_control_t *mmap_control = NULL;
|
static snd_pcm_channel_area_t mmap_stopped_areas[2];
|
||||||
static snd_pcm_mmap_status_t *mmap_status = NULL;
|
static snd_pcm_channel_area_t mmap_running_areas[2];
|
||||||
static char *mmap_data = NULL;
|
|
||||||
static int card=-1,dev=-1,subdev=-1;;
|
static int card=-1,dev=-1,subdev=-1;;
|
||||||
|
|
||||||
//XXX ugh, not defined in asoundlib.h
|
|
||||||
int snd_pcm_mmap_status(snd_pcm_t *pcm, snd_pcm_mmap_status_t **status);
|
|
||||||
int snd_pcm_mmap_control(snd_pcm_t *pcm, snd_pcm_mmap_control_t **control);
|
|
||||||
|
|
||||||
int check_card(int card)
|
int check_card(int card)
|
||||||
{
|
{
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
snd_ctl_hw_info_t info;
|
snd_ctl_hw_info_t info;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = snd_ctl_hw_open(&handle, card)) < 0) {
|
if ((rc = snd_ctl_hw_open(&handle, 0, card)) < 0) {
|
||||||
Con_Printf("Error: control open (%i): %s\n", card, snd_strerror(rc));
|
Con_Printf("Error: control open (%i): %s\n", card, snd_strerror(rc));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -226,6 +198,8 @@ qboolean SNDDMA_Init(void)
|
||||||
//XXX can't support non-interleaved stereo
|
//XXX can't support non-interleaved stereo
|
||||||
params.xfer_mode = stereo ? SND_PCM_XFER_INTERLEAVED
|
params.xfer_mode = stereo ? SND_PCM_XFER_INTERLEAVED
|
||||||
: SND_PCM_XFER_NONINTERLEAVED;
|
: SND_PCM_XFER_NONINTERLEAVED;
|
||||||
|
params.mmap_shape = stereo ? SND_PCM_XFER_INTERLEAVED
|
||||||
|
: SND_PCM_XFER_NONINTERLEAVED;
|
||||||
params.format.sfmt=format;
|
params.format.sfmt=format;
|
||||||
params.format.rate=rate;
|
params.format.rate=rate;
|
||||||
params.format.channels=stereo+1;
|
params.format.channels=stereo+1;
|
||||||
|
@ -236,7 +210,6 @@ qboolean SNDDMA_Init(void)
|
||||||
params.frag_size=frag_size;
|
params.frag_size=frag_size;
|
||||||
params.avail_min = frag_size;
|
params.avail_min = frag_size;
|
||||||
|
|
||||||
params.xrun_max = 1024;
|
|
||||||
params.boundary = params.buffer_size;
|
params.boundary = params.buffer_size;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -254,11 +227,9 @@ qboolean SNDDMA_Init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
err_msg="audio mmap";
|
err_msg="audio mmap";
|
||||||
if ((rc=snd_pcm_mmap(pcm_handle, (void**)&mmap_data))<0)
|
if ((rc=snd_pcm_mmap(pcm_handle))<0)
|
||||||
goto error;
|
goto error;
|
||||||
if ((rc=snd_pcm_mmap_status(pcm_handle, &mmap_status))<0)
|
if ((rc=snd_pcm_mmap_get_areas(pcm_handle, mmap_stopped_areas, mmap_running_areas)))
|
||||||
goto error;
|
|
||||||
if ((rc=snd_pcm_mmap_control(pcm_handle, &mmap_control))<0)
|
|
||||||
goto error;
|
goto error;
|
||||||
err_msg="audio prepare";
|
err_msg="audio prepare";
|
||||||
if ((rc=snd_pcm_prepare(pcm_handle))<0)
|
if ((rc=snd_pcm_prepare(pcm_handle))<0)
|
||||||
|
@ -273,7 +244,7 @@ qboolean SNDDMA_Init(void)
|
||||||
shm->samplebits=setup.format.sfmt==SND_PCM_SFMT_S16_LE?16:8;
|
shm->samplebits=setup.format.sfmt==SND_PCM_SFMT_S16_LE?16:8;
|
||||||
shm->samples=setup.buffer_size*shm->channels; // mono samples in buffer
|
shm->samples=setup.buffer_size*shm->channels; // mono samples in buffer
|
||||||
shm->speed=setup.format.rate;
|
shm->speed=setup.format.rate;
|
||||||
shm->buffer=(unsigned char*)mmap_data;
|
shm->buffer=(unsigned char*)mmap_running_areas->addr;
|
||||||
Con_Printf("%5d stereo\n", shm->channels - 1);
|
Con_Printf("%5d stereo\n", shm->channels - 1);
|
||||||
Con_Printf("%5d samples\n", shm->samples);
|
Con_Printf("%5d samples\n", shm->samples);
|
||||||
Con_Printf("%5d samplepos\n", shm->samplepos);
|
Con_Printf("%5d samplepos\n", shm->samplepos);
|
||||||
|
@ -292,12 +263,28 @@ qboolean SNDDMA_Init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
get_hw_ptr()
|
||||||
|
{
|
||||||
|
size_t app_ptr;
|
||||||
|
ssize_t delay;
|
||||||
|
int hw_ptr;
|
||||||
|
|
||||||
|
if (snd_pcm_state (pcm_handle) != SND_PCM_STATE_RUNNING)
|
||||||
|
return 0;
|
||||||
|
app_ptr = snd_pcm_mmap_offset (pcm_handle);
|
||||||
|
snd_pcm_delay (pcm_handle, &delay);
|
||||||
|
hw_ptr = app_ptr - delay;
|
||||||
|
return hw_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
int SNDDMA_GetDMAPos(void)
|
int SNDDMA_GetDMAPos(void)
|
||||||
{
|
{
|
||||||
size_t hw_ptr;
|
int hw_ptr;
|
||||||
|
|
||||||
if (!snd_inited) return 0;
|
if (!snd_inited) return 0;
|
||||||
hw_ptr = mmap_status->hw_ptr;
|
|
||||||
//printf("%7d %7d\n", mmap_control->appl_ptr, hw_ptr);
|
hw_ptr = get_hw_ptr();
|
||||||
hw_ptr *= shm->channels;
|
hw_ptr *= shm->channels;
|
||||||
shm->samplepos = hw_ptr;
|
shm->samplepos = hw_ptr;
|
||||||
return shm->samplepos;
|
return shm->samplepos;
|
||||||
|
@ -321,27 +308,41 @@ Send sound to device if buffer isn't really the dma buffer
|
||||||
*/
|
*/
|
||||||
void SNDDMA_Submit(void)
|
void SNDDMA_Submit(void)
|
||||||
{
|
{
|
||||||
int count=paintedtime-soundtime;
|
int count = paintedtime - soundtime;
|
||||||
int rc;
|
int avail;
|
||||||
|
int missed;
|
||||||
|
int state;
|
||||||
|
int hw_ptr;
|
||||||
|
int offset;
|
||||||
|
|
||||||
mmap_control->appl_ptr=mmap_status->hw_ptr+count;
|
state = snd_pcm_state (pcm_handle);
|
||||||
switch (mmap_status->state) {
|
|
||||||
|
switch (state) {
|
||||||
case SND_PCM_STATE_PREPARED:
|
case SND_PCM_STATE_PREPARED:
|
||||||
if ((rc=snd_pcm_start(pcm_handle))<0) {
|
snd_pcm_mmap_forward (pcm_handle, count);
|
||||||
fprintf(stderr, "unable to start playback. %s\n",
|
snd_pcm_start (pcm_handle);
|
||||||
snd_strerror(rc));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SND_PCM_STATE_RUNNING:
|
case SND_PCM_STATE_RUNNING:
|
||||||
break;
|
hw_ptr = get_hw_ptr();
|
||||||
case SND_PCM_STATE_UNDERRUN:
|
missed = hw_ptr - shm->samplepos / shm->channels;
|
||||||
printf("sound underrun\n");
|
count -= missed;
|
||||||
if ((rc=snd_pcm_prepare (pcm_handle))<0) {
|
offset = snd_pcm_mmap_offset (pcm_handle);
|
||||||
fprintf(stderr, "underrun: playback channel prepare error. %s\n",
|
if (offset > hw_ptr)
|
||||||
snd_strerror(rc));
|
count -= (offset - hw_ptr);
|
||||||
exit(1);
|
else
|
||||||
|
count -= (setup.buffer_size - hw_ptr + offset);
|
||||||
|
if (count < 0) {
|
||||||
|
snd_pcm_rewind (pcm_handle, -count);
|
||||||
|
} else if (count > 0) {
|
||||||
|
avail = snd_pcm_avail_update(pcm_handle);
|
||||||
|
if (avail > 0 && count > avail) {
|
||||||
|
snd_pcm_mmap_forward (pcm_handle, avail);
|
||||||
|
count -= avail;
|
||||||
}
|
}
|
||||||
|
snd_pcm_mmap_forward (pcm_handle, count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue