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