Audaspace:
authorJoerg Mueller <nexyon@gmail.com>
Mon, 2 Aug 2010 18:22:34 +0000 (18:22 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Mon, 2 Aug 2010 18:22:34 +0000 (18:22 +0000)
* Added a stopCallback function that is called when the end of a sound is reached.
* Fixed the scrubbing not working.
* Minor SoundActuator cleanup.

16 files changed:
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_IDevice.h
intern/audaspace/intern/AUD_NULLDevice.cpp
intern/audaspace/intern/AUD_NULLDevice.h
intern/audaspace/intern/AUD_SilenceFactory.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SilenceFactory.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SilenceReader.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SilenceReader.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
source/blender/blenkernel/intern/sound.c
source/blender/makesdna/DNA_scene_types.h
source/gameengine/Ketsji/KX_SoundActuator.h

index 88e48ff20ba4b2371829c272edfd54469bc0da02..f69a2e5d80564e83c8c1da3b053f82889d47d61c 100644 (file)
@@ -68,6 +68,12 @@ struct AUD_OpenALHandle : AUD_Handle
 
        /// The loop count of the source.
        int loopcount;
+
+       /// The stop callback.
+       stopCallback stop;
+
+       /// Stop callback data.
+       void* stop_data;
 };
 
 struct AUD_OpenALBufferedFactory
@@ -131,13 +137,9 @@ void AUD_OpenALDevice::updateStreams()
 
                {
                        // for all sounds
-                       AUD_HandleIterator it = m_playingSounds->begin();
-                       while(it != m_playingSounds->end())
+                       for(AUD_HandleIterator it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
                        {
                                sound = *it;
-                               // increment the iterator to make sure it's valid,
-                               // in case the sound gets deleted after stopping
-                               ++it;
 
                                // is it a streamed sound?
                                if(!sound->isBuffered)
@@ -227,12 +229,21 @@ void AUD_OpenALDevice::updateStreams()
                                        // if it really stopped
                                        if(sound->data_end)
                                        {
+                                               if(sound->stop)
+                                                       sound->stop(sound->stop_data);
+
+                                               // increment the iterator to the next value,
+                                               // because the sound gets deleted in the list here.
+                                               ++it;
                                                // pause or
                                                if(sound->keep)
                                                        pause(sound);
                                                // stop
                                                else
                                                        stop(sound);
+                                               // decrement again, so that we get the next sound in the
+                                               // next loop run
+                                               --it;
                                        }
                                        // continue playing
                                        else
@@ -1012,6 +1023,20 @@ bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
        return result;
 }
 
+bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
+{
+       lock();
+       bool result = isValid(handle);
+       if(result)
+       {
+               AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
+               h->stop = callback;
+               h->stop_data = data;
+       }
+       unlock();
+       return result;
+}
+
 /* AUD_XXX Temorary disabled
 
 bool AUD_OpenALDevice::bufferFactory(void *value)
index 37a5b886882445b7acb588580f43fb84b1e2a1b4..985954fc20b39d748a4e63783a79a42a7e4e87b4 100644 (file)
@@ -160,6 +160,7 @@ public:
        virtual bool setPitch(AUD_Handle* handle, float pitch);
        virtual int getLoopCount(AUD_Handle* handle);
        virtual bool setLoopCount(AUD_Handle* handle, int count);
+       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
 
        virtual AUD_Vector3 getListenerLocation() const;
        virtual void setListenerLocation(const AUD_Vector3& location);
index 5e0364c618c5eb1beddb39bf1dfedb470c26dfff..b9926b85a48d6a2c443d9532dda0068ae61c64f5 100644 (file)
@@ -60,6 +60,7 @@ bool g_pyinitialized = false;
 #include "AUD_ReadDevice.h"
 #include "AUD_IReader.h"
 #include "AUD_SequencerFactory.h"
+#include "AUD_SilenceFactory.h"
 
 #ifdef WITH_SDL
 #include "AUD_SDLDevice.h"
@@ -845,6 +846,32 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
        return result;
 }
 
+static void pauseSound(AUD_Channel* handle)
+{
+       assert(AUD_device);
+
+       AUD_device->pause(handle);
+}
+
+AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
+{
+       assert(AUD_device);
+
+       AUD_SilenceFactory silence;
+       AUD_LimiterFactory limiter(&silence, 0, seconds);
+
+       try
+       {
+               AUD_Channel* channel = AUD_device->play(&limiter);
+               AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
+               return channel;
+       }
+       catch(AUD_Exception&)
+       {
+               return NULL;
+       }
+}
+
 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
 {
 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
index f73e658d5b1d17158d78081ea0e47d87d5715478..de2d8465d18f875a17c2a0bc89a3819141c2f86b 100644 (file)
@@ -463,6 +463,14 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
                                                                  float sthreshold, int samplerate,
                                                                  int* length);
 
+/**
+ * Pauses a playing sound after a specific amount of time.
+ * \param handle The handle to the sound.
+ * \param time The time in seconds.
+ * \return The silence handle.
+ */
+extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds);
+
 extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume);
 
 extern void AUD_destroySequencer(AUD_Sound* sequencer);
