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