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 >= 2;channels -= 2)
94 // Init the SDL Audio subsystem
95 wantspec.callback = Buffer_Callback;
96 wantspec.userdata = NULL;
97 wantspec.freq = 44100;
98 // COMMANDLINEOPTION: SDL Sound: -sndspeed <hz> chooses sound output rate (try values such as 44100, 48000, 22050, 11025 (quake), 24000, 32000, 96000, 192000, etc)
99 i = COM_CheckParm( "-sndspeed" );
100 if( i && i != ( com_argc - 1 ) )
101 wantspec.freq = atoi( com_argv[ i+1 ] );
102 wantspec.format = AUDIO_S16SYS;
103 wantspec.channels = channels;
104 wantspec.samples = AUDIO_SDL_SAMPLEFRAMES;
106 if( SDL_OpenAudio( &wantspec, NULL ) )
108 Con_Printf("%s\n", SDL_GetError());
112 // Init the shm structure
113 memset( (void*) shm, 0, sizeof(*shm) );
114 shm->format.channels = wantspec.channels;
115 shm->format.width = 2;
116 shm->format.speed = wantspec.freq;
119 shm->sampleframes = wantspec.samples * AUDIO_LOCALFACTOR;
120 shm->samples = shm->sampleframes * shm->format.channels;
121 shm->bufferlength = shm->samples * shm->format.width;
122 shm->buffer = (unsigned char *)Mem_Alloc( snd_mempool, shm->bufferlength );
124 // Init the as structure
125 as.buffer = shm->buffer;
126 as.width = shm->format.width;
128 as.size = shm->bufferlength;
133 Con_Print( "Failed to open the audio device!\n" );
135 "Audio Specification:\n"
140 wantspec.channels, wantspec.format, wantspec.freq, wantspec.samples );
144 SDL_PauseAudio( false );
153 return the current sample position (in mono samples read)
154 inside the recirculating dma buffer, so the mixing code will know
155 how many sample are required to fill it up.
158 int SNDDMA_GetDMAPos(void)
160 shm->samplepos = (as.pos / as.width) % shm->samples;
161 return shm->samplepos;
168 Send sound to device if buffer isn't really the dma buffer
171 void SNDDMA_Submit(void)
180 Reset the sound device for exiting
183 void SNDDMA_Shutdown(void)
186 Mem_Free( as.buffer );
189 void *S_LockBuffer(void)
195 void S_UnlockBuffer(void)
200 static void Buffer_Callback(void *userdata, Uint8 *stream, int len)
204 if( len > as.size - as.pos ) {
205 memcpy( stream, (Uint8*) as.buffer + as.pos, as.size - as.pos );
206 len -= as.size - as.pos;
209 memcpy( stream, (Uint8*) as.buffer + as.pos, len );
210 as.pos = (as.pos + len) % as.size;