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