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