]> 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/alc.h>
31 #else
32 # include <AL/al.h>
33 # include <AL/alc.h>
34 #endif
35
36 #if defined (__APPLE__)
37 // any C++ header file undefines isinf and isnan
38 // so this should be included before <iostream>
39 inline int (isinf)(double r) { return isinf(r); }
40 inline int (isnan)(double r) { return isnan(r); } 
41 #endif
42
43 #if defined (__FreeBSD__)
44 #  if __FreeBSD_version < 500000
45      extern "C" {
46        inline int isnan(double r) { return !(r <= 0 || r >= 0); }
47      }
48 #  endif
49 #endif
50
51 #include STL_IOSTREAM
52
53 #include <simgear/debug/logstream.hxx>
54 #include <simgear/misc/sg_path.hxx>
55
56 #include "soundmgr_openal.hxx"
57
58 #if defined(__MINGW32__)
59 #define isnan(x) _isnan(x)
60 #endif
61
62 //
63 // Sound Manager
64 //
65
66 // constructor
67 SGSoundMgr::SGSoundMgr() {
68
69     SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" );
70
71     // initialize OpenAL
72     if ( (dev = alcOpenDevice( NULL )) != NULL
73             && ( context = alcCreateContext( dev, NULL )) != NULL ) {
74         working = true;
75         alcMakeContextCurrent( context );
76     } else {
77         working = false;
78         context = 0;
79         SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
80     }
81
82     listener_pos[0] = 0.0;
83     listener_pos[1] = 0.0;
84     listener_pos[2] = 0.0;
85
86     listener_vel[0] = 0.0;
87     listener_vel[1] = 0.0;
88     listener_vel[2] = 0.0;
89     
90     listener_ori[0] = 0.0;
91     listener_ori[1] = 0.0;
92     listener_ori[2] = -1.0;
93     listener_ori[3] = 0.0;
94     listener_ori[4] = 1.0;
95     listener_ori[5] = 0.0;
96
97     alListenerf( AL_GAIN, 0.0f );
98     alListenerfv( AL_POSITION, listener_pos );
99     alListenerfv( AL_VELOCITY, listener_vel );
100     alListenerfv( AL_ORIENTATION, listener_ori );
101     alGetError();
102     if ( alGetError() != AL_NO_ERROR) {
103         SG_LOG( SG_GENERAL, SG_ALERT,
104                 "Oops AL error after audio initialization!" );
105     }
106
107     // exaggerate the ear candy?
108     alDopplerFactor(1.0);
109     alDopplerVelocity(340.0);   // speed of sound in meters per second.
110 }
111
112 // destructor
113
114 SGSoundMgr::~SGSoundMgr() {
115
116     if (context)
117         alcDestroyContext( context );
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     if (context) {
166         alcSuspendContext( context );
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
175 void
176 SGSoundMgr::resume ()
177 {
178     if (context) {
179         alcProcessContext( context );
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
188 // add a sound effect, return true if successful
189 bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) {
190
191     sample_map_iterator sample_it = samples.find( refname );
192     if ( sample_it != samples.end() ) {
193         // sound already exists
194         return false;
195     }
196
197     samples[refname] = sound;
198
199     return true;
200 }
201
202
203 // remove a sound effect, return true if successful
204 bool SGSoundMgr::remove( const string &refname ) {
205
206     sample_map_iterator sample_it = samples.find( refname );
207     if ( sample_it != samples.end() ) {
208         // first stop the sound from playing (so we don't bomb the
209         // audio scheduler)
210         SGSoundSample *sample = sample_it->second;
211         delete sample;
212         samples.erase( sample_it );
213
214         // cout << "sndmgr: removed -> " << refname << endl;
215         return true;
216     } else {
217         // cout << "sndmgr: failed remove -> " << refname << endl;
218         return false;
219     }
220 }
221
222
223 // return true of the specified sound exists in the sound manager system
224 bool SGSoundMgr::exists( const string &refname ) {
225     sample_map_iterator sample_it = samples.find( refname );
226     if ( sample_it != samples.end() ) {
227         return true;
228     } else {
229         return false;
230     }
231 }
232
233
234 // return a pointer to the SGSoundSample if the specified sound exists
235 // in the sound manager system, otherwise return NULL
236 SGSoundSample *SGSoundMgr::find( const string &refname ) {
237     sample_map_iterator sample_it = samples.find( refname );
238     if ( sample_it != samples.end() ) {
239         return sample_it->second;
240     } else {
241         return NULL;
242     }
243 }
244
245
246 // tell the scheduler to play the indexed sample in a continuous
247 // loop
248 bool SGSoundMgr::play_looped( const string &refname ) {
249     SGSoundSample *sample;
250
251     if ( (sample = find( refname )) == NULL ) {
252         return false;
253     } else {
254         sample->play( true );
255         return true;
256     }
257 }
258
259
260 // tell the scheduler to play the indexed sample once
261 bool SGSoundMgr::play_once( const string& refname ) {
262     SGSoundSample *sample;
263
264     if ( (sample = find( refname )) == NULL ) {
265         return false;
266     } else {
267         sample->play( false );
268         return true;
269     }
270 }
271
272
273 // return true of the specified sound is currently being played
274 bool SGSoundMgr::is_playing( const string& refname ) {
275     SGSoundSample *sample;
276
277     if ( (sample = find( refname )) == NULL ) {
278         return false;
279     } else {
280         return ( sample->is_playing() );
281     }
282 }
283
284
285 // immediate stop playing the sound
286 bool SGSoundMgr::stop( const string& refname ) {
287     SGSoundSample *sample;
288
289     if ( (sample = find( refname )) == NULL ) {
290         return false;
291     } else {
292         sample->stop();
293         return true;
294     }
295 }
296
297
298 // set source position of all managed sounds
299 void SGSoundMgr::set_source_pos_all( ALfloat *pos ) {
300     if ( isnan(pos[0]) || isnan(pos[1]) || isnan(pos[2]) ) {
301         // bail if a bad position is passed in
302         return;
303     }
304
305     sample_map_iterator sample_current = samples.begin();
306     sample_map_iterator sample_end = samples.end();
307     for ( ; sample_current != sample_end; ++sample_current ) {
308         SGSoundSample *sample = sample_current->second;
309         sample->set_source_pos( pos );
310     }
311 }
312
313
314 // set source velocity of all managed sounds
315 void SGSoundMgr::set_source_vel_all( ALfloat *vel ) {
316     if ( isnan(vel[0]) || isnan(vel[1]) || isnan(vel[2]) ) {
317         // bail if a bad velocity is passed in
318         return;
319     }
320
321     sample_map_iterator sample_current = samples.begin();
322     sample_map_iterator sample_end = samples.end();
323     for ( ; sample_current != sample_end; ++sample_current ) {
324         SGSoundSample *sample = sample_current->second;
325         sample->set_source_vel( vel );
326     }
327 }