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