]> git.mxchange.org Git - simgear.git/blob - simgear/sound/soundmgr_openal.cxx
Expose some of the positional components of the OpenAL API.
[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 }
90
91 // destructor
92
93 SGSoundMgr::~SGSoundMgr() {
94
95     //
96     // Remove the samples from the sample manager.
97     //
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;
102         delete sample;
103     }
104
105     alutExit();
106 }
107
108
109 // initialize the sound manager
110 void SGSoundMgr::init() {
111     //
112     // Remove the samples from the sample manager.
113     //
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;
118         delete sample;
119     }
120     samples.clear();
121 }
122
123
124 void SGSoundMgr::bind ()
125 {
126     // no properties
127 }
128
129
130 void SGSoundMgr::unbind ()
131 {
132     // no properties
133 }
134
135
136 // run the audio scheduler
137 void SGSoundMgr::update( double dt ) {
138 }
139
140
141 void
142 SGSoundMgr::pause ()
143 {
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()!" );
149     }
150 }
151
152
153 void
154 SGSoundMgr::resume ()
155 {
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()!" );
161     }
162 }
163
164
165 // add a sound effect, return true if successful
166 bool SGSoundMgr::add( SGSoundSample *sound, const string& refname ) {
167
168     sample_map_iterator sample_it = samples.find( refname );
169     if ( sample_it != samples.end() ) {
170         // sound already exists
171         return false;
172     }
173
174     samples[refname] = sound;
175
176     return true;
177 }
178
179
180 // remove a sound effect, return true if successful
181 bool SGSoundMgr::remove( const string &refname ) {
182
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
186         // audio scheduler)
187         SGSoundSample *sample = sample_it->second;
188         delete sample;
189         samples.erase( sample_it );
190
191         // cout << "sndmgr: removed -> " << refname << endl;
192         return true;
193     } else {
194         // cout << "sndmgr: failed remove -> " << refname << endl;
195         return false;
196     }
197 }
198
199
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() ) {
204         return true;
205     } else {
206         return false;
207     }
208 }
209
210
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;
217     } else {
218         return NULL;
219     }
220 }
221
222
223 // tell the scheduler to play the indexed sample in a continuous
224 // loop
225 bool SGSoundMgr::play_looped( const string &refname ) {
226     SGSoundSample *sample;
227
228     if ( (sample = find( refname )) == NULL ) {
229         return false;
230     } else {
231         sample->play( true );
232         return true;
233     }
234 }
235
236
237 // tell the scheduler to play the indexed sample once
238 bool SGSoundMgr::play_once( const string& refname ) {
239     SGSoundSample *sample;
240
241     if ( (sample = find( refname )) == NULL ) {
242         return false;
243     } else {
244         sample->play( false );
245         return true;
246     }
247 }
248
249
250 // return true of the specified sound is currently being played
251 bool SGSoundMgr::is_playing( const string& refname ) {
252     SGSoundSample *sample;
253
254     if ( (sample = find( refname )) == NULL ) {
255         return false;
256     } else {
257         return ( sample->is_playing() );
258     }
259 }
260
261
262 // immediate stop playing the sound
263 bool SGSoundMgr::stop( const string& refname ) {
264     SGSoundSample *sample;
265
266     if ( (sample = find( refname )) == NULL ) {
267         return false;
268     } else {
269         sample->stop();
270         return true;
271     }
272 }
273
274
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 );
282     }
283 }
284
285
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 );
293     }
294 }