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

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