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