X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_bsd.c;h=0e927f1e8d02fa01c37dd02482c272fa374794ce;hp=6c1bd6ee3583e01bede3ab2b73c3819272bdbe26;hb=2107b65205dbec9522df439f7639c6fe08e54a46;hpb=31bc6f42205f75d58be52a0059c95cdbe90679af diff --git a/snd_bsd.c b/snd_bsd.c index 6c1bd6ee..0e927f1e 100644 --- a/snd_bsd.c +++ b/snd_bsd.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -17,53 +17,48 @@ 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 #include #ifndef SUNOS -#include +# include #endif #include #include #ifndef SUNOS -#include +# include #endif #include -#include "quakedef.h" #include "snd_main.h" -static const int tryrates[] = {44100, 22050, 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]; +/* +==================== +SndSys_Init -qboolean SNDDMA_Init (void) +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; - memset ((void*)shm, 0, sizeof (*shm)); - // Open the audio device #ifdef _PATH_SOUND snddev = _PATH_SOUND; +#elif defined(SUNOS) + snddev = "/dev/audio"; #else -#ifndef SUNOS snddev = "/dev/sound"; -#else - snddev = "/dev/audio"; -#endif #endif audio_fd = open (snddev, O_WRONLY | O_NDELAY | O_NONBLOCK); if (audio_fd < 0) @@ -72,135 +67,177 @@ qboolean SNDDMA_Init (void) 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->format.channels = 2; - shm->format.width = 2; - for (i = 0; i < sizeof (tryrates) / sizeof (tryrates[0]); i++) - { - shm->format.speed = tryrates[i]; - - AUDIO_INITINFO (&info); - info.play.sample_rate = shm->format.speed; - info.play.channels = shm->format.channels; - info.play.precision = shm->format.width * 8; -// 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 -#ifndef SUNOS - info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; + 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_LINEAR; + 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) - break; - } - if (i == sizeof (tryrates) / sizeof (tryrates[0])) + + if (ioctl (audio_fd, AUDIO_SETINFO, &info) != 0) { - Con_Print("Can't select an appropriate sound output format\n"); - close (audio_fd); + Con_Printf("Can't set up the sound device (%s)\n", snddev); 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->format.width; - shm->samplepos = 0; - shm->buffer = dma_buffer; + // TODO: check the parameters with AUDIO_GETINFO + // TODO: check AUDIO_ENCODINGFLAG_EMULATED with AUDIO_GETENC - snd_inited = true; + snd_renderbuffer = Snd_CreateRingBuffer(requested, 0, NULL); return true; } -int SNDDMA_GetDMAPos (void) -{ - audio_info_t info; - if (!snd_inited) - return 0; +/* +==================== +SndSys_Shutdown - if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) +Stop the sound card, delete "snd_renderbuffer" and free its other resources +==================== +*/ +void SndSys_Shutdown (void) +{ + if (audio_fd >= 0) { - Con_Print("Error: can't get audio info\n"); - SNDDMA_Shutdown (); - return 0; + close(audio_fd); + audio_fd = -1; } - return ((info.play.samples * shm->format.channels) % shm->samples); -} - -void SNDDMA_Shutdown (void) -{ - if (snd_inited) + if (snd_renderbuffer != NULL) { - close (audio_fd); - audio_fd = -1; - snd_inited = false; + Mem_Free(snd_renderbuffer->ring); + Mem_Free(snd_renderbuffer); + snd_renderbuffer = NULL; } } + /* -============== -SNDDMA_Submit +==================== +SndSys_Submit -Send sound to device if buffer isn't really the dma buffer -=============== +Submit the contents of "snd_renderbuffer" to the sound card +==================== */ -void SNDDMA_Submit (void) +void SndSys_Submit (void) { - int bsize; - int bytes, b; - static int wbufp = 0; - unsigned char *p; - int idx; - int stop = paintedtime; - - if (!snd_inited) - return; + unsigned int startoffset, factor, limit, nbframes; + int written; - if (paintedtime < wbufp) - wbufp = 0; // reset - - bsize = shm->format.channels * shm->format.width; - bytes = (paintedtime - wbufp) * bsize; - - if (!bytes) + if (audio_fd < 0 || + snd_renderbuffer->startframe == snd_renderbuffer->endframe) return; - if (bytes > sizeof (writebuf)) + 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) { - bytes = sizeof (writebuf); - stop = wbufp + bytes / bsize; + 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; - // 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--) + if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) { - *p++ = dma_buffer[idx]; - idx = (idx + 1) & (sizeof (dma_buffer) - 1); + Con_Print("Error: can't get audio info\n"); + SndSys_Shutdown (); + return 0; } - if (write (audio_fd, writebuf, bytes) < bytes) - Con_Print("audio can't keep up!\n"); + return info.play.samples; +} - wbufp = stop; + +/* +==================== +SndSys_LockRenderBuffer + +Get the exclusive lock on "snd_renderbuffer" +==================== +*/ +qboolean SndSys_LockRenderBuffer (void) +{ + // Nothing to do + return true; } -void *S_LockBuffer (void) + +/* +==================== +SndSys_UnlockRenderBuffer + +Release the exclusive lock on "snd_renderbuffer" +==================== +*/ +void SndSys_UnlockRenderBuffer (void) { - return shm->buffer; + // Nothing to do } -void S_UnlockBuffer (void) +/* +==================== +SndSys_SendKeyEvents + +Send keyboard events originating from the sound system (e.g. MIDI) +==================== +*/ +void SndSys_SendKeyEvents(void) { + // not supported }