1 // soundmgr.cxx -- Sound effect management class
3 // Sound manager initially written by David Findlay
4 // <david_j_findlay@yahoo.com.au> 2001
6 // C++-ified by Curtis Olson, started March 2001.
8 // Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
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.
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.
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.
28 #if defined(__APPLE__)
29 # include <OpenAL/al.h>
30 # include <OpenAL/alut.h>
31 # include <OpenAL/alc.h>
38 #include <simgear/debug/logstream.hxx>
39 #include <simgear/misc/sg_path.hxx>
41 #include "soundmgr_openal.hxx"
49 SGSoundMgr::SGSoundMgr() {
51 SG_LOG( SG_GENERAL, SG_ALERT, "Initializing OpenAL sound manager" );
56 if ( alGetError() == AL_NO_ERROR) {
60 SG_LOG( SG_GENERAL, SG_ALERT, "Audio initialization failed!" );
63 listener_pos[0] = 0.0;
64 listener_pos[1] = 0.0;
65 listener_pos[2] = 0.0;
67 listener_vel[0] = 0.0;
68 listener_vel[1] = 0.0;
69 listener_vel[2] = 0.0;
71 listener_ori[0] = 0.0;
72 listener_ori[1] = 0.0;
73 listener_ori[2] = -1.0;
74 listener_ori[3] = 0.0;
75 listener_ori[4] = 1.0;
76 listener_ori[5] = 0.0;
78 alListenerfv( AL_POSITION, listener_pos );
79 alListenerfv( AL_VELOCITY, listener_vel );
80 alListenerfv( AL_ORIENTATION, listener_ori );
82 if ( alGetError() != AL_NO_ERROR) {
83 SG_LOG( SG_GENERAL, SG_ALERT,
84 "Oops AL error after audio initialization!" );
87 // exaggerate the ear candy?
93 SGSoundMgr::~SGSoundMgr() {
96 // Remove the samples from the sample manager.
98 sample_map_iterator sample_current = samples.begin();
99 sample_map_iterator sample_end = samples.end();
100 for ( ; sample_current != sample_end; ++sample_current ) {
101 SGSoundSample *sample = sample_current->second;
109 // initialize the sound manager
110 void SGSoundMgr::init() {
112 // Remove the samples from the sample manager.
114 sample_map_iterator sample_current = samples.begin();
115 sample_map_iterator sample_end = samples.end();
116 for ( ; sample_current != sample_end; ++sample_current ) {
117 SGSoundSample *sample = sample_current->second;
124 void SGSoundMgr::bind ()
130 void SGSoundMgr::unbind ()
136 // run the audio scheduler
137 void SGSoundMgr::update( double dt ) {
144 ALCcontext *pCurContext = alcGetCurrentContext();
145 alcSuspendContext( pCurContext );
146 if ( alGetError() != AL_NO_ERROR) {
147 SG_LOG( SG_GENERAL, SG_ALERT,
148 "Oops AL error after soundmgr pause()!" );
154 SGSoundMgr::resume ()
156 ALCcontext *pCurContext = alcGetCurrentContext();
157 alcProcessContext( pCurContext );
158 if ( alGetError() != AL_NO_ERROR) {
159 SG_LOG( SG_GENERAL, SG_ALERT,
160 "Oops AL error after soundmgr resume()!" );
165 // add a sound effect, return true if successful
166 bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) {
168 sample_map_iterator sample_it = samples.find( refname );
169 if ( sample_it != samples.end() ) {
170 // sound already exists
174 samples[refname] = sound;
180 // remove a sound effect, return true if successful
181 bool SGSoundMgr::remove( const string &refname ) {
183 sample_map_iterator sample_it = samples.find( refname );
184 if ( sample_it != samples.end() ) {
185 // first stop the sound from playing (so we don't bomb the
187 SGSoundSample *sample = sample_it->second;
189 samples.erase( sample_it );
191 // cout << "sndmgr: removed -> " << refname << endl;
194 // cout << "sndmgr: failed remove -> " << refname << endl;
200 // return true of the specified sound exists in the sound manager system
201 bool SGSoundMgr::exists( const string &refname ) {
202 sample_map_iterator sample_it = samples.find( refname );
203 if ( sample_it != samples.end() ) {
211 // return a pointer to the SGSoundSample if the specified sound exists
212 // in the sound manager system, otherwise return NULL
213 SGSoundSample *SGSoundMgr::find( const string &refname ) {
214 sample_map_iterator sample_it = samples.find( refname );
215 if ( sample_it != samples.end() ) {
216 return sample_it->second;
223 // tell the scheduler to play the indexed sample in a continuous
225 bool SGSoundMgr::play_looped( const string &refname ) {
226 SGSoundSample *sample;
228 if ( (sample = find( refname )) == NULL ) {
231 sample->play( true );
237 // tell the scheduler to play the indexed sample once
238 bool SGSoundMgr::play_once( const string& refname ) {
239 SGSoundSample *sample;
241 if ( (sample = find( refname )) == NULL ) {
244 sample->play( false );
250 // return true of the specified sound is currently being played
251 bool SGSoundMgr::is_playing( const string& refname ) {
252 SGSoundSample *sample;
254 if ( (sample = find( refname )) == NULL ) {
257 return ( sample->is_playing() );
262 // immediate stop playing the sound
263 bool SGSoundMgr::stop( const string& refname ) {
264 SGSoundSample *sample;
266 if ( (sample = find( refname )) == NULL ) {
275 // set source position of all managed sounds
276 void SGSoundMgr::set_source_pos_all( ALfloat *pos ) {
277 sample_map_iterator sample_current = samples.begin();
278 sample_map_iterator sample_end = samples.end();
279 for ( ; sample_current != sample_end; ++sample_current ) {
280 SGSoundSample *sample = sample_current->second;
281 sample->set_source_pos( pos );
286 // set source velocity of all managed sounds
287 void SGSoundMgr::set_source_vel_all( ALfloat *vel ) {
288 sample_map_iterator sample_current = samples.begin();
289 sample_map_iterator sample_end = samples.end();
290 for ( ; sample_current != sample_end; ++sample_current ) {
291 SGSoundSample *sample = sample_current->second;
292 sample->set_source_vel( vel );