]> git.mxchange.org Git - simgear.git/commitdiff
Initial commit for a sample queue extension.
authorErik Hofman <erik@ehofman.com>
Mon, 2 Aug 2010 08:10:58 +0000 (10:10 +0200)
committerErik Hofman <erik@ehofman.com>
Mon, 2 Aug 2010 08:10:58 +0000 (10:10 +0200)
simgear/sound/Makefile.am
simgear/sound/openal_test4.cxx [new file with mode: 0644]
simgear/sound/sample_group.cxx
simgear/sound/sample_group.hxx
simgear/sound/sample_openal.hxx
simgear/sound/sample_queue.cxx [new file with mode: 0644]
simgear/sound/sample_queue.hxx [new file with mode: 0644]
simgear/sound/soundmgr_openal.cxx

index e76fed450f893f9967c15538fd8f0135a21cd3cf..7719f107c4f5c2694cff2c92ff2b87ea2a7147f8 100644 (file)
@@ -7,22 +7,25 @@ lib_LIBRARIES = libsgsound.a
 noinst_HEADERS =
 
 include_HEADERS = \
+       soundmgr_openal.hxx \
        sample_group.hxx \
        sample_openal.hxx \
-       soundmgr_openal.hxx \
-       xmlsound.hxx 
+       sample_queue.hxx \
+       xmlsound.hxx
 
 libsgsound_a_SOURCES = \
+       soundmgr_openal.cxx \
        sample_group.cxx \
        sample_openal.cxx  \
-       soundmgr_openal.cxx \
-       xmlsound.cxx 
+       sample_queue.cxx \
+       xmlsound.cxx
 
-noinst_PROGRAMS = openal_test1 openal_test2 openal_test3
+check_PROGRAMS = openal_test1 openal_test2 openal_test3 openal_test4
 
 openal_test1_SOURCES = openal_test1.cxx
 openal_test2_SOURCES = openal_test2.cxx
 openal_test3_SOURCES = openal_test3.cxx
+openal_test4_SOURCES = openal_test4.cxx
 
 openal_test1_LDADD = \
        $(top_builddir)/simgear/debug/libsgdebug.a \
@@ -46,4 +49,13 @@ openal_test3_LDADD = \
        $(top_builddir)/simgear/math/libsgmath.a \
        $(openal_LIBS) -lstdc++
 
+openal_test4_LDADD = \
+       libsgsound.a \
+       $(top_builddir)/simgear/structure/libsgstructure.a \
+        $(top_builddir)/simgear/timing/libsgtiming.a \
+       $(top_builddir)/simgear/debug/libsgdebug.a \
+       $(top_builddir)/simgear/misc/libsgmisc.a \
+       $(top_builddir)/simgear/math/libsgmath.a \
+       $(openal_LIBS) -lstdc++
+
 INCLUDES = -I$(top_srcdir) -DSRC_DIR=\"$(top_srcdir)/simgear/sound\"
