From: molivier Date: Mon, 12 Jan 2004 07:38:15 +0000 (+0000) Subject: Added sound support to the NetBSD port. Most of the code comes from the original... X-Git-Tag: xonotic-v0.1.0preview~6160 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=1a56b0b13baaaf613db6e01542e7e3f2d143c8d5;ds=sidebyside Added sound support to the NetBSD port. Most of the code comes from the original "snd_sun.c" file, by id Software. Some TODO remains, including the support for the "-snd*" options. Hopefully, the BSD specific code in DP works for the 3 majors BSD flavors, though I cannot test it on FreeBSD and OpenBSD anyway (feedback and test welcome if you have a BSD box at your disposal). git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3805 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/makefile.bsd b/makefile.bsd index faa17cb5..7eb97cc4 100644 --- a/makefile.bsd +++ b/makefile.bsd @@ -5,7 +5,8 @@ CC=gcc MAKE:=$(MAKE) -f makefile.bsd -OBJ_BSDSOUND=snd_null.o +OBJ_BSDSOUND=snd_bsd.o snd_dma.o snd_mix.o snd_mem.o ogg.o +#OBJ_BSDSOUND=snd_null.o BSDSOUNDLIB= #if you want CD sound in BSD diff --git a/snd_bsd.c b/snd_bsd.c new file mode 100644 index 00000000..a771b4c5 --- /dev/null +++ b/snd_bsd.c @@ -0,0 +1,188 @@ +/* +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 +#include +#include +#include + +#include +#include +#include + +#include "quakedef.h" + + +static const int tryrates[] = {44100, 22051, 11025, 8000}; + +static int audio_fd = -1; +static qboolean snd_inited = false; + +// TODO: allocate them in SNDDMA_Init, with a size depending on +// the sound format (enough for 0.5 sec of sound for instance) +#define SND_BUFF_SIZE 65536 +static qbyte dma_buffer [SND_BUFF_SIZE]; +static qbyte writebuf [SND_BUFF_SIZE]; + + +qboolean SNDDMA_Init (void) +{ + unsigned int i; + const char *snddev = _PATH_SOUND; + audio_info_t info; + + memset ((void*)shm, 0, sizeof (*shm)); + + // Open the audio device + 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; + } + + // Look for an appropriate sound format + // TODO: we should also test mono/stereo and bits + // TODO: support "-sndspeed", "-sndbits", "-sndmono" and "-sndstereo" + shm->channels = 2; + shm->samplebits = 16; + for (i = 0; i < sizeof (tryrates) / sizeof (tryrates[0]); i++) + { + shm->speed = tryrates[i]; + + AUDIO_INITINFO (&info); + info.play.sample_rate = shm->speed; + info.play.channels = shm->channels; + info.play.precision = shm->samplebits; +// We only handle sound cards of the same endianess than the CPU +#if BYTE_ORDER == BIG_ENDIAN + info.play.encoding = AUDIO_ENCODING_SLINEAR_BE; +#else + info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; +#endif + if (ioctl (audio_fd, AUDIO_SETINFO, &info) == 0) + break; + } + if (i == sizeof (tryrates) / sizeof (tryrates[0])) + { + Con_Printf ("Can't select an appropriate sound output format\n"); + close (audio_fd); + return false; + } + + // Print some information + Con_Printf ("%d bit %s sound initialized (rate: %dHz)\n", + info.play.precision, + (info.play.channels == 2) ? "stereo" : "mono", + info.play.sample_rate); + + shm->samples = sizeof (dma_buffer) / (shm->samplebits / 8); + shm->samplepos = 0; + shm->buffer = dma_buffer; + + snd_inited = true; + return true; +} + +int SNDDMA_GetDMAPos (void) +{ + audio_info_t info; + + if (!snd_inited) + return 0; + + if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) + { + Con_Printf ("Error: can't get audio info\n"); + SNDDMA_Shutdown (); + return 0; + } + + return ((info.play.samples * shm->channels) % shm->samples); +} + +void SNDDMA_Shutdown (void) +{ + if (snd_inited) + { + close (audio_fd); + audio_fd = -1; + snd_inited = false; + } +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit (void) +{ + int bsize; + int bytes, b; + static int wbufp = 0; + unsigned char *p; + int idx; + int stop = paintedtime; + + if (!snd_inited) + return; + + 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; + } + + // Transfert the sound data from the circular dma_buffer to writebuf + // TODO: using 2 memcpys instead of this loop should be faster + p = writebuf; + idx = (wbufp*bsize) & (sizeof (dma_buffer) - 1); + for (b = bytes; b; b--) + { + *p++ = dma_buffer[idx]; + idx = (idx + 1) & (sizeof (dma_buffer) - 1); + } + + if (write (audio_fd, writebuf, bytes) < bytes) + Con_Printf ("audio can't keep up!\n"); + + wbufp = stop; +} + +void *S_LockBuffer (void) +{ + return shm->buffer; +} + +void S_UnlockBuffer (void) +{ +} diff --git a/snd_dma.c b/snd_dma.c index 9035546a..5fa7234f 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -817,12 +817,8 @@ void GetSoundtime(void) // it is possible to miscount buffers if it has wrapped twice between // calls to S_Update. Oh well. -#ifdef __sun__ - soundtime = SNDDMA_GetSamples(); -#else samplepos = SNDDMA_GetDMAPos(); - if (samplepos < oldsamplepos) { buffers++; // buffer wrapped @@ -837,7 +833,6 @@ void GetSoundtime(void) oldsamplepos = samplepos; soundtime = buffers*fullsamples + samplepos/shm->channels; -#endif } void IN_Accumulate (void);