]> git.mxchange.org Git - simgear.git/blob - simgear/sound/soundmgr_openal.hxx
Fix #1783: repeated error message on console
[simgear.git] / simgear / sound / soundmgr_openal.hxx
1 ///@file
2 /// Sound effect management class
3 ///
4 /// Provides a sound manager class to keep track of multiple sounds and manage
5 /// playing them with different effects and timings.
6 //
7 // Sound manager initially written by David Findlay
8 // <david_j_findlay@yahoo.com.au> 2001
9 //
10 // C++-ified by Curtis Olson, started March 2001.
11 // Modified for the new SoundSystem by Erik Hofman, October 2009
12 //
13 // Copyright (C) 2001  Curtis L. Olson - http://www.flightgear.org/~curt
14 // Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
15 //
16 // This library is free software; you can redistribute it and/or
17 // modify it under the terms of the GNU Library General Public
18 // License as published by the Free Software Foundation; either
19 // version 2 of the License, or (at your option) any later version.
20 //
21 // This library is distributed in the hope that it will be useful,
22 // but WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24 // Library General Public License for more details.
25 //
26 // You should have received a copy of the GNU Library General Public
27 // License along with this library; if not, write to the Free Software
28 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
29
30 #ifndef _SG_SOUNDMGR_OPENAL_HXX
31 #define _SG_SOUNDMGR_OPENAL_HXX 1
32
33 #include <string>
34 #include <vector>
35 #include <map>
36 #include <memory> // for std::auto_ptr
37      
38 #include <simgear/compiler.h>
39 #include <simgear/structure/subsystem_mgr.hxx>
40 #include <simgear/math/SGMath.hxx>
41
42 // forward decls
43 class SGSampleGroup;
44 class SGSoundSample;
45
46 /**
47  * Manage a collection of SGSampleGroup instances
48  */
49 class SGSoundMgr : public SGSubsystem
50 {
51 public:
52
53     SGSoundMgr();
54     ~SGSoundMgr();
55
56     void init();
57     void update(double dt);
58     
59     void suspend();
60     void resume();
61     void stop();
62
63     void reinit();
64
65     /**
66      * Select a specific sound device.
67      * Requires a init/reinit call before sound is actually switched.
68      */
69     inline void select_device(const char* devname) {_device_name = devname;}
70
71     /**
72      * Test is the sound manager is in a working condition.
73      * @return true is the sound manager is working
74      */
75     bool is_working() const;
76
77     /**
78      * Set the sound manager to a  working condition.
79      */
80     void activate();
81
82     /**
83      * Test is the sound manager is in an active and working condition.
84      * @return true is the sound manager is active
85      */
86     inline bool is_active() const { return _active; }
87
88     /**
89      * Register a sample group to the sound manager.
90      * @param sgrp Pointer to a sample group to add
91      * @param refname Reference name of the sample group
92      * @return true if successful, false otherwise
93      */
94     bool add( SGSampleGroup *sgrp, const std::string& refname );
95
96     /** 
97      * Remove a sample group from the sound manager.
98      * @param refname Reference name of the sample group to remove
99      * @return true if successful, false otherwise
100      */
101     bool remove( const std::string& refname );
102
103     /**
104      * Test if a specified sample group is registered at the sound manager
105      * @param refname Reference name of the sample group test for
106      * @return true if the specified sample group exists
107      */
108     bool exists( const std::string& refname );
109
110     /**
111      * Find a specified sample group in the sound manager
112      *
113      * @param refname Reference name of the sample group to find
114      * @param create  If the group should be create if it does not exist
115      * @return A pointer to the SGSampleGroup
116      */
117     SGSampleGroup *find( const std::string& refname, bool create = false );
118
119     /**
120      * Set the Cartesian position of the sound manager.
121      *
122      * @param pos OpenAL listener position
123      */
124     void set_position( const SGVec3d& pos, const SGGeod& pos_geod );
125
126     void set_position_offset( const SGVec3d& pos ) {
127         _offset_pos = pos; _changed = true;
128     }
129
130     /**
131      * Get the position of the sound manager.
132      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
133      *
134      * @return OpenAL listener position
135      */
136     const SGVec3d& get_position() const;
137
138     /**
139      * Set the velocity vector (in meters per second) of the sound manager
140      * This is the horizontal local frame; x=north, y=east, z=down
141      *
142      * @param vel Velocity vector
143      */
144     void set_velocity( const SGVec3d& vel ) {
145         _velocity = vel; _changed = true;
146     }
147
148     /**
149      * Get the velocity vector of the sound manager
150      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
151      *
152      * @return Velocity vector of the OpenAL listener
153      */
154     inline SGVec3f get_velocity() { return toVec3f(_velocity); }
155
156     /**
157      * Set the orientation of the sound manager
158      *
159      * @param ori Quaternation containing the orientation information
160      */
161     void set_orientation( const SGQuatd& ori );
162
163     /**
164      * Get the orientation of the sound manager
165      *
166      * @return Quaternation containing the orientation information
167      */
168     const SGQuatd& get_orientation() const;
169
170     /**
171      * Get the direction vector of the sound manager
172      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
173      *
174      * @return Look-at direction of the OpenAL listener
175      */
176     SGVec3f get_direction() const;
177
178     enum {
179         NO_SOURCE = (unsigned int)-1,
180         NO_BUFFER = (unsigned int)-1,
181         FAILED_BUFFER = (unsigned int)-2
182     };
183
184     /**
185      * Set the master volume.
186      *
187      * @param vol Volume (must be between 0.0 and 1.0)
188      */
189     void set_volume( float vol );
190
191     /**
192      * Get the master volume.
193      *
194      * @return Volume (must be between 0.0 and 1.0)
195      */
196     inline float get_volume() { return _volume; }
197
198     /**
199      * Get a free OpenAL source-id
200      *
201      * @return NO_SOURCE if no source is available
202      */
203     unsigned int request_source();
204
205     /**
206      * Free an OpenAL source-id for future use
207      *
208      * @param source OpenAL source-id to free
209      */
210     void release_source( unsigned int source );
211
212     /**
213      * Get a free OpenAL buffer-id
214      * The buffer-id will be assigned to the sample by calling this function.
215      *
216      * @param sample Pointer to an audio sample to assign the buffer-id to
217      * @return NO_BUFFER if loading of the buffer failed.
218      */
219     unsigned int request_buffer(SGSoundSample *sample);
220
221     /**
222      * Free an OpenAL buffer-id for this sample
223      *
224      * @param sample Pointer to an audio sample for which to free the buffer
225      */
226     void release_buffer( SGSoundSample *sample );
227
228     /**
229      * Test if the position of the sound manager has changed.
230      * The value will be set to false upon the next call to update_late()
231      *
232      * @return true if the position has changed
233      */
234     inline bool has_changed() { return _changed; }
235
236     /**
237      * Some implementations seem to need the velocity multiplied by a
238      * factor of 100 to make them distinct. I've not found if this is
239      * a problem in the implementation or in out code. Until then
240      * this function is used to detect the problematic implementations.
241      */
242     inline bool bad_doppler_effect() { return _bad_doppler; }
243
244     /**
245      * Load a sample file and return it's configuration and data.
246      *
247      * @param samplepath Path to the file to load
248      * @param data Pointer to a variable that points to the allocated data
249      * @param format Pointer to a vairable that gets the OpenAL format
250      * @param size Pointer to a vairable that gets the sample size in bytes
251      * @param freq Pointer to a vairable that gets the sample frequency in Herz
252      * @return true if succesful, false on error
253      */
254     bool load( const std::string &samplepath,
255                void **data,
256                int *format,
257                size_t *size,
258                int *freq );
259
260     /**
261      * Get a list of available playback devices.
262      */
263     std::vector<const char*> get_available_devices();
264
265     /**
266      * Get the current OpenAL vendor or rendering backend.
267      */
268     const std::string& get_vendor() { return _vendor; }
269     const std::string& get_renderer() { return _renderer; }
270
271 private:
272     class SoundManagerPrivate;
273     /// private implementation object
274     std::auto_ptr<SoundManagerPrivate> d;
275         
276     bool _active;
277     bool _changed;
278     float _volume;
279
280     // Position of the listener.
281     SGVec3d _offset_pos;
282     SGGeod _geod_pos;
283
284     // Velocity of the listener.
285     SGVec3d _velocity;
286
287     bool _bad_doppler;
288     std::string _renderer;
289     std::string _vendor;
290     std::string _device_name;
291
292     bool testForALError(std::string s);
293     bool testForALCError(std::string s);
294     bool testForError(void *p, std::string s);
295
296     void update_sample_config( SGSampleGroup *sound );
297 };
298
299
300 #endif // _SG_SOUNDMGR_OPENAL_HXX
301
302