2 Copyright (C) 2004 Andreas Kirsch
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 SDL samples are really frames (full set of samples for all speakers)
28 #define AUDIO_SDL_SAMPLEFRAMES 4096
29 #define AUDIO_LOCALFACTOR 4
31 typedef struct AudioState_s
42 static void Buffer_Callback(void *userdata, Uint8 *stream, int len);
49 void S_BlockSound( void )
53 if( snd_blocked == 1 )
54 SDL_PauseAudio( true );
63 void S_UnblockSound( void )
66 if( snd_blocked == 0 )
67 SDL_PauseAudio( false );
75 Try to find a sound device to mix for.
76 Returns false if nothing is found.
80 qboolean SNDDMA_Init(void)
82 SDL_AudioSpec wantspec;
86 // Init the SDL Audio subsystem
87 if( SDL_InitSubSystem( SDL_INIT_AUDIO ) ) {
88 Con_Print( "Initializing the SDL Audio subsystem failed!\n" );
92 for (channels = 8;channels >= 1;channels--)
94 if ((channels & 1) && channels != 1)
96 // COMMANDLINEOPTION: SDL Sound: -sndmono sets sound output to mono
97 if ((i=COM_CheckParm("-sndmono")) != 0)
100 // COMMANDLINEOPTION: SDL Sound: -sndstereo sets sound output to stereo
101 if ((i=COM_CheckParm("-sndstereo")) != 0)
104 // Init the SDL Audio subsystem
105 wantspec.callback = Buffer_Callback;
106 wantspec.userdata = NULL;
107 wantspec.freq = 44100;
108 // COMMANDLINEOPTION: SDL Sound: -sndspeed <hz> chooses sound output rate (try values such as 44100, 48000, 22050, 11025 (quake), 24000, 32000, 96000, 192000, etc)
109 i = COM_CheckParm( "-sndspeed" );
110 if( i && i != ( com_argc - 1 ) )
111 wantspec.freq = atoi( com_argv[ i+1 ] );
112 wantspec.format = AUDIO_S16SYS;
113 wantspec.channels = channels;
114 wantspec.samples = AUDIO_SDL_SAMPLEFRAMES;
116 if( SDL_OpenAudio( &wantspec, NULL ) )
118 Con_Printf("%s\n", SDL_GetError());
122 // Init the shm structure
123 memset( (void*) shm, 0, sizeof(*shm) );
124 shm->format.channels = wantspec.channels;
125 shm->format.width = 2;
126 shm->format.speed = wantspec.freq;
129 shm->sampleframes = wantspec.samples * AUDIO_LOCALFACTOR;
130 shm->samples = shm->sampleframes * shm->format.channels;
131 shm->bufferlength = shm->samples * shm->format.width;
132 shm->buffer = (unsigned char *)Mem_Alloc( snd_mempool, shm->bufferlength );
134 // Init the as structure
135 as.buffer = shm->buffer;
136 as.width = shm->format.width;
138 as.size = shm->bufferlength;
143 Con_Print( "Failed to open the audio device!\n" );
145 "Audio Specification:\n"
150 wantspec.channels, wantspec.format, wantspec.freq, wantspec.samples );
154 SDL_PauseAudio( false );
163 return the current sample position (in mono samples read)
164 inside the recirculating dma buffer, so the mixing code will know
165 how many sample are required to fill it up.
168 int SNDDMA_GetDMAPos(void)
170 shm->samplepos = (as.pos / as.width) % shm->samples;
171 return shm->samplepos;
178 Send sound to device if buffer isn't really the dma buffer
181 void SNDDMA_Submit(void)
190 Reset the sound device for exiting
193 void SNDDMA_Shutdown(void)
196 Mem_Free( as.buffer );
199 void *S_LockBuffer(void)
205 void S_UnlockBuffer(void)
210 static void Buffer_Callback(void *userdata, Uint8 *stream, int len)
214 if( len > as.size - as.pos ) {
215 memcpy( stream, (Uint8*) as.buffer + as.pos, as.size - as.pos );
216 len -= as.size - as.pos;
219 memcpy( stream, (Uint8*) as.buffer + as.pos, len );
220 as.pos = (as.pos + len) % as.size;