mirror of
https://github.com/DrBeef/QuakeQuest.git
synced 2024-11-30 16:01:08 +00:00
244 lines
5.2 KiB
C
244 lines
5.2 KiB
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 the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
|
||
|
*/
|
||
|
#include "quakedef.h"
|
||
|
|
||
|
#include <sys/param.h>
|
||
|
#include <sys/audioio.h>
|
||
|
#ifndef SUNOS
|
||
|
# include <sys/endian.h>
|
||
|
#endif
|
||
|
#include <sys/ioctl.h>
|
||
|
|
||
|
#include <fcntl.h>
|
||
|
#ifndef SUNOS
|
||
|
# include <paths.h>
|
||
|
#endif
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "snd_main.h"
|
||
|
|
||
|
|
||
|
static int audio_fd = -1;
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_Init
|
||
|
|
||
|
Create "snd_renderbuffer" with the proper sound format if the call is successful
|
||
|
May return a suggested format if the requested format isn't available
|
||
|
====================
|
||
|
*/
|
||
|
qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
const char *snddev;
|
||
|
audio_info_t info;
|
||
|
|
||
|
// Open the audio device
|
||
|
#ifdef _PATH_SOUND
|
||
|
snddev = _PATH_SOUND;
|
||
|
#elif defined(SUNOS)
|
||
|
snddev = "/dev/audio";
|
||
|
#else
|
||
|
snddev = "/dev/sound";
|
||
|
#endif
|
||
|
audio_fd = open (snddev, O_WRONLY | O_NDELAY | O_NONBLOCK);
|
||
|
if (audio_fd < 0)
|
||
|
{
|
||
|
Con_Printf("Can't open the sound device (%s)\n", snddev);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
AUDIO_INITINFO (&info);
|
||
|
#ifdef AUMODE_PLAY // NetBSD / OpenBSD
|
||
|
info.mode = AUMODE_PLAY;
|
||
|
#endif
|
||
|
info.play.sample_rate = requested->speed;
|
||
|
info.play.channels = requested->channels;
|
||
|
info.play.precision = requested->width * 8;
|
||
|
if (requested->width == 1)
|
||
|
#ifdef SUNOS
|
||
|
info.play.encoding = AUDIO_ENCODING_LINEAR8;
|
||
|
#else
|
||
|
info.play.encoding = AUDIO_ENCODING_ULINEAR;
|
||
|
#endif
|
||
|
else
|
||
|
#ifdef SUNOS
|
||
|
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||
|
#else
|
||
|
if (mem_bigendian)
|
||
|
info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
|
||
|
else
|
||
|
info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
|
||
|
#endif
|
||
|
|
||
|
if (ioctl (audio_fd, AUDIO_SETINFO, &info) != 0)
|
||
|
{
|
||
|
Con_Printf("Can't set up the sound device (%s)\n", snddev);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// TODO: check the parameters with AUDIO_GETINFO
|
||
|
// TODO: check AUDIO_ENCODINGFLAG_EMULATED with AUDIO_GETENC
|
||
|
|
||
|
snd_renderbuffer = Snd_CreateRingBuffer(requested, 0, NULL);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_Shutdown
|
||
|
|
||
|
Stop the sound card, delete "snd_renderbuffer" and free its other resources
|
||
|
====================
|
||
|
*/
|
||
|
void SndSys_Shutdown (void)
|
||
|
{
|
||
|
if (audio_fd >= 0)
|
||
|
{
|
||
|
close(audio_fd);
|
||
|
audio_fd = -1;
|
||
|
}
|
||
|
|
||
|
if (snd_renderbuffer != NULL)
|
||
|
{
|
||
|
Mem_Free(snd_renderbuffer->ring);
|
||
|
Mem_Free(snd_renderbuffer);
|
||
|
snd_renderbuffer = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_Submit
|
||
|
|
||
|
Submit the contents of "snd_renderbuffer" to the sound card
|
||
|
====================
|
||
|
*/
|
||
|
void SndSys_Submit (void)
|
||
|
{
|
||
|
unsigned int startoffset, factor, limit, nbframes;
|
||
|
int written;
|
||
|
|
||
|
if (audio_fd < 0 ||
|
||
|
snd_renderbuffer->startframe == snd_renderbuffer->endframe)
|
||
|
return;
|
||
|
|
||
|
startoffset = snd_renderbuffer->startframe % snd_renderbuffer->maxframes;
|
||
|
factor = snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
|
||
|
limit = snd_renderbuffer->maxframes - startoffset;
|
||
|
nbframes = snd_renderbuffer->endframe - snd_renderbuffer->startframe;
|
||
|
if (nbframes > limit)
|
||
|
{
|
||
|
written = write (audio_fd, &snd_renderbuffer->ring[startoffset * factor], limit * factor);
|
||
|
if (written < 0)
|
||
|
{
|
||
|
Con_Printf("SndSys_Submit: audio write returned %d!\n", written);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (written % factor != 0)
|
||
|
Sys_Error("SndSys_Submit: nb of bytes written (%d) isn't aligned to a frame sample!\n", written);
|
||
|
|
||
|
snd_renderbuffer->startframe += written / factor;
|
||
|
|
||
|
if ((unsigned int)written < limit * factor)
|
||
|
{
|
||
|
Con_Printf("SndSys_Submit: audio can't keep up! (%u < %u)\n", written, limit * factor);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
nbframes -= limit;
|
||
|
startoffset = 0;
|
||
|
}
|
||
|
|
||
|
written = write (audio_fd, &snd_renderbuffer->ring[startoffset * factor], nbframes * factor);
|
||
|
if (written < 0)
|
||
|
{
|
||
|
Con_Printf("SndSys_Submit: audio write returned %d!\n", written);
|
||
|
return;
|
||
|
}
|
||
|
snd_renderbuffer->startframe += written / factor;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_GetSoundTime
|
||
|
|
||
|
Returns the number of sample frames consumed since the sound started
|
||
|
====================
|
||
|
*/
|
||
|
unsigned int SndSys_GetSoundTime (void)
|
||
|
{
|
||
|
audio_info_t info;
|
||
|
|
||
|
if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0)
|
||
|
{
|
||
|
Con_Print("Error: can't get audio info\n");
|
||
|
SndSys_Shutdown ();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return info.play.samples;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_LockRenderBuffer
|
||
|
|
||
|
Get the exclusive lock on "snd_renderbuffer"
|
||
|
====================
|
||
|
*/
|
||
|
qboolean SndSys_LockRenderBuffer (void)
|
||
|
{
|
||
|
// Nothing to do
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_UnlockRenderBuffer
|
||
|
|
||
|
Release the exclusive lock on "snd_renderbuffer"
|
||
|
====================
|
||
|
*/
|
||
|
void SndSys_UnlockRenderBuffer (void)
|
||
|
{
|
||
|
// Nothing to do
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
====================
|
||
|
SndSys_SendKeyEvents
|
||
|
|
||
|
Send keyboard events originating from the sound system (e.g. MIDI)
|
||
|
====================
|
||
|
*/
|
||
|
void SndSys_SendKeyEvents(void)
|
||
|
{
|
||
|
// not supported
|
||
|
}
|