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 // COMMANDLINEOPTION: SDL Sound: -sndquad sets sound output to 4 channel surround
105 if ((i=COM_CheckParm("-sndquad")) != 0)
108 // Init the SDL Audio subsystem
109 wantspec.callback = Buffer_Callback;
110 wantspec.userdata = NULL;
111 wantspec.freq = 44100;
112 // COMMANDLINEOPTION: SDL Sound: -sndspeed <hz> chooses sound output rate (try values such as 44100, 48000, 22050, 11025 (quake), 24000, 32000, 96000, 192000, etc)
113 i = COM_CheckParm( "-sndspeed" );
114 if( i && i != ( com_argc - 1 ) )
115 wantspec.freq = atoi( com_argv[ i+1 ] );
116 wantspec.format = AUDIO_S16SYS;
117 wantspec.channels = channels;
118 wantspec.samples = AUDIO_SDL_SAMPLEFRAMES;
120 if( SDL_OpenAudio( &wantspec, NULL ) )
122 Con_Printf("%s\n", SDL_GetError());
126 // Init the shm structure
127 memset( (void*) shm, 0, sizeof(*shm) );
128 shm->format.channels = wantspec.channels;
129 shm->format.width = 2;
130 shm->format.speed = wantspec.freq;
133 shm->sampleframes = wantspec.samples * AUDIO_LOCALFACTOR;
134 shm->samples = shm->sampleframes * shm->format.channels;
135 shm->bufferlength = shm->samples * shm->format.width;
136 shm->buffer = (unsigned char *)Mem_Alloc( snd_mempool, shm->bufferlength );
138 // Init the as structure
139 as.buffer = shm->buffer;
140 as.width = shm->format.width;
142 as.size = shm->bufferlength;
147 Con_Print( "Failed to open the audio device!\n" );
149 "Audio Specification:\n"
154 wantspec.channels, wantspec.format, wantspec.freq, wantspec.samples );
158 SDL_PauseAudio( false );
167 return the current sample position (in mono samples read)
168 inside the recirculating dma buffer, so the mixing code will know
169 how many sample are required to fill it up.
172 int SNDDMA_GetDMAPos(void)
174 shm->samplepos = (as.pos / as.width) % shm->samples;
175 return shm->samplepos;
182 Send sound to device if buffer isn't really the dma buffer
185 void SNDDMA_Submit(void)
194 Reset the sound device for exiting
197 void SNDDMA_Shutdown(void)
200 Mem_Free( as.buffer );
203 void *S_LockBuffer(void)
209 void S_UnlockBuffer(void)
214 static void Buffer_Callback(void *userdata, Uint8 *stream, int len)
218 if( len > as.size - as.pos ) {
219 memcpy( stream, (Uint8*) as.buffer + as.pos, as.size - as.pos );
220 len -= as.size - as.pos;
223 memcpy( stream, (Uint8*) as.buffer + as.pos, len );
224 as.pos = (as.pos + len) % as.size;