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

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