]> git.mxchange.org Git - simgear.git/blob - simgear/sound/soundmgr_openal.cxx
Martin Spott: Revised handling of missing isnan() on earlier versions of
[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., 675 Mass Ave, Cambridge, MA 02139, USA.
23 //
24 // $Id$
25
26 #include <simgear/compiler.h>
27
28 #if defined(__APPLE__)
29 # include <OpenAL/al.h>
30 # include <OpenAL/alut.h>
31 # include <OpenAL/alc.h>
32 #else
33 # include <AL/al.h>
34 # include <AL/alut.h>
35 # include <AL/alc.h>
36 #endif
37
38 #if defined (__APPLE__)
39 // any C++ header file undefines isinf and isnan
40 // so this should be included before <iostream>
41 inline int (isinf)(double r) { return isinf(r); }
42 inline int (isnan)(double r) { return isnan(r); } 
43 #endif
44
45 #if defined(__MINGW32__)
46 #define isnan(x) _isnan(x)
47 #endif
48
49 #if defined (__FreeBSD__)
50 #  if __FreeBSD_version < 500000
51      extern "C" {
52        inline int isnan(double r) { return !(r <= 0 || r >= 0); }
53      }
54 #  endif
55 #endif
56
57
58 #if defined (__FreeBSD__)
59 inline int isnan(double r) { return !(r <= 0 || r >= 0); }
60 #endif
61
62 #include STL_IOSTREAM
63
64 #include <simgear/debug/logstream.hxx>
65 #include <simgear/misc/sg_path.hxx>
66
67 #include "soundmgr_openal.hxx"
68
69
70 //
71 // Sound Manager
72 //
73
74 // constructor
75 SGSoundMgr::SGSoundMgr() {
76
77     SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" );
78
79     // initialize OpenAL
80     alutInit( 0, NULL );
81     atexit(alutExit);
82
83     if ( alGetError() == AL_NO_ERROR) {
84         working = true;
85     } else {
86         working = false;
87         SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
88     }
89
90     listener_pos[0] = 0.0;
91     listener_pos[1] = 0.0;
92     listener_pos[2] = 0.0;
93
94     listener_vel[0] = 0.0;
95     listener_vel[1] = 0.0;
96     listener_vel[2] = 0.0;
97     
98     listener_ori[0] = 0.0;
99     listener_ori[1] = 0.0;
100     listener_ori[2] = -1.0;
101     listener_ori[3] = 0.0;
102     listener_ori[4] = 1.0;
103     listener_ori[5] = 0.0;
104
105     alListenerfv( AL_POSITION, listener_pos );
106     alListenerfv( AL_VELOCITY, listener_vel );
107     alListenerfv( AL_ORIENTATION, listener_ori );
108     alGetError();
109     if ( alGetError() != AL_NO_ERROR) {
110         SG_LOG( SG_GENERAL, SG_ALERT,
111                 "Oops AL error after audio initialization!" );
112     }
113
114     // exaggerate the ear candy?
115     alDopplerFactor(1.0);
116     alDopplerVelocity(340.0);   // speed of sound in meters per second.
117 }
118
119 // destructor
120
121 SGSoundMgr::~SGSoundMgr() {
122
123     //
124     // Remove the samples from the sample manager.
125     //
126     sample_map_iterator sample_current = samples.begin();
127     sample_map_iterator sample_end = samples.end();
128     for ( ; sample_current != sample_end; ++sample_current ) {
129         SGSoundSample *sample = sample_current->second;
130         delete sample;
131     }
132 }
133
134
135 // initialize the sound manager
136 void SGSoundMgr::init() {
137     //
138     // Remove the samples from the sample manager.
139     //
140     sample_map_iterator sample_current = samples.begin();
141     sample_map_iterator sample_end = samples.end();
142     for ( ; sample_current != sample_end; ++sample_current ) {
143         SGSoundSample *sample = sample_current->second;
144         delete sample;
145     }
146     samples.clear();
147 }
148
149
150 void SGSoundMgr::bind ()
151 {
152     // no properties
153 }
154
155
156 void SGSoundMgr::unbind ()
157 {
158     // no properties
159 }
160
161
162 // run the audio scheduler
163 void SGSoundMgr::update( double dt ) {
164 }
165
166
167 void
168 SGSoundMgr::pause ()
169 {
170     ALCcontext *pCurContext = alcGetCurrentContext();
171     alcSuspendContext( pCurContext );
172     if ( alGetError() != AL_NO_ERROR) {
173         SG_LOG( SG_GENERAL, SG_ALERT,
174                 "Oops AL error after soundmgr pause()!" );
175     }
176 }
177
178
179 void
180 SGSoundMgr::resume ()
181 {
182     ALCcontext *pCurContext = alcGetCurrentContext();
183     alcProcessContext( pCurContext );
184     if ( alGetError() != AL_NO_ERROR) {
185         SG_LOG( SG_GENERAL, SG_ALERT,
186                 "Oops AL error after soundmgr resume()!" );
187     }
188 }
189
190
191 // add a sound effect, return true if successful
192 bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) {
193
194     sample_map_iterator sample_it = samples.find( refname );
195     if ( sample_it != samples.end() ) {
196         // sound already exists
197         return false;
198     }
199
200     samples[refname] = sound;
201
202     return true;
203 }
204
205
206 // remove a sound effect, return true if successful
207 bool SGSoundMgr::remove( const string &refname ) {
208
209     sample_map_iterator sample_it = samples.find( refname );
210     if ( sample_it != samples.end() ) {
211         // first stop the sound from playing (so we don't bomb the
212         // audio scheduler)
213         SGSoundSample *sample = sample_it->second;
214         delete sample;
215         samples.erase( sample_it );
216
217         // cout << "sndmgr: removed -> " << refname << endl;
218         return true;
219     } else {
220         // cout << "sndmgr: failed remove -> " << refname << endl;
221         return false;
222     }
223 }
224
225
226 // return true of the specified sound exists in the sound manager system
227 bool SGSoundMgr::exists( const string &refname ) {
228     sample_map_iterator sample_it = samples.find( refname );
229     if ( sample_it != samples.end() ) {
230         return true;
231     } else {
232         return false;
233     }
234 }
235
236
237 // return a pointer to the SGSoundSample if the specified sound exists
238 // in the sound manager system, otherwise return NULL
239 SGSoundSample *SGSoundMgr::find( const string &refname ) {
240     sample_map_iterator sample_it = samples.find( refname );
241     if ( sample_it != samples.end() ) {
242         return sample_it->second;
243     } else {
244         return NULL;
245     }
246 }
247
248
249 // tell the scheduler to play the indexed sample in a continuous
250 // loop
251 bool SGSoundMgr::play_looped( const string &refname ) {
252     SGSoundSample *sample;
253
254     if ( (sample = find( refname )) == NULL ) {
255         return false;
256     } else {
257         sample->play( true );
258         return true;
259     }
260 }
261
262
263 // tell the scheduler to play the indexed sample once
264 bool SGSoundMgr::play_once( const string& refname ) {
265     SGSoundSample *sample;
266
267     if ( (sample = find( refname )) == NULL ) {
268         return false;
269     } else {
270         sample->play( false );
271         return true;
272     }
273 }
274
275
276 // return true of the specified sound is currently being played
277 bool SGSoundMgr::is_playing( const string& refname ) {
278     SGSoundSample *sample;
279
280     if ( (sample = find( refname )) == NULL ) {
281         return false;
282     } else {
283         return ( sample->is_playing() );
284     }
285 }
286
287
288 // immediate stop playing the sound
289 bool SGSoundMgr::stop( const string& refname ) {
290     SGSoundSample *sample;
291
292     if ( (sample = find( refname )) == NULL ) {
293         return false;
294     } else {
295         sample->stop();
296         return true;
297     }
298 }
299
300
301 // set source position of all managed sounds
302 void SGSoundMgr::set_source_pos_all( ALfloat *pos ) {
303     if ( isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2]) ) {
304         // bail if a bad position is passed in
305         return;
306     }
307
308     sample_map_iterator sample_current = samples.begin();
309     sample_map_iterator sample_end = samples.end();
310     for ( ; sample_current != sample_end; ++sample_current ) {
311         SGSoundSample *sample = sample_current->second;
312         sample->set_source_pos( pos );
313     }
314 }
315
316
317 // set source velocity of all managed sounds
318 void SGSoundMgr::set_source_vel_all( ALfloat *vel ) {
319     if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) {
320         // bail if a bad velocity is passed in
321         return;
322     }
323
324     sample_map_iterator sample_current = samples.begin();
325     sample_map_iterator sample_end = samples.end();
326     for ( ; sample_current != sample_end; ++sample_current ) {
327         SGSoundSample *sample = sample_current->second;
328         sample->set_source_vel( vel );
329     }
330 }