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

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