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