index bb2d65cde746d9577ced04d3b295b62cdfb95cc5..d0925f6f6471921bf930bd4e291cf31d98a7d902 100644 (file)
@@ -34,6 +34,8 @@ struct AUD_Handle
 {
 };
 
+typedef void (*stopCallback)(void*);
+
 /**
  * This class represents an output device for sound sources.
  * Output devices may be several backends such as plattform independand like
@@ -225,6 +227,18 @@ public:
         *        - false if the handle is invalid.
         */
        virtual bool setLoopCount(AUD_Handle* handle, int count)=0;
+
+       /**
+        * Sets the callback function that's called when the end of a playing sound
+        * is reached.
+        * \param handle The sound handle.
+        * \param callback The callback function.
+        * \param data The data that should be passed to the callback function.
+        * \return
+        *        - true if the handle is valid.
+        *        - false if the handle is invalid.
+        */
+       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0;
 };
 
 #endif //AUD_IDevice
index ec9e02ef28f6f278d9a45af7b01f25ad8f264229..272e1e4b5b26fe9bad9bfd28eebfa9b2e395fefa 100644 (file)
@@ -133,3 +133,8 @@ bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count)
 {
        return false;
 }
+
+bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
+{
+       return false;
+}
index c62618548033892048748b4e055ef8bc594bf6a9..a1ffdba201a81875c84fce56d633d19a52422416 100644 (file)
@@ -59,6 +59,7 @@ public:
        virtual bool setPitch(AUD_Handle* handle, float pitch);
        virtual int getLoopCount(AUD_Handle* handle);
        virtual bool setLoopCount(AUD_Handle* handle, int count);
+       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0);
 };
 
 #endif //AUD_NULLDEVICE
diff --git a/intern/audaspace/intern/AUD_SilenceFactory.cpp b/intern/audaspace/intern/AUD_SilenceFactory.cpp
new file mode 100644 (file)
index 0000000..4e59d74
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SilenceFactory.h"
+#include "AUD_SilenceReader.h"
+#include "AUD_Space.h"
+
+AUD_SilenceFactory::AUD_SilenceFactory()
+{
+}
+
+AUD_IReader* AUD_SilenceFactory::createReader() const
+{
+       return new AUD_SilenceReader();
+}
diff --git a/intern/audaspace/intern/AUD_SilenceFactory.h b/intern/audaspace/intern/AUD_SilenceFactory.h
new file mode 100644 (file)
index 0000000..bc8a5b9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SILENCEFACTORY
+#define AUD_SILENCEFACTORY
+
+#include "AUD_IFactory.h"
+
+/**
+ * This factory creates a reader that plays a sine tone.
+ */
+class AUD_SilenceFactory : public AUD_IFactory
+{
+private:
+       // hide copy constructor and operator=
+       AUD_SilenceFactory(const AUD_SilenceFactory&);
+       AUD_SilenceFactory& operator=(const AUD_SilenceFactory&);
+
+public:
+       /**
+        * Creates a new silence factory.
+        */
+       AUD_SilenceFactory();
+
+       virtual AUD_IReader* createReader() const;
+};
+
+#endif //AUD_SILENCEFACTORY
diff --git a/intern/audaspace/intern/AUD_SilenceReader.cpp b/intern/audaspace/intern/AUD_SilenceReader.cpp
new file mode 100644 (file)
index 0000000..5243286
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SilenceReader.h"
+
+#include <cstring>
+
+AUD_SilenceReader::AUD_SilenceReader() :
+       m_position(0)
+{
+}
+
+bool AUD_SilenceReader::isSeekable() const
+{
+       return true;
+}
+
+void AUD_SilenceReader::seek(int position)
+{
+       m_position = position;
+}
+
+int AUD_SilenceReader::getLength() const
+{
+       return -1;
+}
+
+int AUD_SilenceReader::getPosition() const
+{
+       return m_position;
+}
+
+AUD_Specs AUD_SilenceReader::getSpecs() const
+{
+       AUD_Specs specs;
+       specs.rate = AUD_RATE_44100;
+       specs.channels = AUD_CHANNELS_MONO;
+       return specs;
+}
+
+void AUD_SilenceReader::read(int & length, sample_t* & buffer)
+{
+       // resize if necessary
+       if(m_buffer.getSize() < length * sizeof(sample_t))
+       {
+               m_buffer.resize(length * sizeof(sample_t));
+               memset(m_buffer.getBuffer(), 0, m_buffer.getSize());
+       }
+
+       buffer = m_buffer.getBuffer();
+       m_position += length;
+}
diff --git a/intern/audaspace/intern/AUD_SilenceReader.h b/intern/audaspace/intern/AUD_SilenceReader.h
new file mode 100644 (file)
index 0000000..a8b959b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SILENCEREADER
+#define AUD_SILENCEREADER
+
+#include "AUD_IReader.h"
+#include "AUD_Buffer.h"
+
+/**
+ * This class is used for sine tone playback.
+ * The output format is in the 16 bit format and stereo, the sample rate can be
+ * specified.
+ * As the two channels both play the same the output could also be mono, but
+ * in most cases this will result in having to resample for output, so stereo
+ * sound is created directly.
+ */
+class AUD_SilenceReader : public AUD_IReader
+{
+private:
+       /**
+        * The current position in samples.
+        */
+       int m_position;
+
+       /**
+        * The playback buffer.
+        */
+       AUD_Buffer m_buffer;
+
+       // hide copy constructor and operator=
+       AUD_SilenceReader(const AUD_SilenceReader&);
+       AUD_SilenceReader& operator=(const AUD_SilenceReader&);
+
+public:
+       /**
+        * Creates a new reader.
+        */
+       AUD_SilenceReader();
+
+       virtual bool isSeekable() const;
+       virtual void seek(int position);
+       virtual int getLength() const;
+       virtual int getPosition() const;
+       virtual AUD_Specs getSpecs() const;
+       virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_SILENCEREADER
index 1f063e636f15157969fb23ab6b9636c0b78aaac7..757f31fc15d3c68d5784ec49a00cbde09afa0a69 100644 (file)
@@ -45,6 +45,12 @@ struct AUD_SoftwareHandle : AUD_Handle
 
        /// The loop count of the source.
        int loopcount;
+
+       /// The stop callback.
+       stopCallback stop;
+
+       /// Stop callback data.
+       void* stop_data;
 };
 
 typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
