include (SimGearComponent)
set(HEADERS
+ sample.hxx
sample_group.hxx
- sample_openal.hxx
soundmgr_openal.hxx
xmlsound.hxx
readwav.hxx
)
set(SOURCES
+ sample.cxx
sample_group.cxx
- sample_openal.cxx
soundmgr_openal.cxx
xmlsound.cxx
readwav.cxx
#include "soundmgr_openal.hxx"
#include "sample_group.hxx"
-#include "sample_openal.hxx"
+#include "sample.hxx"
int main( int argc, char *argv[] ) {
#include "soundmgr_openal.hxx"
#include "sample_group.hxx"
-#include "sample_openal.hxx"
+#include "sample.hxx"
int main( int argc, char *argv[] ) {
SGSampleGroup *sgr;
#include <simgear/misc/stdint.hxx>
#include <simgear/structure/exception.hxx>
-#include "sample_openal.hxx"
+#include "sample.hxx"
namespace
{
--- /dev/null
+// sample.cxx -- Audio sample encapsulation class
+//
+// Written by Curtis Olson, started April 2004.
+// Modified to match the new SoundSystem by Erik Hofman, October 2009
+//
+// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
+// Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id$
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include <stdlib.h> // rand(), free()
+#include <cstring>
+#include <stdio.h>
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/misc/ResourceManager.hxx>
+
+#include "soundmgr_openal_private.hxx"
+#include "soundmgr_openal.hxx"
+#include "sample.hxx"
+
+#define AL_FALSE 0
+
+using std::string;
+
+//
+// SGSoundSampleInfo
+//
+
+// empty constructor
+SGSoundSampleInfo::SGSoundSampleInfo() :
+ _refname(random_string()),
+ _bits(16),
+ _tracks(1),
+ _samples(0),
+ _frequency(22500),
+ _compressed(false),
+ _loop(false),
+ _static_changed(true),
+ _playing(false),
+ _pitch(1.0f),
+ _volume(1.0f),
+ _master_volume(1.0f),
+ _use_pos_props(false),
+ _out_of_range(false),
+ _inner_angle(360.0f),
+ _outer_angle(360.0f),
+ _outer_gain(0.0f),
+ _reference_dist(500.0f),
+ _max_dist(3000.0f),
+ _absolute_pos(SGVec3d::zeros()),
+ _relative_pos(SGVec3d::zeros()),
+ _direction(SGVec3d::zeros()),
+ _velocity(SGVec3f::zeros()),
+ _orientation(SGQuatd::zeros()),
+ _orivec(SGVec3f::zeros()),
+ _base_pos(SGVec3d::zeros()),
+ _rotation(SGQuatd::zeros())
+{
+ _pos_prop[0] = 0;
+ _pos_prop[1] = 0;
+ _pos_prop[2] = 0;
+}
+
+std::string SGSoundSampleInfo::random_string()
+{
+ static const char *r = "0123456789abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ string rstr = "Auto: ";
+ for (int i=0; i<10; i++) {
+ rstr.push_back( r[rand() % strlen(r)] );
+ }
+
+ return rstr;
+}
+
+//
+// SGSoundSample
+//
+
+// empty constructor
+SGSoundSample::SGSoundSample() :
+ _is_file(false),
+ _changed(true),
+ _valid_source(false),
+ _source(SGSoundMgr::NO_SOURCE),
+ _data(NULL),
+ _valid_buffer(false),
+ _buffer(SGSoundMgr::NO_BUFFER)
+{
+}
+
+// constructor
+SGSoundSample::SGSoundSample(const char *file, const SGPath& currentDir) :
+ _is_file(true),
+ _changed(true),
+ _valid_source(false),
+ _source(SGSoundMgr::NO_SOURCE),
+ _data(NULL),
+ _valid_buffer(false),
+ _buffer(SGSoundMgr::NO_BUFFER)
+{
+ SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
+ _refname = p.str();
+}
+
+// constructor
+SGSoundSample::SGSoundSample( const unsigned char** data,
+ int len, int freq, int format ) :
+ _is_file(false),
+ _changed(true),
+ _valid_source(false),
+ _source(SGSoundMgr::NO_SOURCE),
+ _valid_buffer(false),
+ _buffer(SGSoundMgr::NO_BUFFER)
+{
+ SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
+ _data = (unsigned char*)*data; *data = NULL;
+}
+
+// constructor
+SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) :
+ _is_file(false),
+ _changed(true),
+ _valid_source(false),
+ _source(SGSoundMgr::NO_SOURCE),
+ _valid_buffer(false),
+ _buffer(SGSoundMgr::NO_BUFFER)
+{
+ SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
+ _data = (unsigned char*)*data; *data = NULL;
+}
+
+
+// destructor
+SGSoundSample::~SGSoundSample() {
+ if ( _data != NULL ) free(_data);
+}
+
+void SGSoundSample::update_pos_and_orientation() {
+
+ if (_use_pos_props) {
+ if (_pos_prop[0]) _absolute_pos[0] = _pos_prop[0]->getDoubleValue();
+ if (_pos_prop[1]) _absolute_pos[1] = _pos_prop[1]->getDoubleValue();
+ if (_pos_prop[2]) _absolute_pos[2] = _pos_prop[2]->getDoubleValue();
+ }
+ else {
+ _absolute_pos = _base_pos;
+ if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
+ _absolute_pos += _rotation.rotate( _relative_pos );
+ }
+ }
+
+ _orivec = SGVec3f::zeros();
+ if ( _direction[0] || _direction[1] || _direction[2] ) {
+ _orivec = toVec3f( _rotation.rotate( _direction ) );
+ }
+}
+
+SGPath SGSoundSample::file_path() const
+{
+ if (!_is_file) {
+ return SGPath();
+ }
+
+ return SGPath(_refname);
+}
+
+void SGSoundSample::free_data()
+{
+ if ( _data != NULL ) {
+ free( _data );
+ }
+ _data = NULL;
+}
--- /dev/null
+// sample.hxx -- Audio sample encapsulation class
+//
+// Written by Curtis Olson, started April 2004.
+// Modified to match the new SoundSystem by Erik Hofman, October 2009
+//
+// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
+// Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// $Id$
+
+/**
+ * \file audio sample.hxx
+ * Provides a audio sample encapsulation
+ */
+
+#ifndef _SG_SAMPLE_HXX
+#define _SG_SAMPLE_HXX 1
+
+#include <simgear/math/SGMath.hxx>
+#include <simgear/props/props.hxx>
+
+enum {
+ SG_SAMPLE_MONO = 1,
+ SG_SAMPLE_STEREO = 2,
+
+ SG_SAMPLE_4BITS = 4,
+ SG_SAMPLE_8BITS = 8,
+ SG_SAMPLE_16BITS = 16,
+
+ SG_SAMPLE_UNCOMPRESSED = 0,
+ SG_SAMPLE_COMPRESSED = 256,
+
+ SG_SAMPLE_MONO8 = (SG_SAMPLE_MONO|SG_SAMPLE_8BITS),
+ SG_SAMPLE_MONO16 = (SG_SAMPLE_MONO|SG_SAMPLE_16BITS),
+ SG_SAMPLE_MULAW = (SG_SAMPLE_MONO|SG_SAMPLE_8BITS|SG_SAMPLE_COMPRESSED),
+ SG_SAMPLE_ADPCM = (SG_SAMPLE_MONO|SG_SAMPLE_4BITS|SG_SAMPLE_COMPRESSED)
+};
+
+
+/**
+ * manages everything we need to know for an individual audio sample
+ */
+
+class SGSoundSampleInfo
+{
+public:
+ SGSoundSampleInfo();
+ ~SGSoundSampleInfo() {}
+
+ /**
+ * Returns the format of this audio sample.
+ * @return SimGear format-id
+ */
+ inline unsigned int get_format() { return (_tracks | _bits | _compressed*256); }
+
+ /**
+ * Get the reference name of this audio sample.
+ * @return Sample name
+ */
+ inline std::string get_sample_name() const { return _refname; }
+
+ /**
+ * Returns the frequency (in Herz) of this audio sample.
+ * @return Frequency
+ */
+ inline unsigned int get_frequency() { return _frequency; }
+
+ /**
+ * Get the current pitch value of this audio sample.
+ * @return Pitch
+ */
+ inline float get_pitch() { return _pitch; }
+
+ /**
+ * Get the final volume value of this audio sample.
+ * @return Volume
+ */
+ inline float get_volume() { return _volume * _master_volume; }
+
+ /**
+ * Returns the size (in bytes) of this audio sample.
+ * @return Data size
+ */
+ inline size_t get_size() const {
+ return (_samples * _tracks * _bits)/8;
+ }
+
+
+ /**
+ * Get the absolute position of this sound.
+ * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
+ * @return Absolute position
+ */
+ inline SGVec3d& get_position() { return _absolute_pos; }
+
+ /**
+ * Get the orientation vector of this sound.
+ * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
+ * @return Orientaton vector
+ */
+ inline SGVec3f& get_orientation() { return _orivec; }
+
+ /**
+ * Get the inner angle of the audio cone.
+ * @return Inner angle in degrees
+ */
+ inline float get_innerangle() { return _inner_angle; }
+
+ /**
+ * Get the outer angle of the audio cone.
+ * @return Outer angle in degrees
+ */
+ inline float get_outerangle() { return _outer_angle; }
+
+ /**
+ * Get the remaining gain at the edge of the outer cone.
+ * @return Gain
+ */
+ inline float get_outergain() { return _outer_gain; }
+
+ /**
+ * Get velocity vector (in meters per second) of this sound.
+ * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
+ * @return Velocity vector
+ */
+ inline SGVec3f& get_velocity() { return _velocity; }
+
+ /**
+ * Get reference distance ((in meters) of this sound.
+ * This is the distance where the gain will be half.
+ * @return Reference distance
+ */
+ inline float get_reference_dist() { return _reference_dist; }
+
+ /**
+ * Get maximum distance (in meters) of this sound.
+ * This is the distance where this sound is no longer audible.
+ * @return dist Maximum distance
+ */
+ inline float get_max_dist() { return _max_dist; }
+
+ /**
+ * Test if static data of audio sample configuration has changed.
+ * Calling this function will reset the flag so calling it a second
+ * time in a row will return false.
+ * @return Return true is the static data has changed in the mean time.
+ */
+ bool has_static_data_changed() {
+ bool b = _static_changed; _static_changed = false; return b;
+ }
+
+protected:
+ // static sound emitter info
+ std::string _refname;
+ unsigned int _bits;
+ unsigned int _tracks;
+ unsigned int _samples;
+ unsigned int _frequency;
+ bool _compressed;
+ bool _loop;
+
+ // dynamic sound emitter info (non 3d)
+ bool _static_changed;
+ bool _playing;
+
+ float _pitch;
+ float _volume;
+ float _master_volume;
+
+ // dynamic sound emitter info (3d)
+ bool _use_pos_props;
+ bool _out_of_range;
+
+ float _inner_angle;
+ float _outer_angle;
+ float _outer_gain;
+
+ float _reference_dist;
+ float _max_dist;
+
+ SGPropertyNode_ptr _pos_prop[3];
+ SGVec3d _absolute_pos; // absolute position
+ SGVec3d _relative_pos; // position relative to the base position
+ SGVec3d _direction; // orientation offset
+ SGVec3f _velocity; // Velocity of the source sound.
+
+ // The position and orientation of this sound
+ SGQuatd _orientation; // base orientation
+ SGVec3f _orivec; // orientation vector
+ SGVec3d _base_pos; // base position
+
+ SGQuatd _rotation;
+
+private:
+ static std::string random_string();
+};
+
+
+class SGSoundSample : public SGSoundSampleInfo, public SGReferenced {
+public:
+
+ /**
+ * Empty constructor, can be used to read data to the systems
+ * memory and not to the driver.
+ */
+ SGSoundSample();
+
+ /**
+ * Constructor
+ * @param file File name of sound
+ Buffer data is freed by the sample group
+ */
+ SGSoundSample(const char *file, const SGPath& currentDir);
+
+ /**
+ * Constructor.
+ * @param data Pointer to a memory buffer containing this audio sample data
+ The application may free the data by calling free_data(), otherwise it
+ will be resident until the class is destroyed. This pointer will be
+ set to NULL after calling this function.
+ * @param len Byte length of array
+ * @param freq Frequency of the provided data (bytes per second)
+ * @param format SimGear format id of the data
+ */
+ SGSoundSample( void** data, int len, int freq, int format=SG_SAMPLE_MONO8 );
+ SGSoundSample( const unsigned char** data, int len, int freq,
+ int format = SG_SAMPLE_MONO8 );
+
+ /**
+ * Destructor
+ */
+ virtual ~SGSoundSample ();
+
+ /**
+ * Test if this audio sample configuration has changed since the last call.
+ * Calling this function will reset the flag so calling it a second
+ * time in a row will return false.
+ * @return Return true is the configuration has changed in the mean time.
+ */
+ bool has_changed() {
+ bool b = _changed; _changed = false; return b;
+ }
+
+ /**
+ * Detect whether this audio sample holds the information of a sound file.
+ * @return Return true if this sample is to be constructed from a file.
+ */
+ inline bool is_file() const { return _is_file; }
+
+ SGPath file_path() const;
+
+ /**
+ * Schedule this audio sample for playing. Actual playing will only start
+ * at the next call op SoundGroup::update()
+ * @param _loop Define whether this sound should be played in a loop.
+ */
+ void play( bool loop = false ) {
+ _playing = true; _loop = loop; _changed = true; _static_changed = true;
+ }
+
+ /**
+ * Check if this audio sample is set to be continuous looping.
+ * @return Return true if this audio sample is set to looping.
+ */
+ inline bool is_looping() { return _loop; }
+
+ /**
+ * Schedule this audio sample to stop playing.
+ */
+ virtual void stop() {
+ _playing = false; _changed = true;
+ }
+
+ /**
+ * Schedule this audio sample to play once.
+ * @see #play
+ */
+ inline void play_once() { play(false); }
+
+ /**
+ * Schedule this audio sample to play looped.
+ * @see #play
+ */
+ inline void play_looped() { play(true); }
+
+ /**
+ * Test if a audio sample is scheduled for playing.
+ * @return true if this audio sample is playing, false otherwise.
+ */
+ inline bool is_playing() { return _playing; }
+
+
+ /**
+ * Set this sample to out-of-range (or not) and
+ * Schedule this audio sample to stop (or start) playing.
+ */
+ inline void set_out_of_range(bool oor = true) {
+ _out_of_range = oor; _playing = (!oor && _loop); _changed = true;
+ }
+
+ /**
+ * Test if this sample to out-of-range or not.
+ */
+ inline bool test_out_of_range() {
+ return _out_of_range;
+ }
+
+ /**
+ * Set the data associated with this audio sample
+ * @param data Pointer to a memory block containg this audio sample data.
+ This pointer will be set to NULL after calling this function.
+ */
+ inline void set_data( const unsigned char **data ) {
+ _data = (unsigned char*)*data; *data = NULL;
+ }
+ inline void set_data( const void **data ) {
+ _data = (unsigned char*)*data; *data = NULL;
+ }
+
+ /**
+ * Return the data associated with this audio sample.
+ * @return A pointer to this sound data of this audio sample.
+ */
+ inline void* get_data() const { return _data; }
+
+ /**
+ * Free the data associated with this audio sample
+ */
+ void free_data();
+
+ /**
+ * Set the source id of this source
+ * @param sid source-id
+ */
+ virtual void set_source(unsigned int sid) {
+ _source = sid; _valid_source = true; _changed = true;
+ }
+
+ /**
+ * Get the source id of this source
+ * @return source-id
+ */
+ virtual unsigned int get_source() { return _source; }
+
+ /**
+ * Test if the source-id of this audio sample is usable.
+ * @return true if the source-id is valid
+ */
+ virtual bool is_valid_source() const { return _valid_source; }
+
+ /**
+ * Set the source-id of this audio sample to invalid.
+ */
+ virtual void no_valid_source() { _valid_source = false; }
+
+ /**
+ * Set the buffer-id of this source
+ * @param bid buffer-id
+ */
+ inline void set_buffer(unsigned int bid) {
+ _buffer = bid; _valid_buffer = true; _changed = true;
+ }
+
+ /**
+ * Get the buffer-id of this source
+ * @return buffer-id
+ */
+ inline unsigned int get_buffer() { return _buffer; }
+
+ /**
+ * Test if the buffer-id of this audio sample is usable.
+ * @return true if the buffer-id is valid
+ */
+ inline bool is_valid_buffer() const { return _valid_buffer; }
+
+ /**
+ * Set the buffer-id of this audio sample to invalid.
+ */
+ inline void no_valid_buffer() { _valid_buffer = false; }
+
+ /**
+ * Set the playback pitch of this audio sample.
+ * Should be between 0.0 and 2.0 for maximum compatibility.
+ * @param p Pitch
+ */
+ inline void set_pitch( float p ) {
+ if (p > 2.0) p = 2.0; else if (p < 0.01) p = 0.01;
+ _pitch = p; _changed = true;
+ }
+
+ /**
+ * Set the master volume of this sample. Should be between 0.0 and 1.0.
+ * The final volume is calculated by multiplying the master and audio sample
+ * volume.
+ * @param v Volume
+ */
+ inline void set_master_volume( float v ) {
+ if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
+ _master_volume = v; _changed = true;
+ }
+
+ /**
+ * Set the volume of this audio sample. Should be between 0.0 and 1.0.
+ * The final volume is calculated by multiplying the master and audio sample
+ * volume.
+ * @param v Volume
+ */
+ inline void set_volume( float v ) {
+ if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
+ _volume = v; _changed = true;
+ }
+
+ /**
+ * Set the SimGear format of this audio sample.
+ * @param format SimGear format-id
+ */
+ inline void set_format( int fmt ) {
+ _tracks = fmt & 0x3; _bits = fmt & 0x1C; _compressed = fmt & 0x100;
+ }
+
+ /**
+ * Set the frequency (in Herz) of this audio sample.
+ * @param freq Frequency
+ */
+ inline void set_frequency( int freq ) { _frequency = freq; }
+
+ /**
+ * Sets the size (in bytes) of this audio sample.
+ * @param size Data size
+ */
+ inline void set_size( size_t size ) {
+ _samples = size*8/(_bits*_tracks);
+ }
+ inline void set_no_samples(size_t samples) { _samples = samples; }
+
+ /**
+ * Set the position of this sound relative to the base position.
+ * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
+ * @param pos Relative position of this sound
+ */
+ inline void set_relative_position( const SGVec3f& pos ) {
+ _relative_pos = toVec3d(pos); _changed = true;
+ }
+
+ /**
+ * Set the base position in Cartesian coordinates
+ * @param pos position in Cartesian coordinates
+ */
+ inline void set_position( const SGVec3d& pos ) {
+ _base_pos = pos; _changed = true;
+ }
+
+ inline void set_position_properties(SGPropertyNode_ptr pos[3]) {
+ _pos_prop[0] = pos[0]; _pos_prop[1] = pos[1]; _pos_prop[2] = pos[2];
+ if (pos[0] || pos[1] || pos[2]) _use_pos_props = true;
+ _changed = true;
+ }
+
+ /**
+ * Set the orientation of this sound.
+ * @param ori Quaternation containing the orientation information
+ */
+ inline void set_orientation( const SGQuatd& ori ) {
+ _orientation = ori; _changed = true;
+ }
+
+ inline void set_rotation( const SGQuatd& ec2body ) {
+ _rotation = ec2body; _changed = true;
+ }
+
+ /**
+ * Set direction of this sound relative to the orientation.
+ * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
+ * @param dir Sound emission direction
+ */
+ inline void set_direction( const SGVec3f& dir ) {
+ _direction = toVec3d(dir); _static_changed = true;
+ }
+
+ /**
+ * Define the audio cone parameters for directional audio.
+ * Note: setting it to 2 degree will result in 1 degree to both sides.
+ * @param inner Inner cone angle (0 - 360 degrees)
+ * @param outer Outer cone angle (0 - 360 degrees)
+ * @param gain Remaining gain at the edge of the outer cone (0.0 - 1.0)
+ */
+ void set_audio_cone( float inner, float outer, float gain ) {
+ _inner_angle = inner; _outer_angle = outer; _outer_gain = gain;
+ _static_changed = true;
+ }
+
+ /**
+ * Set the velocity vector (in meters per second) of this sound.
+ * This is in the local frame coordinate system; x=north, y=east, z=down
+ * @param Velocity vector
+ */
+ inline void set_velocity( const SGVec3f& vel ) {
+ _velocity = vel; _changed = true;
+ }
+
+ /**
+ * Set reference distance (in meters) of this sound.
+ * This is the distance where the gain will be half.
+ * @param dist Reference distance
+ */
+ inline void set_reference_dist( float dist ) {
+ _reference_dist = dist; _static_changed = true;
+ }
+
+ /**
+ * Set maximum distance (in meters) of this sound.
+ * This is the distance where this sound is no longer audible.
+ * @param dist Maximum distance
+ */
+ inline void set_max_dist( float dist ) {
+ _max_dist = dist; _static_changed = true;
+ }
+
+ inline virtual bool is_queue() const { return false; }
+
+ void update_pos_and_orientation();
+
+protected:
+ bool _is_file;
+ bool _changed;
+
+ // Sources are points emitting sound.
+ bool _valid_source;
+ unsigned int _source;
+
+private:
+ unsigned char* _data;
+
+ // Buffers hold sound data.
+ bool _valid_buffer;
+ unsigned int _buffer;
+};
+
+#endif // _SG_SAMPLE_HXX
+
+
# include <simgear_config.h>
#endif
-#include <cassert>
#include <simgear/compiler.h>
#include <simgear/sg_inlines.h>
#include <simgear/debug/logstream.hxx>
_smgr = 0;
}
-static bool is_sample_stopped(SGSoundSample *sample)
-{
-#ifdef ENABLE_SOUND
- assert(sample->is_valid_source());
- unsigned int source = sample->get_source();
- int result;
- alGetSourcei( source, AL_SOURCE_STATE, &result );
- return (result == AL_STOPPED);
-#else
- return true;
-#endif
-}
-
void SGSampleGroup::cleanup_removed_samples()
{
// Delete any OpenAL buffers that might still be in use.
unsigned int size = _removed_samples.size();
for (unsigned int i=0; i<size; ) {
SGSoundSample *sample = _removed_samples[i];
- bool stopped = is_sample_stopped(sample);
- if ( sample->is_valid_source() ) {
- int source = sample->get_source();
-
- if ( sample->is_looping() && !stopped) {
-#ifdef ENABLE_SOUND
- alSourceStop( source );
-#endif
- stopped = is_sample_stopped(sample);
- }
-
- if ( stopped ) {
- sample->no_valid_source();
- _smgr->release_source( source );
- }
- }
+ _smgr->sample_stop(sample);
+ bool stopped = _smgr->is_sample_stopped(sample);
if ( stopped ) {
sample->stop();
void SGSampleGroup::start_playing_sample(SGSoundSample *sample)
{
-#ifdef ENABLE_SOUND
- //
- // a request to start playing a sound has been filed.
- //
- ALuint source = _smgr->request_source();
- if (alIsSource(source) == AL_FALSE ) {
- return;
- }
-
- sample->set_source( source );
+ _smgr->sample_init( sample );
update_sample_config( sample );
- ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
-
- if ( !sample->is_queue() )
- {
- ALuint buffer = _smgr->request_buffer(sample);
- if (buffer == SGSoundMgr::FAILED_BUFFER ||
- buffer == SGSoundMgr::NO_BUFFER)
- {
- _smgr->release_source(source);
- return;
- }
-
- // start playing the sample
- buffer = sample->get_buffer();
- if ( alIsBuffer(buffer) == AL_TRUE )
- {
- alSourcei( source, AL_BUFFER, buffer );
- testForALError("assign buffer to source");
- } else
- SG_LOG( SG_SOUND, SG_ALERT, "No such buffer!");
- }
-
- alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
- alSourcei( source, AL_LOOPING, looping );
- alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
- alSourcePlay( source );
- testForALError("sample play");
-#endif
+ _smgr->sample_play( sample );
}
void SGSampleGroup::check_playing_sample(SGSoundSample *sample)
{
// check if the sound has stopped by itself
- if (is_sample_stopped(sample)) {
+ if (_smgr->is_sample_stopped(sample)) {
// sample is stopped because it wasn't looping
sample->stop();
sample->no_valid_source();
sample_map_iterator sample_end = _samples.end();
for ( ; sample_current != sample_end; ++sample_current ) {
SGSoundSample *sample = sample_current->second;
-
- if ( sample->is_valid_source() ) {
-#ifdef ENABLE_SOUND
- ALint source = sample->get_source();
- if ( sample->is_playing() ) {
- alSourceStop( source );
- testForALError("stop");
- }
- _smgr->release_source( source );
-#endif
- sample->no_valid_source();
- }
-
- if ( sample->is_valid_buffer() ) {
- _smgr->release_buffer( sample );
- sample->no_valid_buffer();
- }
+ _smgr->sample_destroy( sample );
}
}
for ( ; sample_current != sample_end; ++sample_current ) {
#ifdef ENABLE_SOUND
SGSoundSample *sample = sample_current->second;
- if ( sample->is_valid_source() && sample->is_playing() ) {
- alSourcePause( sample->get_source() );
- }
+ _smgr->sample_suspend( sample );
#endif
}
testForALError("suspend");
sample_map_iterator sample_end = _samples.end();
for ( ; sample_current != sample_end; ++sample_current ) {
SGSoundSample *sample = sample_current->second;
- if ( sample->is_valid_source() && sample->is_playing() ) {
- alSourcePlay( sample->get_source() );
- }
+ _smgr->sample_resume( sample );
}
testForALError("resume");
#endif
if (isNaN(velocity.data())) printf("NaN in source velocity\n");
#endif
- unsigned int source = sample->get_source();
- alSourcefv( source, AL_POSITION, toVec3f(position).data() );
- alSourcefv( source, AL_VELOCITY, velocity.data() );
- alSourcefv( source, AL_DIRECTION, orientation.data() );
- testForALError("position and orientation");
-
- alSourcef( source, AL_PITCH, sample->get_pitch() );
- alSourcef( source, AL_GAIN, sample->get_volume() );
- testForALError("pitch and gain");
-
- if ( sample->has_static_data_changed() ) {
- alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() );
- alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() );
- alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() );
- testForALError("audio cone");
-
- alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() );
- alSourcef( source, AL_REFERENCE_DISTANCE,
- sample->get_reference_dist() );
- testForALError("distance rolloff");
- }
+ _smgr->update_sample_config( sample, position, orientation, velocity );
#endif
}
bool SGSampleGroup::testForALError(std::string s)
{
-#ifdef SG_C
- ALenum error = alGetError();
- if (error != AL_NO_ERROR) {
- SG_LOG( SG_SOUND, SG_ALERT, "AL Error (" << _refname << "): "
- << alGetString(error) << " at " << s);
- return true;
- }
-#endif
+ _smgr->testForError(s, _refname);
return false;
}
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/structure/exception.hxx>
-#include "sample_openal.hxx"
+#include "sample.hxx"
typedef std::map < std::string, SGSharedPtr<SGSoundSample> > sample_map;
+++ /dev/null
-// sample_openal.cxx -- Audio sample encapsulation class
-//
-// Written by Curtis Olson, started April 2004.
-// Modified to match the new SoundSystem by Erik Hofman, October 2009
-//
-// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
-// Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// $Id$
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#include <stdlib.h> // rand(), free()
-#include <cstring>
-#include <stdio.h>
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/structure/exception.hxx>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/misc/ResourceManager.hxx>
-
-#include "soundmgr_openal.hxx"
-#include "sample_openal.hxx"
-#include "soundmgr_openal_private.hxx"
-
-#define AL_FALSE 0
-
-using std::string;
-
-//
-// SGSoundSampleInfo
-//
-
-// empty constructor
-SGSoundSampleInfo::SGSoundSampleInfo() :
- _refname(random_string()),
- _bits(16),
- _tracks(1),
- _samples(0),
- _frequency(22500),
- _compressed(false),
- _loop(false),
- _static_changed(true),
- _playing(false),
- _pitch(1.0f),
- _volume(1.0f),
- _master_volume(1.0f),
- _use_pos_props(false),
- _out_of_range(false),
- _inner_angle(360.0f),
- _outer_angle(360.0f),
- _outer_gain(0.0f),
- _reference_dist(500.0f),
- _max_dist(3000.0f),
- _absolute_pos(SGVec3d::zeros()),
- _relative_pos(SGVec3d::zeros()),
- _direction(SGVec3d::zeros()),
- _velocity(SGVec3f::zeros()),
- _orientation(SGQuatd::zeros()),
- _orivec(SGVec3f::zeros()),
- _base_pos(SGVec3d::zeros()),
- _rotation(SGQuatd::zeros())
-{
- _pos_prop[0] = 0;
- _pos_prop[1] = 0;
- _pos_prop[2] = 0;
-}
-
-std::string SGSoundSampleInfo::random_string()
-{
- static const char *r = "0123456789abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- string rstr = "Auto: ";
- for (int i=0; i<10; i++) {
- rstr.push_back( r[rand() % strlen(r)] );
- }
-
- return rstr;
-}
-
-//
-// SGSoundSample
-//
-
-// empty constructor
-SGSoundSample::SGSoundSample() :
- _is_file(false),
- _changed(true),
- _valid_source(false),
- _source(SGSoundMgr::NO_SOURCE),
- _data(NULL),
- _valid_buffer(false),
- _buffer(SGSoundMgr::NO_BUFFER)
-{
-}
-
-// constructor
-SGSoundSample::SGSoundSample(const char *file, const SGPath& currentDir) :
- _is_file(true),
- _changed(true),
- _valid_source(false),
- _source(SGSoundMgr::NO_SOURCE),
- _data(NULL),
- _valid_buffer(false),
- _buffer(SGSoundMgr::NO_BUFFER)
-{
- SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
- _refname = p.str();
-}
-
-// constructor
-SGSoundSample::SGSoundSample( const unsigned char** data,
- int len, int freq, int format ) :
- _is_file(false),
- _changed(true),
- _valid_source(false),
- _source(SGSoundMgr::NO_SOURCE),
- _valid_buffer(false),
- _buffer(SGSoundMgr::NO_BUFFER)
-{
- SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
- _data = (unsigned char*)*data; *data = NULL;
-}
-
-// constructor
-SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) :
- _is_file(false),
- _changed(true),
- _valid_source(false),
- _source(SGSoundMgr::NO_SOURCE),
- _valid_buffer(false),
- _buffer(SGSoundMgr::NO_BUFFER)
-{
- SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
- _data = (unsigned char*)*data; *data = NULL;
-}
-
-
-// destructor
-SGSoundSample::~SGSoundSample() {
- if ( _data != NULL ) free(_data);
-}
-
-void SGSoundSample::update_pos_and_orientation() {
-
- if (_use_pos_props) {
- if (_pos_prop[0]) _absolute_pos[0] = _pos_prop[0]->getDoubleValue();
- if (_pos_prop[1]) _absolute_pos[1] = _pos_prop[1]->getDoubleValue();
- if (_pos_prop[2]) _absolute_pos[2] = _pos_prop[2]->getDoubleValue();
- }
- else {
- _absolute_pos = _base_pos;
- if (_relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
- _absolute_pos += _rotation.rotate( _relative_pos );
- }
- }
-
- _orivec = SGVec3f::zeros();
- if ( _direction[0] || _direction[1] || _direction[2] ) {
- _orivec = toVec3f( _rotation.rotate( _direction ) );
- }
-}
-
-SGPath SGSoundSample::file_path() const
-{
- if (!_is_file) {
- return SGPath();
- }
-
- return SGPath(_refname);
-}
-
-void SGSoundSample::free_data()
-{
- if ( _data != NULL ) {
- free( _data );
- }
- _data = NULL;
-}
+++ /dev/null
-// sample_openal.hxx -- Audio sample encapsulation class
-//
-// Written by Curtis Olson, started April 2004.
-// Modified to match the new SoundSystem by Erik Hofman, October 2009
-//
-// Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
-// Copyright (C) 2009 Erik Hofman <erik@ehofman.com>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// $Id$
-
-/**
- * \file audio sample.hxx
- * Provides a audio sample encapsulation
- */
-
-#ifndef _SG_SAMPLE_HXX
-#define _SG_SAMPLE_HXX 1
-
-#include <simgear/math/SGMath.hxx>
-#include <simgear/props/props.hxx>
-
-enum {
- SG_SAMPLE_MONO = 1,
- SG_SAMPLE_STEREO = 2,
-
- SG_SAMPLE_4BITS = 4,
- SG_SAMPLE_8BITS = 8,
- SG_SAMPLE_16BITS = 16,
-
- SG_SAMPLE_UNCOMPRESSED = 0,
- SG_SAMPLE_COMPRESSED = 256,
-
- SG_SAMPLE_MONO8 = (SG_SAMPLE_MONO|SG_SAMPLE_8BITS),
- SG_SAMPLE_MONO16 = (SG_SAMPLE_MONO|SG_SAMPLE_16BITS),
- SG_SAMPLE_MULAW = (SG_SAMPLE_MONO|SG_SAMPLE_8BITS|SG_SAMPLE_COMPRESSED),
- SG_SAMPLE_ADPCM = (SG_SAMPLE_MONO|SG_SAMPLE_4BITS|SG_SAMPLE_COMPRESSED)
-};
-
-
-/**
- * manages everything we need to know for an individual audio sample
- */
-
-class SGSoundSampleInfo
-{
-public:
- SGSoundSampleInfo();
- ~SGSoundSampleInfo() {}
-
- /**
- * Returns the format of this audio sample.
- * @return SimGear format-id
- */
- inline unsigned int get_format() { return (_tracks | _bits | _compressed*256); }
-
- /**
- * Get the reference name of this audio sample.
- * @return Sample name
- */
- inline std::string get_sample_name() const { return _refname; }
-
- /**
- * Returns the frequency (in Herz) of this audio sample.
- * @return Frequency
- */
- inline unsigned int get_frequency() { return _frequency; }
-
- /**
- * Get the current pitch value of this audio sample.
- * @return Pitch
- */
- inline float get_pitch() { return _pitch; }
-
- /**
- * Get the final volume value of this audio sample.
- * @return Volume
- */
- inline float get_volume() { return _volume * _master_volume; }
-
- /**
- * Returns the size (in bytes) of this audio sample.
- * @return Data size
- */
- inline size_t get_size() const {
- return (_samples * _tracks * _bits)/8;
- }
-
-
- /**
- * Get the absolute position of this sound.
- * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
- * @return Absolute position
- */
- inline SGVec3d& get_position() { return _absolute_pos; }
-
- /**
- * Get the orientation vector of this sound.
- * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
- * @return Orientaton vector
- */
- inline SGVec3f& get_orientation() { return _orivec; }
-
- /**
- * Get the inner angle of the audio cone.
- * @return Inner angle in degrees
- */
- inline float get_innerangle() { return _inner_angle; }
-
- /**
- * Get the outer angle of the audio cone.
- * @return Outer angle in degrees
- */
- inline float get_outerangle() { return _outer_angle; }
-
- /**
- * Get the remaining gain at the edge of the outer cone.
- * @return Gain
- */
- inline float get_outergain() { return _outer_gain; }
-
- /**
- * Get velocity vector (in meters per second) of this sound.
- * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
- * @return Velocity vector
- */
- inline SGVec3f& get_velocity() { return _velocity; }
-
- /**
- * Get reference distance ((in meters) of this sound.
- * This is the distance where the gain will be half.
- * @return Reference distance
- */
- inline float get_reference_dist() { return _reference_dist; }
-
- /**
- * Get maximum distance (in meters) of this sound.
- * This is the distance where this sound is no longer audible.
- * @return dist Maximum distance
- */
- inline float get_max_dist() { return _max_dist; }
-
- /**
- * Test if static data of audio sample configuration has changed.
- * Calling this function will reset the flag so calling it a second
- * time in a row will return false.
- * @return Return true is the static data has changed in the mean time.
- */
- bool has_static_data_changed() {
- bool b = _static_changed; _static_changed = false; return b;
- }
-
-protected:
- // static sound emitter info
- std::string _refname;
- unsigned int _bits;
- unsigned int _tracks;
- unsigned int _samples;
- unsigned int _frequency;
- bool _compressed;
- bool _loop;
-
- // dynamic sound emitter info (non 3d)
- bool _static_changed;
- bool _playing;
-
- float _pitch;
- float _volume;
- float _master_volume;
-
- // dynamic sound emitter info (3d)
- bool _use_pos_props;
- bool _out_of_range;
-
- float _inner_angle;
- float _outer_angle;
- float _outer_gain;
-
- float _reference_dist;
- float _max_dist;
-
- SGPropertyNode_ptr _pos_prop[3];
- SGVec3d _absolute_pos; // absolute position
- SGVec3d _relative_pos; // position relative to the base position
- SGVec3d _direction; // orientation offset
- SGVec3f _velocity; // Velocity of the source sound.
-
- // The position and orientation of this sound
- SGQuatd _orientation; // base orientation
- SGVec3f _orivec; // orientation vector
- SGVec3d _base_pos; // base position
-
- SGQuatd _rotation;
-
-private:
- static std::string random_string();
-};
-
-
-class SGSoundSample : public SGSoundSampleInfo, public SGReferenced {
-public:
-
- /**
- * Empty constructor, can be used to read data to the systems
- * memory and not to the driver.
- */
- SGSoundSample();
-
- /**
- * Constructor
- * @param file File name of sound
- Buffer data is freed by the sample group
- */
- SGSoundSample(const char *file, const SGPath& currentDir);
-
- /**
- * Constructor.
- * @param data Pointer to a memory buffer containing this audio sample data
- The application may free the data by calling free_data(), otherwise it
- will be resident until the class is destroyed. This pointer will be
- set to NULL after calling this function.
- * @param len Byte length of array
- * @param freq Frequency of the provided data (bytes per second)
- * @param format SimGear format id of the data
- */
- SGSoundSample( void** data, int len, int freq, int format=SG_SAMPLE_MONO8 );
- SGSoundSample( const unsigned char** data, int len, int freq,
- int format = SG_SAMPLE_MONO8 );
-
- /**
- * Destructor
- */
- virtual ~SGSoundSample ();
-
- /**
- * Test if this audio sample configuration has changed since the last call.
- * Calling this function will reset the flag so calling it a second
- * time in a row will return false.
- * @return Return true is the configuration has changed in the mean time.
- */
- bool has_changed() {
- bool b = _changed; _changed = false; return b;
- }
-
- /**
- * Detect whether this audio sample holds the information of a sound file.
- * @return Return true if this sample is to be constructed from a file.
- */
- inline bool is_file() const { return _is_file; }
-
- SGPath file_path() const;
-
- /**
- * Schedule this audio sample for playing. Actual playing will only start
- * at the next call op SoundGroup::update()
- * @param _loop Define whether this sound should be played in a loop.
- */
- void play( bool loop = false ) {
- _playing = true; _loop = loop; _changed = true; _static_changed = true;
- }
-
- /**
- * Check if this audio sample is set to be continuous looping.
- * @return Return true if this audio sample is set to looping.
- */
- inline bool is_looping() { return _loop; }
-
- /**
- * Schedule this audio sample to stop playing.
- */
- virtual void stop() {
- _playing = false; _changed = true;
- }
-
- /**
- * Schedule this audio sample to play once.
- * @see #play
- */
- inline void play_once() { play(false); }
-
- /**
- * Schedule this audio sample to play looped.
- * @see #play
- */
- inline void play_looped() { play(true); }
-
- /**
- * Test if a audio sample is scheduled for playing.
- * @return true if this audio sample is playing, false otherwise.
- */
- inline bool is_playing() { return _playing; }
-
-
- /**
- * Set this sample to out-of-range (or not) and
- * Schedule this audio sample to stop (or start) playing.
- */
- inline void set_out_of_range(bool oor = true) {
- _out_of_range = oor; _playing = (!oor && _loop); _changed = true;
- }
-
- /**
- * Test if this sample to out-of-range or not.
- */
- inline bool test_out_of_range() {
- return _out_of_range;
- }
-
- /**
- * Set the data associated with this audio sample
- * @param data Pointer to a memory block containg this audio sample data.
- This pointer will be set to NULL after calling this function.
- */
- inline void set_data( const unsigned char **data ) {
- _data = (unsigned char*)*data; *data = NULL;
- }
- inline void set_data( const void **data ) {
- _data = (unsigned char*)*data; *data = NULL;
- }
-
- /**
- * Return the data associated with this audio sample.
- * @return A pointer to this sound data of this audio sample.
- */
- inline void* get_data() const { return _data; }
-
- /**
- * Free the data associated with this audio sample
- */
- void free_data();
-
- /**
- * Set the source id of this source
- * @param sid source-id
- */
- virtual void set_source(unsigned int sid) {
- _source = sid; _valid_source = true; _changed = true;
- }
-
- /**
- * Get the source id of this source
- * @return source-id
- */
- virtual unsigned int get_source() { return _source; }
-
- /**
- * Test if the source-id of this audio sample is usable.
- * @return true if the source-id is valid
- */
- virtual bool is_valid_source() const { return _valid_source; }
-
- /**
- * Set the source-id of this audio sample to invalid.
- */
- virtual void no_valid_source() { _valid_source = false; }
-
- /**
- * Set the buffer-id of this source
- * @param bid buffer-id
- */
- inline void set_buffer(unsigned int bid) {
- _buffer = bid; _valid_buffer = true; _changed = true;
- }
-
- /**
- * Get the buffer-id of this source
- * @return buffer-id
- */
- inline unsigned int get_buffer() { return _buffer; }
-
- /**
- * Test if the buffer-id of this audio sample is usable.
- * @return true if the buffer-id is valid
- */
- inline bool is_valid_buffer() const { return _valid_buffer; }
-
- /**
- * Set the buffer-id of this audio sample to invalid.
- */
- inline void no_valid_buffer() { _valid_buffer = false; }
-
- /**
- * Set the playback pitch of this audio sample.
- * Should be between 0.0 and 2.0 for maximum compatibility.
- * @param p Pitch
- */
- inline void set_pitch( float p ) {
- if (p > 2.0) p = 2.0; else if (p < 0.01) p = 0.01;
- _pitch = p; _changed = true;
- }
-
- /**
- * Set the master volume of this sample. Should be between 0.0 and 1.0.
- * The final volume is calculated by multiplying the master and audio sample
- * volume.
- * @param v Volume
- */
- inline void set_master_volume( float v ) {
- if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
- _master_volume = v; _changed = true;
- }
-
- /**
- * Set the volume of this audio sample. Should be between 0.0 and 1.0.
- * The final volume is calculated by multiplying the master and audio sample
- * volume.
- * @param v Volume
- */
- inline void set_volume( float v ) {
- if (v > 1.0) v = 1.0; else if (v < 0.0) v = 0.0;
- _volume = v; _changed = true;
- }
-
- /**
- * Set the SimGear format of this audio sample.
- * @param format SimGear format-id
- */
- inline void set_format( int fmt ) {
- _tracks = fmt & 0x3; _bits = fmt & 0x1C; _compressed = fmt & 0x100;
- }
-
- /**
- * Set the frequency (in Herz) of this audio sample.
- * @param freq Frequency
- */
- inline void set_frequency( int freq ) { _frequency = freq; }
-
- /**
- * Sets the size (in bytes) of this audio sample.
- * @param size Data size
- */
- inline void set_size( size_t size ) {
- _samples = size*8/(_bits*_tracks);
- }
- inline void set_no_samples(size_t samples) { _samples = samples; }
-
- /**
- * Set the position of this sound relative to the base position.
- * This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
- * @param pos Relative position of this sound
- */
- inline void set_relative_position( const SGVec3f& pos ) {
- _relative_pos = toVec3d(pos); _changed = true;
- }
-
- /**
- * Set the base position in Cartesian coordinates
- * @param pos position in Cartesian coordinates
- */
- inline void set_position( const SGVec3d& pos ) {
- _base_pos = pos; _changed = true;
- }
-
- inline void set_position_properties(SGPropertyNode_ptr pos[3]) {
- _pos_prop[0] = pos[0]; _pos_prop[1] = pos[1]; _pos_prop[2] = pos[2];
- if (pos[0] || pos[1] || pos[2]) _use_pos_props = true;
- _changed = true;
- }
-
- /**
- * Set the orientation of this sound.
- * @param ori Quaternation containing the orientation information
- */
- inline void set_orientation( const SGQuatd& ori ) {
- _orientation = ori; _changed = true;
- }
-
- inline void set_rotation( const SGQuatd& ec2body ) {
- _rotation = ec2body; _changed = true;
- }
-
- /**
- * Set direction of this sound relative to the orientation.
- * This is in the same coordinate system as OpenGL; y=up, z=back, x=right
- * @param dir Sound emission direction
- */
- inline void set_direction( const SGVec3f& dir ) {
- _direction = toVec3d(dir); _static_changed = true;
- }
-
- /**
- * Define the audio cone parameters for directional audio.
- * Note: setting it to 2 degree will result in 1 degree to both sides.
- * @param inner Inner cone angle (0 - 360 degrees)
- * @param outer Outer cone angle (0 - 360 degrees)
- * @param gain Remaining gain at the edge of the outer cone (0.0 - 1.0)
- */
- void set_audio_cone( float inner, float outer, float gain ) {
- _inner_angle = inner; _outer_angle = outer; _outer_gain = gain;
- _static_changed = true;
- }
-
- /**
- * Set the velocity vector (in meters per second) of this sound.
- * This is in the local frame coordinate system; x=north, y=east, z=down
- * @param Velocity vector
- */
- inline void set_velocity( const SGVec3f& vel ) {
- _velocity = vel; _changed = true;
- }
-
- /**
- * Set reference distance (in meters) of this sound.
- * This is the distance where the gain will be half.
- * @param dist Reference distance
- */
- inline void set_reference_dist( float dist ) {
- _reference_dist = dist; _static_changed = true;
- }
-
- /**
- * Set maximum distance (in meters) of this sound.
- * This is the distance where this sound is no longer audible.
- * @param dist Maximum distance
- */
- inline void set_max_dist( float dist ) {
- _max_dist = dist; _static_changed = true;
- }
-
- inline virtual bool is_queue() const { return false; }
-
- void update_pos_and_orientation();
-
-protected:
- bool _is_file;
- bool _changed;
-
- // Sources are points emitting sound.
- bool _valid_source;
- unsigned int _source;
-
-private:
- unsigned char* _data;
-
- // Buffers hold sound data.
- bool _valid_buffer;
- unsigned int _buffer;
-};
-
-#endif // _SG_SAMPLE_HXX
-
-
#include <iostream>
#include <algorithm>
#include <cstring>
+#include <cassert>
#include <boost/foreach.hpp>
// AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE));
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
- testForALError("listener initialization");
+ testForError("listener initialization");
// get a free source one at a time
// if an error is returned no more (hardware) sources are available
// clear all OpenAL sources
BOOST_FOREACH(ALuint source, d->_free_sources) {
alDeleteSources( 1 , &source );
- testForALError("SGSoundMgr::stop: delete sources");
+ testForError("SGSoundMgr::stop: delete sources");
}
d->_free_sources.clear();
refUint ref = buffers_current->second;
ALuint buffer = ref.id;
alDeleteBuffers(1, &buffer);
- testForALError("SGSoundMgr::stop: delete buffers");
+ testForError("SGSoundMgr::stop: delete buffers");
}
d->_buffers.clear();
alListenerfv( AL_VELOCITY, toVec3f(velocity).data() );
// alDopplerVelocity(340.3); // TODO: altitude dependent
- testForALError("update");
+ testForError("update");
_changed = false;
}
}
alSourcei( source, AL_BUFFER, 0 ); // detach the associated buffer
- testForALError("release_source");
+ testForError("release_source");
#endif
d->_free_sources.push_back( source );
d->_sources_in_use.erase( it );
// create an OpenAL buffer handle
alGenBuffers(1, &buffer);
- if ( !testForALError("generate buffer") ) {
+ if ( !testForError("generate buffer") ) {
// Copy data to the internal OpenAL buffer
ALenum format = AL_NONE;
ALsizei freq = sample->get_frequency();
alBufferData( buffer, format, sample_data, size, freq );
- if ( !testForALError("buffer add data") ) {
+ if ( !testForError("buffer add data") ) {
sample->set_buffer(buffer);
d->_buffers[sample_name] = refUint(buffer);
}
alDeleteBuffers(1, &buffer);
#endif
d->_buffers.erase( buffer_it );
- testForALError("release buffer");
+ testForError("release buffer");
}
}
}
+void SGSoundMgr::sample_suspend( SGSoundSample *sample )
+{
+ if ( sample->is_valid_source() && sample->is_playing() ) {
+ alSourcePause( sample->get_source() );
+ }
+}
+
+void SGSoundMgr::sample_resume( SGSoundSample *sample )
+{
+ if ( sample->is_valid_source() && sample->is_playing() ) {
+ alSourcePlay( sample->get_source() );
+ }
+}
+
+void SGSoundMgr::sample_init( SGSoundSample *sample )
+{
+#ifdef ENABLE_SOUND
+ //
+ // a request to start playing a sound has been filed.
+ //
+ ALuint source = request_source();
+ if (alIsSource(source) == AL_FALSE ) {
+ return;
+ }
+
+ sample->set_source( source );
+#endif
+}
+
+void SGSoundMgr::sample_play( SGSoundSample *sample )
+{
+#ifdef ENABLE_SOUND
+ ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
+ ALint source = sample->get_source();
+
+ if ( !sample->is_queue() )
+ {
+ ALuint buffer = request_buffer(sample);
+ if (buffer == SGSoundMgr::FAILED_BUFFER ||
+ buffer == SGSoundMgr::NO_BUFFER)
+ {
+ release_source(source);
+ return;
+ }
+
+ // start playing the sample
+ buffer = sample->get_buffer();
+ if ( alIsBuffer(buffer) == AL_TRUE )
+ {
+ alSourcei( source, AL_BUFFER, buffer );
+ testForError("assign buffer to source");
+ } else
+ SG_LOG( SG_SOUND, SG_ALERT, "No such buffer!");
+ }
+
+ alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
+ alSourcei( source, AL_LOOPING, looping );
+ alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
+ alSourcePlay( source );
+ testForError("sample play");
+#endif
+}
+
+void SGSoundMgr::sample_stop( SGSoundSample *sample )
+{
+ if ( sample->is_valid_source() ) {
+ int source = sample->get_source();
+
+ bool stopped = is_sample_stopped(sample);
+ if ( sample->is_looping() && !stopped) {
+#ifdef ENABLE_SOUND
+ alSourceStop( source );
+#endif
+ stopped = is_sample_stopped(sample);
+ }
+
+ if ( stopped ) {
+ sample->no_valid_source();
+ release_source( source );
+ }
+ }
+}
+
+void SGSoundMgr::sample_destroy( SGSoundSample *sample )
+{
+ if ( sample->is_valid_source() ) {
+#ifdef ENABLE_SOUND
+ ALint source = sample->get_source();
+ if ( sample->is_playing() ) {
+ alSourceStop( source );
+ testForError("stop");
+ }
+ release_source( source );
+#endif
+ sample->no_valid_source();
+ }
+
+ if ( sample->is_valid_buffer() ) {
+ release_buffer( sample );
+ sample->no_valid_buffer();
+ }
+}
+
+bool SGSoundMgr::is_sample_stopped(SGSoundSample *sample)
+{
+#ifdef ENABLE_SOUND
+ assert(sample->is_valid_source());
+ unsigned int source = sample->get_source();
+ int result;
+ alGetSourcei( source, AL_SOURCE_STATE, &result );
+ return (result == AL_STOPPED);
+#else
+ return true;
+#endif
+}
+
+void SGSoundMgr::update_sample_config( SGSoundSample *sample, SGVec3d& position, SGVec3f& orientation, SGVec3f& velocity )
+{
+ unsigned int source = sample->get_source();
+ alSourcefv( source, AL_POSITION, toVec3f(position).data() );
+ alSourcefv( source, AL_VELOCITY, velocity.data() );
+ alSourcefv( source, AL_DIRECTION, orientation.data() );
+ testForError("position and orientation");
+
+ alSourcef( source, AL_PITCH, sample->get_pitch() );
+ alSourcef( source, AL_GAIN, sample->get_volume() );
+ testForError("pitch and gain");
+
+ if ( sample->has_static_data_changed() ) {
+ alSourcef( source, AL_CONE_INNER_ANGLE, sample->get_innerangle() );
+ alSourcef( source, AL_CONE_OUTER_ANGLE, sample->get_outerangle() );
+ alSourcef( source, AL_CONE_OUTER_GAIN, sample->get_outergain() );
+ testForError("audio cone");
+
+ alSourcef( source, AL_MAX_DISTANCE, sample->get_max_dist() );
+ alSourcef( source, AL_REFERENCE_DISTANCE,
+ sample->get_reference_dist() );
+ testForError("distance rolloff");
+ }
+}
+
+
bool SGSoundMgr::load( const std::string &samplepath,
void **dbuf,
int *fmt,
}
-bool SGSoundMgr::testForALError(std::string s)
+bool SGSoundMgr::testForError(std::string s, std::string name)
{
#ifdef ENABLE_SOUND
ALenum error = alGetError();
if (error != AL_NO_ERROR) {
- SG_LOG( SG_SOUND, SG_ALERT, "AL Error (sound manager): "
+ SG_LOG( SG_SOUND, SG_ALERT, "AL Error (" << name << "): "
<< alGetString(error) << " at " << s);
return true;
}
*/
void release_buffer( SGSoundSample *sample );
+ /**
+ * Initialize sample for playback.
+ *
+ * @param sample Pointer to an audio sample to initialize.
+ */
+ void sample_init( SGSoundSample *sample );
+
+ /**
+ * Stop and destroy a sample
+ *
+ * @param sample Pointer to an audio sample to destroy.
+ */
+ void sample_destroy( SGSoundSample *sample );
+
+ /**
+ * Start playback of a sample
+ *
+ * @param sample Pointer to an audio sample to start playing.
+ */
+ void sample_play( SGSoundSample *sample );
+
+ /**
+ * Stop a sample
+ *
+ * @param sample Pointer to an audio sample to stop.
+ */
+ void sample_stop( SGSoundSample *sample );
+
+ /**
+ * Suspend playback of a sample
+ *
+ * @param sample Pointer to an audio sample to suspend.
+ */
+ void sample_suspend( SGSoundSample *sample );
+
+ /**
+ * Resume playback of a sample
+ *
+ * @param sample Pointer to an audio sample to resume.
+ */
+ void sample_resume( SGSoundSample *sample );
+
+ /**
+ * Check if a sample is stopped, or still playing
+ *
+ * @param sample Pointer to an audio sample to test.
+ * @return true if the sample is stopped.
+ */
+ bool is_sample_stopped( SGSoundSample *sample );
+
+ /**
+ * Update all status and 3d parameters of a sample.
+ *
+ * @param sample Pointer to an audio sample to update.
+ */
+ void update_sample_config( SGSoundSample *sample, SGVec3d& position, SGVec3f& orientation, SGVec3f& velocity );
+
/**
* Test if the position of the sound manager has changed.
* The value will be set to false upon the next call to update_late()
const std::string& get_vendor() { return _vendor; }
const std::string& get_renderer() { return _renderer; }
+ bool testForError(std::string s, std::string name = "sound manager");
+
static const char* subsystemName() { return "sound"; };
private:
class SoundManagerPrivate;
std::string _vendor;
std::string _device_name;
- bool testForALError(std::string s);
bool testForALCError(std::string s);
bool testForError(void *p, std::string s);
# include <AL/alext.h>
#endif
+#include <simgear/structure/SGSharedPtr.hxx>
+
+class SGSampleGroup;
+
struct refUint {
unsigned int refctr;
ALuint id;
#include <simgear/misc/sg_path.hxx>
#include "sample_group.hxx"
-#include "sample_openal.hxx"
+#include "sample.hxx"
using std::string;