source: abuse/trunk/src/sdlport/sound.cpp @ 28

Last change on this file since 28 was 11, checked in by Sam Hocevar, 17 years ago
  • fixed 64 bit issues here and there.
File size: 6.0 KB
Line 
1/************************
2 * sound.c
3 * SDL port for Abuse
4 * by Anthony Kruize
5 ************************/
6
7#include <SDL.h>
8
9#include "sound.hpp"
10#include "jmalloc.hpp"
11#include "readwav.hpp"
12#include "specs.hpp"
13#include "setup.h"
14
15class effect_handle
16{
17public:
18        effect_handle   *prev;          // Handle to the previous effect
19        effect_handle   *next;          // Handle to the next effect
20        Uint8                   *data;          // Audio data
21        Uint8                   *pos;           // current playing position in the data
22        Uint32                  length;         // Length of the data
23        Uint32                  volume;         // Volume for this effect.
24
25        effect_handle( effect_handle *Next )
26        {
27                next = Next;
28                if( next )
29                {
30                        next->prev = this;
31                }
32                prev = NULL;
33                data = NULL;
34                pos = NULL;
35        }
36
37        ~effect_handle()
38        {
39                if( next )
40                {
41                        next->prev = prev;
42                }
43                if( prev )
44                {
45                        prev->next = next;
46                }
47        }
48};
49
50static effect_handle * fx_list = NULL;
51extern flags_struct flags;
52static int sound_enabled = 0;
53static SDL_AudioSpec audioObtained;
54
55//
56// mix_audio
57//
58// Do the actual playing of the audio by looping through our effects list
59// and mixing each sample.
60//
61void mix_audio(void *udata, Uint8 *stream, int len)
62{
63        effect_handle *handle = fx_list;
64
65        while( handle )
66        {
67                if( handle->length > 0 && handle->pos )
68                {
69                        len = ( len > (int)handle->length ? handle->length : len );
70                        SDL_MixAudio( stream, handle->pos, len, handle->volume );
71                        handle->pos += len;
72                        handle->length -= len;
73                        handle = handle->next;
74                }
75                else
76                {
77                        // update the list pointer if we're deleting the first node
78                        if( fx_list == handle )
79                        {
80                                fx_list = handle->next;
81                        }
82                        effect_handle *tmp = handle->next;
83                        if( !flags.mono )
84                        {
85                                // delete the audio buffer
86                                free( handle->data );
87                        }
88                        delete handle;
89                        handle = tmp;
90                }
91        }
92}
93
94//
95// sound_init()
96// Initialise audio
97//
98int sound_init( int argc, char **argv )
99{
100        SDL_AudioSpec audioWanted;
101        char *sfxdir, *datadir;
102        FILE *fd = NULL;
103
104        // Disable sound if requested.
105        if( flags.nosound )
106        {
107                // User requested that sound be disabled
108                printf( "Sound : Disabled (-nosound)\n" );
109                return 0;
110        }
111
112        // Check for the sfx directory, disable sound if we can't find it.
113        datadir = get_filename_prefix();
114        sfxdir = (char *)jmalloc( strlen( datadir ) + 5 + 1, "sfxdir" );
115        sprintf( sfxdir, "%s/sfx/", datadir );
116        if( (fd = fopen( sfxdir,"r" )) == NULL )
117        {
118                // Didn't find the directory, so disable sound.
119                printf( "Sound : Disabled (couldn't find the sfx directory)\n" );
120                return 0;
121        }
122        jfree( sfxdir );
123
124        audioWanted.freq = 11025;
125        audioWanted.format = AUDIO_U8;
126        audioWanted.channels = 2 - flags.mono;
127        audioWanted.samples = 128;
128        audioWanted.callback = mix_audio;
129        audioWanted.userdata = NULL;
130
131        // Now open the audio device
132        if( SDL_OpenAudio( &audioWanted, &audioObtained ) < 0 )
133        {
134                printf( "Sound : Unable to open audio - %s\nSound : Disabled (error)\n", SDL_GetError() );
135                return 0;
136        }
137
138        sound_enabled = 1;
139        printf( "Sound : Enabled\n" );
140
141        SDL_PauseAudio( 0 );
142
143        // It's all good
144        return sound_enabled;
145}
146
147//
148// sound_uninit
149//
150// Shutdown audio and release any memory left over.
151//
152void sound_uninit()
153{
154        if( sound_enabled )
155        {
156                SDL_PauseAudio( 1 );
157                while( fx_list )
158                {
159                        effect_handle *last = fx_list;
160                        fx_list = fx_list->next;
161                        jfree( last );
162                }
163                SDL_CloseAudio();
164        }
165}
166
167//
168// sound_effect constructor
169//
170// Read in the requested .wav file.
171//
172sound_effect::sound_effect( char * filename )
173{
174        if( sound_enabled )
175        {
176                long sample_speed;
177                data = (void *)read_wav( filename, sample_speed, size );
178        }
179}
180
181//
182// sound_effect destructor
183//
184// Release the audio data.
185//
186sound_effect::~sound_effect()
187{
188        if( sound_enabled )
189        {
190                if( data )
191                {
192                        jfree( data );
193                }
194        }
195}
196
197//
198// sound_effect::play
199//
200// Insert a new effect_handle into the list and modify the audio
201// if we're doing stereo.
202// panpot defines the pan position for the sound effect.
203//   0   - Completely to the right.
204//   128 - Centered.
205//   255 - Completely to the left.
206//
207void sound_effect::play( int volume, int pitch, int panpot )
208{
209        if( sound_enabled )
210        {
211                SDL_LockAudio();
212
213                fx_list = new effect_handle( fx_list );
214                if( fx_list == NULL )
215                {
216                        printf( "Sound : ERROR - Failed to create new effect.\n" );
217                        SDL_UnlockAudio();
218                        return;
219                }
220
221                if( !flags.mono )
222                {
223                        unsigned int i;
224                        Uint32 cvtBufferSize;
225                        SDL_AudioCVT audiocvt;
226
227                        // Do some audio conversion
228                        SDL_BuildAudioCVT( &audiocvt, AUDIO_U8, 1, 11025, audioObtained.format, audioObtained.channels, audioObtained.freq );
229                        audiocvt.buf = (Uint8 *)malloc( size * audiocvt.len_mult );
230                        audiocvt.len = size;
231                        memcpy( audiocvt.buf, data, size );
232                        SDL_ConvertAudio( &audiocvt );
233                        cvtBufferSize = (Uint32)((double)size * audiocvt.len_ratio);
234
235                        // Adjust for requested pan position
236                        if( panpot != 128 )
237                        {
238                                if( panpot > 128 )
239                                {
240                                        // Pan to the left
241                                        panpot = (panpot - 255) * -1;
242                                        for( i = 1 ; i <= cvtBufferSize; i += 2 )
243                                        {
244                                                audiocvt.buf[i] = (((audiocvt.buf[i] - 128) * panpot) / 128) + 128;
245                                        }
246                                }
247                                else
248                                {
249                                        // Pan to the right
250                                        for( i = 0 ; i < cvtBufferSize; i += 2 )
251                                        {
252                                                audiocvt.buf[i] = (((audiocvt.buf[i] - 128) * panpot) / 128) + 128;
253                                        }
254                                }
255                        }
256
257                        fx_list->data = audiocvt.buf;
258                        fx_list->pos = audiocvt.buf;
259                        fx_list->length = cvtBufferSize;
260                        fx_list->volume = volume;
261                }
262                else
263                {
264                        // Only doing mono so don't mess with the audio data.
265                        fx_list->data = (Uint8 *)data;
266                        fx_list->pos = (Uint8 *)data;
267                        fx_list->length = size;
268                        fx_list->volume = volume;
269                }
270                SDL_UnlockAudio();
271        }
272}
273
274
275//
276// We don't handle songs.  These are just stubs to basically do nothing.
277// I tried using SDL_mixer to do this, but with no success.
278//
279
280song::song( char * filename )
281{
282        data = NULL;
283        Name = strcpy((char *)jmalloc( strlen( filename ) + 1, "song name" ), filename );
284        song_id = 0;
285}
286
287song::~song()
288{
289        if( playing() )
290        {
291                stop();
292        }
293        if( data )
294        {
295                jfree( data );
296        }
297        jfree( Name );
298}
299
300void song::play( unsigned char volume )
301{
302        song_id = 1;
303}
304
305void song::stop( long fadeout_time )
306{
307        song_id = 0;
308}
309
310int song::playing()
311{
312        return song_id;
313}
314
315void song::set_volume( int volume )
316{
317//      do nothing...
318}
Note: See TracBrowser for help on using the repository browser.