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