@@ -151,6 +157,9 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                        // in case the end of the sound is reached
                        if(pos < length)
                        {
+                               if(sound->stop)
+                                       sound->stop(sound->stop_data);
+
                                if(sound->keep)
                                        pause(sound);
                                else
@@ -488,3 +497,17 @@ bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count)
        unlock();
        return result;
 }
+
+bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
+{
+       lock();
+       bool result = isValid(handle);
+       if(result)
+       {
+               AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
+               h->stop = callback;
+               h->stop_data = data;
+       }
+       unlock();
+       return result;
+}
index c14b5356c6bd91fabf5836dea44a4a4a1c281bbf..93b0f165c7aed5c06729c72b6e9f10656b45a5e3 100644 (file)
@@ -132,6 +132,7 @@ public:
        virtual bool setPitch(AUD_Handle* handle, float pitch);
        virtual int getLoopCount(AUD_Handle* handle);
        virtual bool setLoopCount(AUD_Handle* handle, int count);
+       virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
 };
 
 #endif //AUD_SOFTWAREDEVICE
index 17ff6615ee735b8a85074aa8ea031b01ec469d97..264bae3108980df4e178c90150257ede9d8d1e2a 100644 (file)
@@ -438,6 +438,10 @@ void sound_seek_scene(struct bContext *C)
                else
                        AUD_seek(scene->sound_scene_handle, CFRA / FPS);
                AUD_resume(scene->sound_scene_handle);
+               if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
+                       AUD_seek(scene->sound_scrub_handle, 0);
+               else
+                       scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS);
        }
        else
        {
index 984aa5a67051016a46943f69ea2332989a5171fd..d0d9d21e0bdc3b9167b542d8a1329033a0af0d60 100644 (file)
@@ -797,6 +797,7 @@ typedef struct Scene {
        
        void *sound_scene;
        void *sound_scene_handle;
+       void *sound_scrub_handle;
        
        void *fps_info;                                 /* (runtime) info/cache used for presenting playback framerate info to the user */
        
index ce7612d4bcb2bbfd92244f90bde644f813352418..c175a184a1529039005256c8a26aa9ceb6b46232 100644 (file)
@@ -107,14 +107,12 @@ public:
        static int pyattr_set_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-       static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
 
        static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
-       static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
 
 #endif // DISABLE_PYTHON