]> git.mxchange.org Git - simgear.git/blob - simgear/sound/soundmgr_openal.cxx
Compile time fixes needed to build SimGear on recent cygwin versions.
[simgear.git] / simgear / sound / soundmgr_openal.cxx
1 // soundmgr.cxx -- Sound effect management class
2 //
3 // Sound manager initially written by David Findlay
4 // <david_j_findlay@yahoo.com.au> 2001
5 //
6 // C++-ified by Curtis Olson, started March 2001.
7 //
8 // Copyright (C) 2001  Curtis L. Olson - http://www.flightgear.org/~curt
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 //
24 // $Id$
25
26 #ifdef HAVE_CONFIG_H
27 #  include <simgear_config.h>
28 #endif
29
30 #include <simgear/compiler.h>
31
32 #if defined(__APPLE__)
33 # include <OpenAL/al.h>
34 # include <OpenAL/alc.h>
35 #else
36 # include <AL/al.h>
37 # include <AL/alc.h>
38 #endif
39
40 #if defined (__APPLE__)
41 #  ifdef __GNUC__
42 #    if ( __GNUC__ >= 3 ) && ( __GNUC_MINOR__ >= 3 )
43 //  #        include <math.h>
44 inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
45 #    else
46     // any C++ header file undefines isinf and isnan
47     // so this should be included before <iostream>
48     // the functions are STILL in libm (libSystem on mac os x)
49 extern "C" int isnan (double);
50 extern "C" int isinf (double);
51 #    endif
52 #  else
53 //    inline int (isinf)(double r) { return isinf(r); }
54 //    inline int (isnan)(double r) { return isnan(r); }
55 #  endif
56 #endif
57
58 #if defined (__FreeBSD__)
59 #  if __FreeBSD_version < 500000
60      extern "C" {
61        inline int isnan(double r) { return !(r <= 0 || r >= 0); }
62      }
63 #  endif
64 #endif
65
66 #if defined (__CYGWIN__)
67 #include <ieeefp.h>
68 #endif
69
70
71 #include STL_IOSTREAM
72
73 #include <simgear/debug/logstream.hxx>
74 #include <simgear/misc/sg_path.hxx>
75
76 #include "soundmgr_openal.hxx"
77
78 #if defined(__MINGW32__)
79 #define isnan(x) _isnan(x)
80 #endif
81
82 //
83 // Sound Manager
84 //
85
86 // constructor
87 SGSoundMgr::SGSoundMgr() {
88
89     SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" );
90
91     // initialize OpenAL
92 #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
93     if (!alutInit(NULL, NULL))
94     {
95         ALenum error = alutGetError ();
96         SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
97         SG_LOG( SG_GENERAL, SG_ALERT, "   "+string(alutGetErrorString(error)));
98         working = false;
99         context = 0;
100     }
101     else
102     {
103         working = true;
104         context = alcGetCurrentContext();
105     }
106 #else
107     if ( (dev = alcOpenDevice( NULL )) != NULL
108             && ( context = alcCreateContext( dev, NULL )) != NULL ) {
109         working = true;
110         alcMakeContextCurrent( context );
111     } else {
112         working = false;
113         context = 0;
114         SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
115     }
116 #endif
117
118     listener_pos[0] = 0.0;
119     listener_pos[1] = 0.0;
120     listener_pos[2] = 0.0;
121
122     listener_vel[0] = 0.0;
123     listener_vel[1] = 0.0;
124     listener_vel[2] = 0.0;
125     
126     listener_ori[0] = 0.0;
127     listener_ori[1] = 0.0;
128     listener_ori[2] = -1.0;
129     listener_ori[3] = 0.0;
130     listener_ori[4] = 1.0;
131     listener_ori[5] = 0.0;
132
133     alListenerf( AL_GAIN, 0.0f );
134     alListenerfv( AL_POSITION, listener_pos );
135     alListenerfv( AL_VELOCITY, listener_vel );
136     alListenerfv( AL_ORIENTATION, listener_ori );
137     alGetError();
138     if ( alGetError() != AL_NO_ERROR) {
139         SG_LOG( SG_GENERAL, SG_ALERT,
140                 "Oops AL error after audio initialization!" );
141     }
142
143     // exaggerate the ear candy?
144     alDopplerFactor(1.0);
145     alDopplerVelocity(340.0);   // speed of sound in meters per second.
146 }
147
148 // destructor
149
150 SGSoundMgr::~SGSoundMgr() {
151
152 #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
153     alutExit ();
154 #else
155     if (context)
156         alcDestroyContext( context );
157 #endif
158 }
159
160
161 // initialize the sound manager
162 void SGSoundMgr::init() {
163     //
164     // Remove the samples from the sample manager.
165     //
166     samples.clear();
167 }
168
169
170 void SGSoundMgr::bind ()
171 {
172     // no properties
173 }
174
175
176 void SGSoundMgr::unbind ()
177 {
178     // no properties
179 }
180
181
182 // run the audio scheduler
183 void SGSoundMgr::update( double dt ) {
184 }
185
186
187 void
188 SGSoundMgr::pause ()
189 {
190     if (context) {
191         alcSuspendContext( context );
192         if ( alGetError() != AL_NO_ERROR) {
193             SG_LOG( SG_GENERAL, SG_ALERT,
194                     "Oops AL error after soundmgr pause()!" );
195         }
196     }
197 }
198
199
200 void
201 SGSoundMgr::resume ()
202 {
203     if (context) {
204         alcProcessContext( context );
205         if ( alGetError() != AL_NO_ERROR) {
206             SG_LOG( SG_GENERAL, SG_ALERT,
207                     "Oops AL error after soundmgr resume()!" );
208         }
209     }
210 }
211
212
213 // add a sound effect, return true if successful
214 bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) {
215
216     sample_map_iterator sample_it = samples.find( refname );
217     if ( sample_it != samples.end() ) {
218         // sound already exists
219         return false;
220     }
221
222     samples[refname] = sound;
223
224     return true;
225 }
226
227
228 // remove a sound effect, return true if successful
229 bool SGSoundMgr::remove( const string &refname ) {
230
231     sample_map_iterator sample_it = samples.find( refname );
232     if ( sample_it != samples.end() ) {
233         // first stop the sound from playing (so we don't bomb the
234         // audio scheduler)
235         samples.erase( sample_it );
236
237         // cout << "sndmgr: removed -> " << refname << endl;
238         return true;
239     } else {
240         // cout << "sndmgr: failed remove -> " << refname << endl;
241         return false;
242     }
243 }
244
245
246 // return true of the specified sound exists in the sound manager system
247 bool SGSoundMgr::exists( const string &refname ) {
248     sample_map_iterator sample_it = samples.find( refname );
249     if ( sample_it != samples.end() ) {
250         return true;
251     } else {
252         return false;
253     }
254 }
255
256
257 // return a pointer to the SGSoundSample if the specified sound exists
258 // in the sound manager system, otherwise return NULL
259 SGSoundSample *SGSoundMgr::find( const string &refname ) {
260     sample_map_iterator sample_it = samples.find( refname );
261     if ( sample_it != samples.end() ) {
262         return sample_it->second;
263     } else {
264         return NULL;
265     }
266 }
267
268
269 // tell the scheduler to play the indexed sample in a continuous
270 // loop
271 bool SGSoundMgr::play_looped( const string &refname ) {
272     SGSoundSample *sample;
273
274     if ( (sample = find( refname )) == NULL ) {
275         return false;
276     } else {
277         sample->play( true );
278         return true;
279     }
280 }
281
282
283 // tell the scheduler to play the indexed sample once
284 bool SGSoundMgr::play_once( const string& refname ) {
285     SGSoundSample *sample;
286
287     if ( (sample = find( refname )) == NULL ) {
288         return false;
289     } else {
290         sample->play( false );
291         return true;
292     }
293 }
294
295
296 // return true of the specified sound is currently being played
297 bool SGSoundMgr::is_playing( const string& refname ) {
298     SGSoundSample *sample;
299
300     if ( (sample = find( refname )) == NULL ) {
301         return false;
302     } else {
303         return ( sample->is_playing() );
304     }
305 }
306
307
308 // immediate stop playing the sound
309 bool SGSoundMgr::stop( const string& refname ) {
310     SGSoundSample *sample;
311
312     if ( (sample = find( refname )) == NULL ) {
313         return false;
314     } else {
315         sample->stop();
316         return true;
317     }
318 }
319
320
321 // set source position of all managed sounds
322 void SGSoundMgr::set_source_pos_all( ALfloat *pos ) {
323     if ( isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2]) ) {
324         // bail if a bad position is passed in
325         return;
326     }
327
328     sample_map_iterator sample_current = samples.begin();
329     sample_map_iterator sample_end = samples.end();
330     for ( ; sample_current != sample_end; ++sample_current ) {
331         SGSoundSample *sample = sample_current->second;
332         sample->set_source_pos( pos );
333     }
334 }
335
336
337 // set source velocity of all managed sounds
338 void SGSoundMgr::set_source_vel_all( ALfloat *vel ) {
339     if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) {
340         // bail if a bad velocity is passed in
341         return;
342     }
343
344     sample_map_iterator sample_current = samples.begin();
345     sample_map_iterator sample_end = samples.end();
346     for ( ; sample_current != sample_end; ++sample_current ) {
347         SGSoundSample *sample = sample_current->second;
348         sample->set_source_vel( vel );
349     }
350 }