]> git.mxchange.org Git - simgear.git/blob - simgear/sound/sample_openal.hxx
Make it possible to tie the absolute position to a property
[simgear.git] / simgear / sound / sample_openal.hxx
1 ///@file
2 /// Provides an audio sample encapsulation class.
3 // 
4 // Written by Curtis Olson, started April 2004.
5 // Modified to match the new SoundSystem by Erik Hofman, October 2009
6 //
7 // Copyright (C) 2004  Curtis L. Olson - http://www.flightgear.org/~curt
8 // Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Library General Public
12 // License as published by the Free Software Foundation; either
13 // version 2 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU Library General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
23
24 #ifndef _SG_SAMPLE_HXX
25 #define _SG_SAMPLE_HXX 1
26
27 #include <string>
28
29 #include <simgear/compiler.h>
30 #include <simgear/structure/SGReferenced.hxx>
31 #include <simgear/structure/SGSharedPtr.hxx>
32 #include <simgear/math/SGMath.hxx>
33 #include <simgear/props/props.hxx>
34      
35 class SGPath;
36
37 #ifndef AL_FORMAT_MONO8
38      #define AL_FORMAT_MONO8    0x1100
39 #endif
40  
41
42 /**
43  * Encapsulate and audio sample.
44  *
45  * Manages everything we need to know for an individual audio sample.
46  */
47
48 class SGSoundSample : public SGReferenced {
49 public:
50
51      /**
52       * Empty constructor, can be used to read data to the systems
53       * memory and not to the driver.
54       */
55     SGSoundSample();
56
57     /**
58      * Constructor
59      * @param file File name of sound
60        Buffer data is freed by the sample group
61      */
62     SGSoundSample(const char *file, const SGPath& currentDir);
63
64     /**
65      * Constructor.
66      * @param data Pointer to a memory buffer containing this audio sample data
67        The application may free the data by calling free_data(), otherwise it
68        will be resident until the class is destroyed. This pointer will be
69        set to NULL after calling this function.
70      * @param len Byte length of array
71      * @param freq Frequency of the provided data (bytes per second)
72      * @param format OpenAL format id of the data
73      */
74     SGSoundSample( void** data, int len, int freq, int format=AL_FORMAT_MONO8 );
75     SGSoundSample( const unsigned char** data, int len, int freq,
76                    int format = AL_FORMAT_MONO8 );
77
78     /**
79      * Destructor
80      */
81     virtual ~SGSoundSample ();
82
83     /**
84      * Detect whether this audio sample holds the information of a sound file.
85      * @return Return true if this audio sample is to be constructed from a file.
86      */
87     inline bool is_file() const { return _is_file; }
88
89     SGPath file_path() const;
90
91     /**
92      * Test if this audio sample configuration has changed since the last call.
93      * Calling this function will reset the flag so calling it a second
94      * time in a row will return false.
95      *
96      * @return Return true is the configuration has changed in the mean time.
97      */
98     bool has_changed() {
99         bool b = _changed; _changed = false; return b;
100     }
101
102     /**
103      * Test if static data of audio sample configuration has changed.
104      * Calling this function will reset the flag so calling it a second
105      * time in a row will return false.
106      *
107      * @return Return true is the static data has changed in the mean time.
108      */
109     bool has_static_data_changed() {
110         bool b = _static_changed; _static_changed = false; return b;
111     }
112
113     /**
114      * Schedule this audio sample for playing. Actual playing will only start
115      * at the next call op SoundGroup::update()
116      *
117      * @param loop Whether this sound should be played in a loop.
118      */
119     void play( bool loop = false ) {
120         _playing = true; _loop = loop; _changed = true; _static_changed = true;
121     }
122
123     /**
124      * Check if this audio sample is set to be continuous looping.
125      *
126      * @return Return true if this audio sample is set to looping.
127      */
128     inline bool is_looping() { return _loop; }
129
130     /**
131      * Schedule this audio sample to stop playing.
132      */
133     virtual void stop() {
134         _playing = false; _changed = true;
135     }
136
137     /**
138      * Schedule this audio sample to play once.
139      * @see #play
140      */
141     inline void play_once() { play(false); }
142
143     /** 
144      * Schedule this audio sample to play looped.
145      * @see #play
146      */
147     inline void play_looped() { play(true); }
148
149     /**
150      * Test if a audio sample is scheduled for playing.
151      * @return true if this audio sample is playing, false otherwise.
152      */
153     inline bool is_playing() { return _playing; }
154
155
156     /**
157      * Set this sample to out-of-range (or not) and
158      * Schedule this audio sample to stop (or start) playing.
159      */
160     inline void set_out_of_range(bool oor = true) {
161         _out_of_range = oor; _playing = (!oor && _loop); _changed = true;
162     }
163
164     /**
165      * Test if this sample to out-of-range or not.
166      */
167     inline bool test_out_of_range() {
168         return _out_of_range;
169     }
170
171     /**
172      * Set the data associated with this audio sample
173      * @param data Pointer to a memory block containg this audio sample data.
174        This pointer will be set to NULL after calling this function.
175      */
176     inline void set_data( const unsigned char **data ) {
177         _data = (unsigned char*)*data; *data = NULL;
178     }
179     inline void set_data( const void **data ) {
180         _data = (unsigned char*)*data; *data = NULL;
181     }
182
183     /**
184      * Return the data associated with this audio sample.
185      * @return A pointer to this sound data of this audio sample.
186      */
187     inline void* get_data() const { return _data; }
188
189     /**
190      * Free the data associated with this audio sample
191      */
192     void free_data();
193
194     /**
195      * Set the source id of this source
196      * @param sid OpenAL source-id
197      */
198     virtual void set_source(unsigned int sid) {
199         _source = sid; _valid_source = true; _changed = true;
200     }
201
202     /**
203      * Get the OpenAL source id of this source
204      * @return OpenAL source-id
205      */
206     virtual unsigned int get_source() { return _source; }
207
208     /**
209      * Test if the source-id of this audio sample may be passed to OpenAL.
210      * @return true if the source-id is valid
211      */
212     virtual bool is_valid_source() const { return _valid_source; }
213
214     /**
215      * Set the source-id of this audio sample to invalid.
216      */
217     virtual void no_valid_source() { _valid_source = false; }
218
219     /**
220      * Set the OpenAL buffer-id of this source
221      * @param bid OpenAL buffer-id
222      */
223     inline void set_buffer(unsigned int bid) {
224         _buffer = bid; _valid_buffer = true; _changed = true;
225     } 
226
227     /**
228      * Get the OpenAL buffer-id of this source
229      * @return OpenAL buffer-id
230      */
231     inline unsigned int get_buffer() { return _buffer; }
232
233     /**
234      * Test if the buffer-id of this audio sample may be passed to OpenAL.
235      * @return true if the buffer-id is valid
236      */
237     inline bool is_valid_buffer() const { return _valid_buffer; }
238
239     /**
240      * Set the buffer-id of this audio sample to invalid.
241      */
242     inline void no_valid_buffer() { _valid_buffer = false; }
243
244     /**
245      * Set the playback pitch of this audio sample. 
246      * Should be between 0.0 and 2.0 for maximum compatibility.
247      * @param p Pitch
248      */
249     inline void set_pitch( float p ) {
250         if (p > 2.0) p = 2.0; else if (p < 0.01) p = 0.01;
251         _pitch = p; _changed = true;
252     }
253
254     /**
255      * Get the current pitch value of this audio sample.
256      * @return Pitch
257      */
258     inline float get_pitch() { return _pitch; }
259
260     /**
261      * Set the master volume of this sample. Should be between 0.0 and 1.0.
262      * The final volume is calculated by multiplying the master and audio sample
263      * volume.
264      * @param v Volume
265      */
266     inline void set_master_volume( float v ) {
267         if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
268         _master_volume = v; _changed = true;
269     }
270
271     /**
272      * Set the volume of this audio sample. Should be between 0.0 and 1.0.
273      * The final volume is calculated by multiplying the master and audio sample
274      * volume.
275      * @param v Volume
276      */
277     inline void set_volume( float v ) {
278         if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
279         _volume = v; _changed = true;
280     }
281
282     /**
283      * Get the final volume value of this audio sample.
284      * @return Volume
285      */
286     inline float get_volume() { return _volume * _master_volume; }
287
288     /**
289      * Set the OpenAL format of this audio sample.
290      * @param format OpenAL format-id
291      */
292     inline void set_format( int format ) { _format = format; }
293
294     /**
295      * Returns the format of this audio sample.
296      * @return OpenAL format-id
297      */
298     inline int get_format() { return _format; }
299
300     /**
301      * Set the frequency (in Herz) of this audio sample.
302      * @param freq Frequency
303      */
304     inline void set_frequency( int freq ) { _freq = freq; }
305
306     /**
307      * Returns the frequency (in Herz) of this audio sample.
308      * @return Frequency
309      */
310     inline int get_frequency() { return _freq; }
311
312     /**
313      * Sets the size (in bytes) of this audio sample.
314      * @param size Data size
315      */
316     inline void set_size( size_t size ) { _size = size; }
317
318     /**
319      * Returns the size (in bytes) of this audio sample.
320      * @return Data size
321      */
322     inline size_t get_size() const { return _size; }
323
324     /**
325      * Set the position of this sound relative to the base position.
326      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
327      * @param pos Relative position of this sound
328      */
329     inline void set_relative_position( const SGVec3f& pos ) {
330         _relative_pos = toVec3d(pos); _changed = true;
331     }
332
333     /**
334      * Set the base position in Cartesian coordinates
335      * @param pos position in Cartesian coordinates
336      */
337     inline void set_position( const SGVec3d& pos ) {
338         _base_pos = pos; _changed = true;
339     }
340
341     inline void set_position_properties(SGPropertyNode_ptr pos[3]) {
342         _pos_prop[0] = pos[0]; _pos_prop[1] = pos[1]; _pos_prop[2] = pos[2];
343         if (pos[0] || pos[1] || pos[2]) _use_pos_props = true;
344         _changed = true;
345     }
346
347     /**
348      * Get the absolute position of this sound.
349      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
350      * @return Absolute position
351      */
352     SGVec3d& get_position() { return _absolute_pos; }
353
354     /**
355      * Set the orientation of this sound.
356      * @param ori Quaternation containing the orientation information
357      */
358     inline void set_orientation( const SGQuatd& ori ) {
359         _orientation = ori; _changed = true;
360     }
361
362     inline void set_rotation( const SGQuatd& ec2body ) {
363         _rotation = ec2body; _changed = true;
364     }
365
366     /**
367      * Set direction of this sound relative to the orientation.
368      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
369      * @param dir Sound emission direction
370      */
371     inline void set_direction( const SGVec3f& dir ) {
372         _direction = toVec3d(dir); _static_changed = true;
373     }
374
375     /**
376      * Define the audio cone parameters for directional audio.
377      * Note: setting it to 2 degree will result in 1 degree to both sides.
378      * @param inner Inner cone angle (0 - 360 degrees)
379      * @param outer Outer cone angle (0 - 360 degrees)
380      * @param gain Remaining gain at the edge of the outer cone (0.0 - 1.0)
381      */
382     void set_audio_cone( float inner, float outer, float gain ) {
383         _inner_angle = inner; _outer_angle = outer; _outer_gain = gain;
384         _static_changed = true;
385     }
386
387     /**
388      * Get the orientation vector of this sound.
389      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
390      * @return Orientaton vector
391      */
392     SGVec3f& get_orientation() { return _orivec; }
393
394     /**
395      * Get the inner angle of the audio cone.
396      * @return Inner angle in degrees
397      */
398     float get_innerangle() { return _inner_angle; }
399
400     /**
401      * Get the outer angle of the audio cone.
402      * @return Outer angle in degrees
403      */
404     float get_outerangle() { return _outer_angle; }
405
406     /**
407      * Get the remaining gain at the edge of the outer cone.
408      * @return Gain
409      */
410     float get_outergain() { return _outer_gain; }
411
412     /**
413      * Set the velocity vector (in meters per second) of this sound.
414      * This is in the local frame coordinate system; x=north, y=east, z=down
415      *
416      * @param vel Velocity vector
417      */
418     inline void set_velocity( const SGVec3f& vel ) {
419         _velocity = vel; _changed = true;
420     }
421
422     /**
423      * Get velocity vector (in meters per second) of this sound.
424      * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
425      * @return Velocity vector
426      */
427     SGVec3f& get_velocity() { return _velocity; }
428
429
430     /**
431      * Set reference distance (in meters) of this sound.
432      * This is the distance where the gain will be half.
433      * @param dist Reference distance
434      */
435     inline void set_reference_dist( float dist ) {
436         _reference_dist = dist; _static_changed = true;
437     }
438
439     /**
440      * Get reference distance ((in meters) of this sound.
441      * This is the distance where the gain will be half.
442      * @return Reference distance
443      */
444     inline float get_reference_dist() { return _reference_dist; }
445
446
447     /**
448      * Set maximum distance (in meters) of this sound.
449      * This is the distance where this sound is no longer audible.
450      * @param dist Maximum distance
451      */
452     inline void set_max_dist( float dist ) {
453         _max_dist = dist; _static_changed = true;
454     }
455
456     /**
457      * Get maximum distance (in meters) of this sound.
458      * This is the distance where this sound is no longer audible.
459      * @return dist Maximum distance
460      */
461     inline float get_max_dist() { return _max_dist; }
462
463     /**
464      * Get the reference name of this audio sample.
465      * @return Sample name
466      */
467     inline std::string get_sample_name() const { return _refname; }
468     inline void set_sample_name(const std::string& refname) { _refname = refname; }
469
470     inline virtual bool is_queue() const { return false; }
471
472     void update_pos_and_orientation();
473
474 protected:
475     int _format;
476     size_t _size;
477     int _freq;
478     bool _changed;
479     
480     // Sources are points emitting sound.
481     bool _valid_source;
482     unsigned int _source;
483
484 private:
485
486     // Position of the source sound.
487     SGPropertyNode_ptr _pos_prop[3];    // always absolute
488     SGVec3d _absolute_pos;      // absolute position
489     SGVec3d _relative_pos;      // position relative to the base position
490     SGVec3d _direction;         // orientation offset
491     SGVec3f _velocity;          // Velocity of the source sound.
492
493     // The position and orientation of this sound
494     SGQuatd _orientation;       // base orientation
495     SGVec3f _orivec;            // orientation vector for OpenAL
496     SGVec3d _base_pos;          // base position
497
498     SGQuatd _rotation;
499
500     std::string _refname;       // name or file path
501     unsigned char* _data;
502
503     // configuration values
504     
505     // Buffers hold sound data.
506     bool _valid_buffer;
507     unsigned int _buffer;
508
509     // The orientation of this sound (direction and cut-off angles)
510     float _inner_angle;
511     float _outer_angle;
512     float _outer_gain;
513
514     float _pitch;
515     float _volume;
516     float _master_volume;
517     float _reference_dist;
518     float _max_dist;
519     bool _loop;
520
521     bool _playing;
522     bool _static_changed;
523     bool _out_of_range;
524     bool _is_file;
525     bool _use_pos_props;
526
527     std::string random_string();
528 };
529
530
531 #endif // _SG_SAMPLE_HXX
532
533