diff --git a/simgear/sound/openal_test4.cxx b/simgear/sound/openal_test4.cxx
new file mode 100644 (file)
index 0000000..320b6e6
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#ifdef _WIN32
+#include <windows.h>
+#define sleep(x) Sleep(x*1000)
+#else
+#include <unistd.h>
+#endif
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#include "soundmgr_openal.hxx"
+
+
+int main( int argc, char *argv[] ) {
+    SGSampleQueue *squeue;
+    SGSampleGroup *sgr;
+    SGSoundMgr *smgr;
+    SGGeod pos;
+
+    smgr = new SGSoundMgr;
+
+    smgr->bind();
+    smgr->init("OSS Default");
+    sgr = smgr->find("default", true);
+    smgr->set_volume(0.9);
+    smgr->activate();
+
+
+    void *data;
+    size_t len;
+    int freq, fmt;
+    string file = SRC_DIR"/jet.wav";
+    smgr->load(file, &data, &fmt, &len, &freq);
+
+    squeue = new SGSampleQueue( freq, fmt );
+    sgr->add(squeue, "queue");
+
+    squeue->add(  data, len );
+    squeue->add(  data, len );
+    squeue->play();
+    printf("playing queue\n");
+
+    smgr->update(1.0);
+    sleep(10);
+    smgr->update(10.0);
+
+    printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n");
+    pos = SGGeod::fromDeg(9.99,-9.99);
+    squeue->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(10,-10)) );
+    smgr->set_position( SGVec3d::fromGeod(pos), pos );
+
+    squeue->add(  data, len );
+    squeue->add(  data, len );
+    squeue->play( true ); // play looped
+    printf("playing queue\n");
+
+    smgr->update(1.0);
+    sleep(10);
+    smgr->update(10.0);
+
+    squeue->stop();
+    smgr->update(1.0);
+    sleep(1);
+
+    sgr->remove("queue");
+    smgr->unbind();
+    sleep(2);
+
+    delete smgr;
+}
index a4fbfc49113f166046615109dfacca9934656af3..99a5a0eb3689fa40b398e97d0fe3ad98f08d8b69 100644 (file)
@@ -104,9 +104,11 @@ void SGSampleGroup::update( double dt ) {
 
         if ( result == AL_STOPPED ) {
             sample->stop();
-            ALuint buffer = sample->get_buffer();
-            alDeleteBuffers( 1, &buffer );
-            testForALError("buffer remove");
+            if ( !sample->is_queue() ) {
+                ALuint buffer = sample->get_buffer();
+                alDeleteBuffers( 1, &buffer );
+                testForALError("buffer remove");
+            }
             _removed_samples.erase( _removed_samples.begin()+i );
             size--;
             continue;
@@ -129,33 +131,46 @@ void SGSampleGroup::update( double dt ) {
             //
             // a request to start playing a sound has been filed.
             //
-            if ( _smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER )
-                continue;
-
-            // start playing the sample
-            ALuint buffer = sample->get_buffer();
             ALuint source = _smgr->request_source();
-            if (alIsSource(source) == AL_TRUE && alIsBuffer(buffer) == AL_TRUE)
+            if (alIsSource(source) == AL_TRUE )
             {
-                sample->set_source( source );
-                
-                alSourcei( source, AL_BUFFER, buffer );
-                testForALError("assign buffer to source");
-
-                sample->set_source( source );
-                update_sample_config( sample );
-
-                ALboolean looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
-                alSourcei( source, AL_LOOPING, looping );
-                alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
-                alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
-                alSourcePlay( source );
-                testForALError("sample play");
-            } else {
-                if (alIsBuffer(buffer) == AL_FALSE) 
-                   SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n");
-                // sample->no_valid_source();
-                // sadly, no free source available at this time
+                if ( sample->is_queue() )
+                {
+                    sample->set_source( source );
+                    update_sample_config( sample );
+
+                    alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
+                    alSourcei( source, AL_LOOPING, AL_FALSE);
+                    alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
+                    alSourcePlay( source );
+                    testForALError("sample play");
+                }
+                else
+                {
+                    if (_smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER)
+                        continue;
+
+                    // start playing the sample
+                    ALuint buffer = sample->get_buffer();
+                    if ( alIsBuffer(buffer) == AL_TRUE )
+                    {
+                        ALboolean looping;
+
+                        alSourcei( source, AL_BUFFER, buffer );
+                        testForALError("assign buffer to source");
+
+                        sample->set_source( source );
+                        update_sample_config( sample );
+
+                        looping = sample->is_looping() ? AL_TRUE : AL_FALSE;
+                        alSourcei( source, AL_LOOPING, looping );
+                        alSourcef( source, AL_ROLLOFF_FACTOR, 0.3 );
+                        alSourcei( source, AL_SOURCE_RELATIVE, AL_FALSE );
+                        alSourcePlay( source );
+                        testForALError("sample play");
+                    } else
+                        SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n");
+                }
             }
 
         } else if ( sample->is_valid_source() ) {
@@ -215,6 +230,7 @@ bool SGSampleGroup::remove( const string &refname ) {
 
     if ( sample_it->second->is_valid_buffer() )
         _removed_samples.push_back( sample_it->second );
+
     _samples.erase( sample_it );
 
     return true;
@@ -265,7 +281,7 @@ SGSampleGroup::stop ()
             sample->no_valid_source();
         }
 
-        if (sample->is_valid_buffer() ) {
+        if ( sample->is_valid_buffer() ) {
             _smgr->release_buffer( sample );
             sample->no_valid_buffer();
         }
index d2d47394d4530a32a33f68db431e4212f5e6638b..59d42b323e8cacbea970ef1e0cb84790be4781d6 100644 (file)
@@ -52,6 +52,7 @@
 #include <simgear/structure/exception.hxx>
 
 #include "sample_openal.hxx"
+#include "sample_queue.hxx"
 
 using std::map;
 using std::string;
index d2cb1824763a7a76b3769397bc80a0956c9464e0..362915b0929d3808391b0f6df9148665d74f03b1 100644 (file)
@@ -42,7 +42,6 @@
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/math/SGMath.hxx>
 
-// #include <plib/sg.h>
 
 /**
  * manages everything we need to know for an individual audio sample
@@ -115,7 +114,7 @@ public:
      * at the next call op SoundGroup::update()
      * @param _loop Define whether this sound should be played in a loop.
      */
-    void play( bool loop ) {
+    void play( bool loop = false ) {
         _playing = true; _loop = loop; _changed = true;
     }
 
@@ -128,7 +127,7 @@ public:
     /**
      * Schedule this audio sample to stop playing.
      */
-    void stop() {
+    virtual void stop() {
         _playing = false; _changed = true;
     }
 
@@ -158,7 +157,7 @@ public:
     inline void set_data( const unsigned char **data ) {
         _data = (unsigned char*)*data; *data = NULL;
     }
-    inline void set_data( void **data ) {
+    inline void set_data( const void **data ) {
         _data = (unsigned char*)*data; *data = NULL;
     }
 
@@ -179,7 +178,7 @@ public:
      * Set the source id of this source
      * @param sid OpenAL source-id
      */
-    void set_source(unsigned int sid) {
+    virtual inline void set_source(unsigned int sid) {
         _source = sid; _valid_source = true; _changed = true;
     }
 
@@ -187,24 +186,24 @@ public:
      * Get the OpenAL source id of this source
      * @return OpenAL source-id
      */
-    inline unsigned int get_source() { return _source; }
+    virtual inline unsigned int get_source() { return _source; }
 
     /**
      * Test if the source-id of this audio sample may be passed to OpenAL.
      * @return true if the source-id is valid
      */
-    inline bool is_valid_source() const { return _valid_source; }
+    virtual inline bool is_valid_source() const { return _valid_source; }
 
     /**
      * Set the source-id of this audio sample to invalid.
      */
-    inline void no_valid_source() { _valid_source = false; }
+    virtual inline void no_valid_source() { _valid_source = false; }
 
     /**
      * Set the OpenAL buffer-id of this source
      * @param bid OpenAL buffer-id
      */
-    void set_buffer(unsigned int bid) {
+    inline void set_buffer(unsigned int bid) {
         _buffer = bid; _valid_buffer = true; _changed = true;
     } 
 
@@ -443,6 +442,8 @@ public:
      */
     inline std::string get_sample_name() const { return _refname; }
 
+    inline virtual bool is_queue() const { return false; }
+
     void update_pos_and_orientation();
 
 private:
diff --git a/simgear/sound/sample_queue.cxx b/simgear/sound/sample_queue.cxx
new file mode 100644 (file)
index 0000000..a7eeac1
--- /dev/null
@@ -0,0 +1,141 @@
+// queue.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()
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/math/SGMath.hxx>
+
+#include "soundmgr_openal.hxx"
+#include "sample_queue.hxx"
+
+
+//
+// SGSampleQueue
+//
+
+// empty constructor
+SGSampleQueue::SGSampleQueue( int freq, int format ) :
+    _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()),
+    _refname(random_string()),
+    _format(format),
+    _freq(freq),
+    _valid_source(false),
+    _source(SGSoundMgr::NO_SOURCE),
+    _inner_angle(360.0),
+    _outer_angle(360.0),
+    _outer_gain(0.0),
+    _pitch(1.0),
+    _volume(1.0),
+    _master_volume(1.0),
+    _reference_dist(500.0),
+    _max_dist(3000.0),
+    _playing(false),
+    _changed(true)
+{
+    _buffers.clear();
+}
+
+SGSampleQueue::~SGSampleQueue() {
+    stop();
+}
+
+void SGSampleQueue::stop()
+{
+    ALint num;
+    alGetSourcei(_source, AL_BUFFERS_PROCESSED, &num);
+    for (int i=0; i<num; i++) {
+        ALuint buffer;
+        alSourceUnqueueBuffers(_source, 1, &buffer);
+        alDeleteBuffers(1, &buffer);
+    }
+    _buffers.clear();
+
+    _playing = false;
+    _changed = true;
+}
+
+void SGSampleQueue::add( const void* smp_data, size_t len )
+{
+    const ALvoid *data = (const ALvoid *)smp_data;
+    ALuint buffer;
+    ALint num;
+
+    if ( _valid_source )
+    {
+       alGetSourcei(_source, AL_BUFFERS_PROCESSED, &num);
+       if (num > 1) {
+           alSourceUnqueueBuffers(_source, 1, &buffer);
+       } else {
+           alGenBuffers(1, &buffer);
+       }
+       alBufferData(buffer, _format, data, len, _freq);
+    }
+    else
+    {
+        alGenBuffers(1, &buffer);
+        alBufferData(buffer, _format, data, len, _freq);
+        _buffers.push_back(buffer);
+    }
+}
+
+void SGSampleQueue::set_source( unsigned int sid )
+{
+    _source = sid;
+    _valid_source = true;
+    _changed = true;
+
+    ALuint num = _buffers.size();
+    for (unsigned int i=0; i < num; i++)
+    {
+        ALuint buffer = _buffers[i];
+        alSourceQueueBuffers(_source, 1, &buffer);
+    }
+    _buffers.clear();
+
+}
+
+string SGSampleQueue::random_string() {
+      static const char *r = "0123456789abcdefghijklmnopqrstuvwxyz"
+                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+      string rstr = "Queued sample: ";
+      for (int i=0; i<10; i++) {
+          rstr.push_back( r[rand() % strlen(r)] );
+      }
+
+      return rstr;
+}
diff --git a/simgear/sound/sample_queue.hxx b/simgear/sound/sample_queue.hxx
new file mode 100644 (file)
index 0000000..32d49d3
--- /dev/null
@@ -0,0 +1,157 @@
+// queue.hxx -- Sample Queue encapsulation class
+// 
+// based on sample.hxx
+// 
+// Copyright (C) 2010 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 sample queue encapsulation
+ */
+
+#ifndef _SG_QUEUE_HXX
+#define _SG_QUEUE_HXX 1
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <string>
+#include <vector>
+
+#include <simgear/compiler.h>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/math/SGMath.hxx>
+
+#include "sample_openal.hxx"
+
+/**
+ * manages everything we need to know for an individual audio sample
+ */
+
+class SGSampleQueue : public SGSoundSample {
+public:
+
+
+     /**
+      * Empty constructor, can be used to read data to the systems
+      * memory and not to the driver.
+      * @param freq sample frequentie of the samples
+      * @param format OpenAL format id of the data
+      */
+    SGSampleQueue(int freq, int format = AL_FORMAT_MONO8);
+
+    /**
+     * Destructor
+     */
+    ~SGSampleQueue ();
+
+    /**
+     * Schedule this audio sample to stop playing.
+     */
+    virtual void stop();
+
+    /**
+     * Queue new data for this audio sample
+     * @param data Pointer to a memory block containg this audio sample data.
+     * @param len length of the sample buffer in bytes
+     */
+    void add( const void* smp_data, size_t len );
+
+    /**
+     * Set the source id of this source
+     * @param sid OpenAL source-id
+     */
+    virtual void set_source(unsigned int sid);
+
+    /**
+     * Get the OpenAL source id of this source
+     * @return OpenAL source-id
+     */
+    virtual inline unsigned int get_source() { return _source; }
+
+    /**
+     * Test if the source-id of this audio sample may be passed to OpenAL.
+     * @return true if the source-id is valid
+     */
+    virtual inline bool is_valid_source() const { return _valid_source; }
+
+    /**
+     * Set the source-id of this audio sample to invalid.
+     */
+    virtual inline void no_valid_source() { _valid_source = false; }
+
+    /**
+     * Test if the buffer-id of this audio sample may be passed to OpenAL.
+     * @return false for sample queue
+     */
+    inline bool is_valid_buffer() const { return false; }
+
+    inline virtual bool is_queue() const { return true; }
+
+private:
+
+    // Position of the source sound.
+    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 for OpenAL
+    SGVec3d _base_pos;         // base position
+
+    SGQuatd _rotation;
+
+    std::string _refname;      // sample name
+    std::vector<unsigned int> _buffers;
+    unsigned int _buffer;
+
+    // configuration values
+    int _format;
+    int _freq;
+
+    // Sources are points emitting sound.
+    bool _valid_source;
+    unsigned int _source;
+
+    // The orientation of this sound (direction and cut-off angles)
+    float _inner_angle;
+    float _outer_angle;
+    float _outer_gain;
+
+    float _pitch;
+    float _volume;
+    float _master_volume;
+    float _reference_dist;
+    float _max_dist;
+
+    bool _playing;
+    bool _changed;
+
+    string random_string();
+};
+
+
+#endif // _SG_QUEUE_HXX
+
+
index 750c4b0f94fbb17a50899fe364e6e1b26ce449c4..e91cf767785c64cf1493a1269068220bcb6d0986 100644 (file)
@@ -508,20 +508,23 @@ unsigned int SGSoundMgr::request_buffer(SGSoundSample *sample)
 
 void SGSoundMgr::release_buffer(SGSoundSample *sample)
 {
-    string sample_name = sample->get_sample_name();
-    buffer_map_iterator buffer_it = _buffers.find( sample_name );
-    if ( buffer_it == _buffers.end() ) {
-        // buffer was not found
-        return;
-    }
+    if ( !sample->is_queue() )
+    {
+        string sample_name = sample->get_sample_name();
+        buffer_map_iterator buffer_it = _buffers.find( sample_name );
+        if ( buffer_it == _buffers.end() ) {
+            // buffer was not found
+            return;
+        }
 
-    sample->no_valid_buffer();
-    buffer_it->second.refctr--;
-    if (buffer_it->second.refctr == 0) {
-        ALuint buffer = buffer_it->second.id;
-        alDeleteBuffers(1, &buffer);
-        _buffers.erase( buffer_it );
-        testForALError("release buffer");
+        sample->no_valid_buffer();
+        buffer_it->second.refctr--;
+        if (buffer_it->second.refctr == 0) {
+            ALuint buffer = buffer_it->second.id;
+            alDeleteBuffers(1, &buffer);
+            _buffers.erase( buffer_it );
+            testForALError("release buffer");
+        }
     }
 }