--- /dev/null
+/*
+Copyright (C) 2004 Andreas Kirsch
+
+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 <SDL.h>
+
+/*
+Info:
+One SDL sample consists of x channel samples
+The mixer supposes that the driver has one channel entry/sample though it has x channels/sample
+like the SDL
+*/
+
+#define AUDIO_SDL_SAMPLES 4096
+#define AUDIO_LOCALFACTOR 4
+
+typedef struct AudioState_s
+{
+ int width;
+ int size;
+ int pos;
+ void *buffer;
+} AudioState;
+
+
+extern mempool_t *snd_mempool;
+static AudioState as;
+
+static void Buffer_Callback(void *userdata, Uint8 *stream, int len);
+
+/*
+==================
+S_BlockSound
+==================
+*/
+void S_BlockSound( void )
+{
+ snd_blocked++;
+
+ if( snd_blocked == 1 )
+ SDL_PauseAudio( true );
+}
+
+
+/*
+==================
+S_UnblockSound
+==================
+*/
+void S_UnblockSound( void )
+{
+ snd_blocked--;
+ if( snd_blocked == 0 )
+ SDL_PauseAudio( false );
+}
+
+
+/*
+==================
+SNDDMA_Init
+
+Try to find a sound device to mix for.
+Returns false if nothing is found.
+==================
+*/
+
+qboolean SNDDMA_Init(void)
+{
+ SDL_AudioSpec spec;
+ int i;
+
+ // Init the SDL Audio subsystem
+ if( SDL_InitSubSystem( SDL_INIT_AUDIO ) ) {
+ Con_SafePrint( "Initializing the SDL Audio subsystem failed!\n" );
+ return false;
+ }
+
+ // Init the shm structure
+ memset( (void*) shm, 0, sizeof(*shm) );
+
+ shm->format.channels = 2; //stereo
+ shm->format.width = 2;
+
+ i = COM_CheckParm( "-sndspeed" );
+ if( i && i != ( com_argc - 1 ) )
+ shm->format.speed = atoi( com_argv[ i+1 ] );
+ else
+ shm->format.speed = 44100;
+
+ shm->samplepos = 0;
+ shm->samples = AUDIO_SDL_SAMPLES * AUDIO_LOCALFACTOR;
+ shm->bufferlength = shm->samples * shm->format.width;
+ shm->buffer = Mem_Alloc( snd_mempool, shm->bufferlength );
+
+ // Init the as structure
+ as.buffer = shm->buffer;
+ as.width = shm->format.width;
+ as.pos = 0;
+ as.size = shm->bufferlength;
+
+ // Init the SDL Audio subsystem
+ spec.callback = Buffer_Callback;
+ spec.channels = shm->format.channels;
+ spec.format = AUDIO_S16LSB;
+ spec.freq = shm->format.speed;
+ spec.userdata = NULL;
+ spec.samples = AUDIO_SDL_SAMPLES;
+
+ if( SDL_OpenAudio( &spec, NULL ) ) {
+ Con_SafePrint( "Failed to open the audio device!\n" );
+ Con_DPrintf(
+ "Audio Specification:\n"
+ "\tChannels : %i\n"
+ "\tFormat : %x\n"
+ "\tFrequency : %i\n"
+ "\tBuffersize: %i Bytes(%i Samples)\n",
+ spec.channels, spec.format, spec.freq, shm->bufferlength , spec.samples );
+ Mem_Free( shm->buffer );
+ return false;
+ }
+
+ SDL_PauseAudio( false );
+
+ return true;
+}
+
+/*
+==============
+SNDDMA_GetDMAPos
+
+return the current sample position (in mono samples read)
+inside the recirculating dma buffer, so the mixing code will know
+how many sample are required to fill it up.
+===============
+*/
+int SNDDMA_GetDMAPos(void)
+{
+ shm->samplepos = (as.pos / as.width) % shm->samples;
+ return shm->samplepos;
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+
+}
+
+/*
+==============
+SNDDMA_Shutdown
+
+Reset the sound device for exiting
+===============
+*/
+void SNDDMA_Shutdown(void)
+{
+ SDL_CloseAudio();
+ Mem_Free( as.buffer );
+}
+
+void *S_LockBuffer(void)
+{
+ SDL_LockAudio();
+ return shm->buffer;
+}
+
+void S_UnlockBuffer(void)
+{
+ SDL_UnlockAudio();
+}
+
+static void Buffer_Callback(void *userdata, Uint8 *stream, int len)
+{
+ if( len > as.size )
+ len = as.size;
+ if( len > as.size - as.pos ) {
+ memcpy( stream, (Uint8*) as.buffer + as.pos, as.size - as.pos );
+ len -= as.size - as.pos;
+ as.pos = 0;
+ }
+ memcpy( stream, (Uint8*) as.buffer + as.pos, len );
+ as.pos = (as.pos + len) % as.size;
+}
+