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