X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_bsd.c;h=e32766f11dea6f2d94ff08990e8629d4ddd4e097;hp=a771b4c5a8d7de4d3ffbcc27755dd8ba58fe7e05;hb=7d115bb0e31921e2e0519a39637985efef1391f4;hpb=1a56b0b13baaaf613db6e01542e7e3f2d143c8d5 diff --git a/snd_bsd.c b/snd_bsd.c index a771b4c5..e32766f1 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,172 +17,216 @@ 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 -#include +#ifndef SUNOS +# include +#endif #include #include -#include +#ifndef SUNOS +# include +#endif #include -#include "quakedef.h" - +#include "snd_main.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]; +/* +==================== +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 = _PATH_SOUND; + 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 + 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); + 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; + 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 BYTE_ORDER == BIG_ENDIAN + info.play.encoding = AUDIO_ENCODING_SLINEAR_BE; +# else info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; +# endif #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_Printf ("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->samplebits / 8); - 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_Printf ("Error: can't get audio info\n"); - SNDDMA_Shutdown (); - return 0; + close(audio_fd); + audio_fd = -1; } - return ((info.play.samples * shm->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; - - if (paintedtime < wbufp) - wbufp = 0; // reset + unsigned int startoffset, factor, limit, nbframes; + int written; - bsize = shm->channels * (shm->samplebits / 8); - 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) { - bytes = sizeof (writebuf); - stop = wbufp + bytes / bsize; + 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; } - // 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--) + written = write (audio_fd, &snd_renderbuffer->ring[startoffset * factor], nbframes * factor); + if (written < 0) { - *p++ = dma_buffer[idx]; - idx = (idx + 1) & (sizeof (dma_buffer) - 1); + Con_Printf("SndSys_Submit: audio write returned %d!\n", written); + return; } + snd_renderbuffer->startframe += written / factor; +} + + +/* +==================== +SndSys_GetSoundTime - if (write (audio_fd, writebuf, bytes) < bytes) - Con_Printf ("audio can't keep up!\n"); +Returns the number of sample frames consumed since the sound started +==================== +*/ +unsigned int SndSys_GetSoundTime (void) +{ + audio_info_t info; - wbufp = stop; + 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; } -void *S_LockBuffer (void) + +/* +==================== +SndSys_LockRenderBuffer + +Get the exclusive lock on "snd_renderbuffer" +==================== +*/ +qboolean SndSys_LockRenderBuffer (void) { - return shm->buffer; + // Nothing to do + return true; } -void S_UnlockBuffer (void) + +/* +==================== +SndSys_UnlockRenderBuffer + +Release the exclusive lock on "snd_renderbuffer" +==================== +*/ +void SndSys_UnlockRenderBuffer (void) { + // Nothing to do }