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