3D Audio GSoC:
authorJoerg Mueller <nexyon@gmail.com>
Tue, 26 Jul 2011 13:56:31 +0000 (13:56 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Tue, 26 Jul 2011 13:56:31 +0000 (13:56 +0000)
Main: Complete rewrite of the sequencer related audio code to support 3D Audio objects later and especially adressing the animation system problems (see mailing list if interested).
Note: Animation is not working yet, so with this commit volume animation doesn't work anymore, that's the next step.

Minor things:
* Changed AUD_Reference behaviour a little to be more usage safe.
* Fixed bug in AUD_I3DHandle: Missing virtual destructor
* Fixed enmus in AUD_Space.h
* Fixed a warning in rna_scene.c
* Removed an unneeded call in rna_sound.c

31 files changed:
intern/audaspace/CMakeLists.txt
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/intern/AUD_AnimateableProperty.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_AnimateableProperty.h [new file with mode: 0644]
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_I3DHandle.h
intern/audaspace/intern/AUD_IHandle.h
intern/audaspace/intern/AUD_NULLDevice.cpp
intern/audaspace/intern/AUD_ReadDevice.cpp
intern/audaspace/intern/AUD_ReadDevice.h
intern/audaspace/intern/AUD_Reference.h
intern/audaspace/intern/AUD_SequencerEntry.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerEntry.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerFactory.cpp
intern/audaspace/intern/AUD_SequencerFactory.h
intern/audaspace/intern/AUD_SequencerHandle.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerHandle.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerReader.cpp
intern/audaspace/intern/AUD_SequencerReader.h
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
intern/audaspace/intern/AUD_Space.h
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenloader/intern/readfile.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_sound.c

index 603e98a57827b89747d7192ac8409464077158eb..6f3d184dd0bb1bbbb285d253dd7ea3a083a2d9be 100644 (file)
@@ -68,6 +68,8 @@ set(SRC
        FX/AUD_SuperposeReader.cpp
        FX/AUD_VolumeFactory.cpp
        intern/AUD_3DMath.h
+       intern/AUD_AnimateableProperty.cpp
+       intern/AUD_AnimateableProperty.h
        intern/AUD_Buffer.cpp
        intern/AUD_Buffer.h
        intern/AUD_BufferReader.cpp
@@ -109,8 +111,12 @@ set(SRC
        intern/AUD_ReferenceHandler.cpp
        intern/AUD_ResampleReader.cpp
        intern/AUD_ResampleReader.h
+       intern/AUD_SequencerEntry.cpp
+       intern/AUD_SequencerEntry.h
        intern/AUD_SequencerFactory.cpp
        intern/AUD_SequencerFactory.h
+       intern/AUD_SequencerHandle.cpp
+       intern/AUD_SequencerHandle.h
        intern/AUD_SequencerReader.cpp
        intern/AUD_SequencerReader.h
        intern/AUD_SilenceFactory.cpp
index 684ad50792b37c69297c8000a2bdae5d00e43139..40fc8a55f035914113aa32e7731f30d61b7a4610 100644 (file)
@@ -1168,7 +1168,7 @@ AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> rea
 
        // check format
        if(specs.channels == AUD_CHANNELS_INVALID)
-               return NULL;
+               return AUD_Reference<AUD_IHandle>();
 
        if(m_specs.format != AUD_FORMAT_FLOAT32)
                reader = new AUD_ConverterReader(reader, m_specs);
@@ -1176,7 +1176,7 @@ AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> rea
        ALenum format;
 
        if(!getFormat(format, specs))
-               return NULL;
+               return AUD_Reference<AUD_IHandle>();
 
        lock();
        alcSuspendContext(m_context);
diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.cpp b/intern/audaspace/intern/AUD_AnimateableProperty.cpp
new file mode 100644 (file)
index 0000000..bc51781
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_AnimateableProperty.cpp
+ *  \ingroup audaspaceintern
+ */
+
+
+#include "AUD_AnimateableProperty.h"
+
+#include <cstring>
+
+AUD_AnimateableProperty::AUD_AnimateableProperty(int count) :
+       AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false), m_changed(false)
+{
+       memset(getBuffer(), 0, count * sizeof(float));
+
+       pthread_mutexattr_t attr;
+       pthread_mutexattr_init(&attr);
+       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+       pthread_mutex_init(&m_mutex, &attr);
+
+       pthread_mutexattr_destroy(&attr);
+}
+
+AUD_AnimateableProperty::~AUD_AnimateableProperty()
+{
+       pthread_mutex_destroy(&m_mutex);
+}
+
+void AUD_AnimateableProperty::lock()
+{
+       pthread_mutex_lock(&m_mutex);
+}
+
+void AUD_AnimateableProperty::unlock()
+{
+       pthread_mutex_unlock(&m_mutex);
+}
+
+void AUD_AnimateableProperty::write(const float* data)
+{
+       lock();
+
+       m_isAnimated = false;
+       m_changed = true;
+       memcpy(getBuffer(), data, m_count * sizeof(float));
+
+       unlock();
+}
+
+void AUD_AnimateableProperty::write(const float* data, int position, int count)
+{
+       lock();
+
+       m_isAnimated = true;
+       m_changed = true;
+       assureSize((count + position) * m_count * sizeof(float), true);
+       memcpy(getBuffer() + position * m_count, data, count * m_count * sizeof(float));
+
+       unlock();
+}
+
+const float* AUD_AnimateableProperty::read(int position) const
+{
+       return getBuffer() + position * m_count;
+}
+
+bool AUD_AnimateableProperty::isAnimated() const
+{
+       return m_isAnimated;
+}
+
+bool AUD_AnimateableProperty::hasChanged()
+{
+       bool result = m_changed;
+       m_changed = false;
+       return result;
+}
diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.h b/intern/audaspace/intern/AUD_AnimateableProperty.h
new file mode 100644 (file)
index 0000000..5fb9509
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_AnimateableProperty.h
+ *  \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_ANIMATEABLEPROPERTY
+#define AUD_ANIMATEABLEPROPERTY
+
+#include "AUD_Buffer.h"
+
+#include <pthread.h>
+
+/**
+ * This class saves animation data for float properties.
+ */
+class AUD_AnimateableProperty : private AUD_Buffer
+{
+private:
+       /// The count of floats for a single property.
+       const int m_count;
+
+       /// Whether the property is animated or not.
+       bool m_isAnimated;
+
+       /// The mutex for locking.
+       pthread_mutex_t m_mutex;
+
+       /// Whether the property has been changed.
+       bool m_changed;
+
+       // hide copy constructor and operator=
+       AUD_AnimateableProperty(const AUD_AnimateableProperty&);
+       AUD_AnimateableProperty& operator=(const AUD_AnimateableProperty&);
+
+public:
+       /**
+        * Creates a new animateable property.
+        * \param count The count of floats for a single property.
+        */
+       AUD_AnimateableProperty(int count = 1);
+
+       /**
+        * Destroys the animateable property.
+        */
+       ~AUD_AnimateableProperty();
+
+       /**
+        * Locks the property.
+        */
+       void lock();
+
+       /**
+        * Unlocks the previously locked property.
+        */
+       void unlock();
+
+       void write(const float* data);
+
+       void write(const float* data, int position, int count);
+
+       const float* read(int position) const;
+
+       bool isAnimated() const;
+
+       bool hasChanged();
+};
+
+#endif //AUD_ANIMATEABLEPROPERTY
index db76b9b4fafff22b85584bb2759c082188c80ae3..477dc61fd538a40c2119a278e39996154bd8e3f3 100644 (file)
@@ -65,6 +65,7 @@
 #include "AUD_ReadDevice.h"
 #include "AUD_IReader.h"
 #include "AUD_SequencerFactory.h"
+#include "AUD_SequencerEntry.h"
 #include "AUD_SilenceFactory.h"
 
 #ifdef WITH_SDL
@@ -112,7 +113,7 @@ void AUD_initOnce()
 
 int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
 {
-       AUD_Reference<AUD_IDevice> dev = NULL;
+       AUD_Reference<AUD_IDevice> dev;
 
        if(!AUD_device.isNull())
                AUD_exit();
@@ -156,7 +157,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
 
 void AUD_exit()
 {
-       AUD_device = NULL;
+       AUD_device = AUD_Reference<AUD_IDevice>();
        AUD_3ddevice = NULL;
 }
 
@@ -880,14 +881,14 @@ AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds)
        return NULL;
 }
 
-AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume)
+AUD_Sound* AUD_createSequencer(float fps, int muted)
 {
        // specs are changed at a later point!
        AUD_Specs specs;
        specs.channels = AUD_CHANNELS_STEREO;
        specs.rate = AUD_RATE_44100;
-       AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume));
-       return reinterpret_cast<AUD_Sound*>(sequencer);
+       AUD_Sound* sequencer = new AUD_Sound(AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, fps, muted)));
+       return sequencer;
 }
 
 void AUD_destroySequencer(AUD_Sound* sequencer)
@@ -900,27 +901,41 @@ void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted)
        ((AUD_SequencerFactory*)sequencer->get())->mute(muted);
 }
 
-AUD_Reference<AUD_SequencerEntry>* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound,
-                                                                float begin, float end, float skip, void* data)
+void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps)
 {
-       return new AUD_Reference<AUD_SequencerEntry>(((AUD_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data));
+       ((AUD_SequencerFactory*)sequencer->get())->setFPS(fps);
 }
 
-void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry)
+AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
+                                                        float begin, float end, float skip)
+{
+       if(!sound)
+               return new AUD_SEntry(((AUD_SequencerFactory*)sequencer->get())->add(AUD_Sound(), begin, end, skip));
+       return new AUD_SEntry(((AUD_SequencerFactory*)sequencer->get())->add(*sound, begin, end, skip));
+}
+
+void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry)
 {
        ((AUD_SequencerFactory*)sequencer->get())->remove(*entry);
        delete entry;
 }
 
-void AUD_moveSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry,
-                                  float begin, float end, float skip)
+void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->move(*entry, begin, end, skip);
+       (*entry)->move(begin, end, skip);
 }
 
-void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, char mute)
+void AUD_muteSequence(AUD_SEntry* entry, char mute)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute);
+       (*entry)->mute(mute);
+}
+
+void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound)
+{
+       if(sound)
+               (*entry)->setSound(*sound);
+       else
+               (*entry)->setSound(AUD_Sound());
 }
 
 void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer)
@@ -933,6 +948,71 @@ void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs)
        ((AUD_SequencerFactory*)sequencer->get())->setSpecs(specs);
 }
 
+void AUD_seekSequencer(AUD_Handle* handle, float time)
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               device->seekPlayback(time);
+       else
+#endif
+       {
+               assert(handle);
+               (*handle)->seek(time);
+       }
+}
+
+float AUD_getSequencerPosition(AUD_Handle* handle)
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               return device->getPlaybackPosition();
+       else
+#endif
+       {
+               assert(handle);
+               return (*handle)->getPosition();
+       }
+}
+
+void AUD_startPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               device->startPlayback();
+#endif
+}
+
+void AUD_stopPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               device->stopPlayback();
+#endif
+}
+
+#ifdef WITH_JACK
+void AUD_setSyncCallback(AUD_syncFunction function, void* data)
+{
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               device->setSyncCallback(function, data);
+}
+#endif
+
+int AUD_doesPlayback()
+{
+#ifdef WITH_JACK
+       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
+       if(device)
+               return device->doesPlayback();
+#endif
+       return -1;
+}
+
 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
 {
        AUD_DeviceSpecs specs;
@@ -983,71 +1063,6 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
        return length;
 }
 
-void AUD_startPlayback()
-{
-#ifdef WITH_JACK
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               device->startPlayback();
-#endif
-}
-
-void AUD_stopPlayback()
-{
-#ifdef WITH_JACK
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               device->stopPlayback();
-#endif
-}
-
-void AUD_seekSequencer(AUD_Handle* handle, float time)
-{
-#ifdef WITH_JACK
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               device->seekPlayback(time);
-       else
-#endif
-       {
-               assert(handle);
-               (*handle)->seek(time);
-       }
-}
-
-float AUD_getSequencerPosition(AUD_Handle* handle)
-{
-#ifdef WITH_JACK
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               return device->getPlaybackPosition();
-       else
-#endif
-       {
-               assert(handle);
-               return (*handle)->getPosition();
-       }
-}
-
-#ifdef WITH_JACK
-void AUD_setSyncCallback(AUD_syncFunction function, void* data)
-{
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               device->setSyncCallback(function, data);
-}
-#endif
-
-int AUD_doesPlayback()
-{
-#ifdef WITH_JACK
-       AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get());
-       if(device)
-               return device->doesPlayback();
-#endif
-       return -1;
-}
-
 AUD_Sound* AUD_copy(AUD_Sound* sound)
 {
        return new AUD_Reference<AUD_IFactory>(*sound);
index 72d423e847b3482548d0cb599947a183c8179834..949bb89d9e59a38806ef8e2ee479d8e7664d17b1 100644 (file)
@@ -452,43 +452,45 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
  */
 extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
 
-extern AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume);
+extern AUD_Sound* AUD_createSequencer(float fps, int muted);
 
 extern void AUD_destroySequencer(AUD_Sound* sequencer);
 
 extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted);
 
-extern AUD_SEntry* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound,
-                                                                               float begin, float end, float skip, void* data);
+extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps);
 
-extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SEntry* entry);
+extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
+                                                                  float begin, float end, float skip);
 
-extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SEntry* entry,
-                                                 float begin, float end, float skip);
+extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry);
 
-extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SEntry* entry,
-                                                 char mute);
+extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip);
+
+extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
+
+extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
 
 extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
 
 extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
 
-extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
+extern void AUD_seekSequencer(AUD_Handle* handle, float time);
+
+extern float AUD_getSequencerPosition(AUD_Handle* handle);
 
 extern void AUD_startPlayback(void);
 
 extern void AUD_stopPlayback(void);
 
-extern void AUD_seekSequencer(AUD_Handle* handle, float time);
-
-extern float AUD_getSequencerPosition(AUD_Handle* handle);
-
 #ifdef WITH_JACK
 extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
 #endif
 
 extern int AUD_doesPlayback(void);
 
+extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
+
 extern AUD_Sound* AUD_copy(AUD_Sound* sound);
 
 extern void AUD_freeHandle(AUD_Handle* channel);
index 259c702bf868324ab9ceeb163e52816749afe9b4..afb8cb29c536b0ee5cc3dc35af9496889b295169 100644 (file)
 class AUD_I3DHandle
 {
 public:
+       /**
+        * Destroys the handle.
+        */
+       virtual ~AUD_I3DHandle() {}
+
        /**
         * Retrieves the location of a source.
         * \return The location.
index 51d8e0ca2e5d49811280800129faedfd75d25a2b..5b8695131e4d3f02e0657541c258e39a3cb83515 100644 (file)
@@ -43,7 +43,7 @@ class AUD_IHandle
 {
 public:
        /**
-        * Destroys the device.
+        * Destroys the handle.
         */
        virtual ~AUD_IHandle() {}
 
index 6cb13111a430fed963fcb3cb46cf3acc3cb22226..c3a8c754cb2ef939852c87bd1b2ca30f0e09d968 100644 (file)
@@ -51,12 +51,12 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const
 
 AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
 {
-       return 0;
+       return AUD_Reference<AUD_IHandle>();
 }
 
 AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
 {
-       return 0;
+       return AUD_Reference<AUD_IHandle>();
 }
 
 void AUD_NULLDevice::lock()
index 5c1876aeb34002eb8b3d3540baa432bbc036c9f7..24e92d22038bec80782767139c3302b4f9e4cd10 100644 (file)
@@ -42,6 +42,15 @@ AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) :
        create();
 }
 
+AUD_ReadDevice::AUD_ReadDevice(AUD_Specs specs) :
+       m_playing(false)
+{
+       m_specs.specs = specs;
+       m_specs.format = AUD_FORMAT_FLOAT32;
+
+       create();
+}
+
 AUD_ReadDevice::~AUD_ReadDevice()
 {
        destroy();
@@ -59,6 +68,12 @@ bool AUD_ReadDevice::read(data_t* buffer, int length)
        return m_playing;
 }
 
+void AUD_ReadDevice::changeSpecs(AUD_Specs specs)
+{
+       if(memcmp(&specs, &m_specs.specs, sizeof(specs)))
+               setSpecs(specs);
+}
+
 void AUD_ReadDevice::playing(bool playing)
 {
        m_playing = playing;
index 0a77f74b9f68aaeb1c62ec4ebfe2e8bcde421da0..3ec48e6ebca8958dd6ecb59669416d2b752d2d7e 100644 (file)
@@ -59,6 +59,12 @@ public:
         */
        AUD_ReadDevice(AUD_DeviceSpecs specs);
 
+       /**
+        * Creates a new read device.
+        * \param specs The wanted audio specification.
+        */
+       AUD_ReadDevice(AUD_Specs specs);
+
        /**
         * Closes the device.
         */
@@ -73,6 +79,8 @@ public:
         *         silence.
         */
        bool read(data_t* buffer, int length);
+
+       void changeSpecs(AUD_Specs specs);
 };
 
 #endif //AUD_READDEVICE
index 3ddeab2eff15524668ae3e06ca8fec1d3ca95b11..25cc7bcda58a05e0127a284b3b872d3969f065d6 100644 (file)
@@ -33,6 +33,8 @@
 
 #include <map>
 
+// #define MEM_DEBUG
+
 #ifdef MEM_DEBUG
 #include <iostream>
 #include <typeinfo>
@@ -89,24 +91,33 @@ public:
         * Creates a new reference counter.
         * \param reference The reference.
         */
-       AUD_Reference(T* reference = 0)
+       template <class U>
+       AUD_Reference(U* reference)
        {
-               m_original = m_reference = reference;
-               AUD_ReferenceHandler::incref(reference);
+               m_original = reference;
+               m_reference = dynamic_cast<T*>(reference);
+               AUD_ReferenceHandler::incref(m_original);
 #ifdef MEM_DEBUG
                if(m_reference != 0)
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
 #endif
        }
 
+       AUD_Reference()
+       {
+               m_original = 0;
+               m_reference = 0;
+       }
+
        /**
         * Copies an AUD_Reference object.
         * \param ref The AUD_Reference object to copy.
         */
        AUD_Reference(const AUD_Reference& ref)
        {
-               m_original = m_reference = ref.m_reference;
-               AUD_ReferenceHandler::incref(m_reference);
+               m_original = ref.m_original;
+               m_reference = ref.m_reference;
+               AUD_ReferenceHandler::incref(m_original);
 #ifdef MEM_DEBUG
                if(m_reference != 0)
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp
new file mode 100644 (file)
index 0000000..23dc3f3
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_SequencerEntry.cpp
+ *  \ingroup audaspaceintern
+ */
+
+
+#include "AUD_SequencerEntry.h"
+#include "AUD_SequencerReader.h"
+
+#include <cmath>
+#include <limits>
+
+AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip, int id) :
+       m_status(0),
+       m_pos_status(1),
+       m_sound_status(0),
+       m_id(0),
+       m_sound(sound),
+       m_begin(begin),
+       m_end(end),
+       m_skip(skip),
+       m_muted(false),
+       m_relative(false),
+       m_volume_max(1.0f),
+       m_volume_min(0),
+       m_distance_max(std::numeric_limits<float>::max()),
+       m_distance_reference(1.0f),
+       m_attenuation(1.0f),
+       m_cone_angle_outer(360),
+       m_cone_angle_inner(360),
+       m_cone_volume_outer(0),
+       m_location(3),
+       m_orientation(4)
+{
+       AUD_Quaternion q;
+       m_orientation.write(q.get());
+       float f = 1;
+       m_volume.write(&f);
+       m_pitch.write(&f);
+}
+
+void AUD_SequencerEntry::setSound(AUD_Reference<AUD_IFactory> sound)
+{
+       m_sound = sound;
+       m_sound_status++;
+}
+
+void AUD_SequencerEntry::move(float begin, float end, float skip)
+{
+       m_begin = begin;
+       m_skip = skip;
+       m_end = end;
+       m_pos_status++;
+}
+
+void AUD_SequencerEntry::mute(bool mute)
+{
+       m_muted = mute;
+}
+
+int AUD_SequencerEntry::getID() const
+{
+       return m_id;
+}
+
+bool AUD_SequencerEntry::isRelative()
+{
+       return m_relative;
+}
+
+void AUD_SequencerEntry::setRelative(bool relative)
+{
+       m_relative = relative;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getVolumeMaximum()
+{
+       return m_volume_max;
+}
+
+void AUD_SequencerEntry::setVolumeMaximum(float volume)
+{
+       m_volume_max = volume;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getVolumeMinimum()
+{
+       return m_volume_min;
+}
+
+void AUD_SequencerEntry::setVolumeMinimum(float volume)
+{
+       m_volume_min = volume;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getDistanceMaximum()
+{
+       return m_distance_max;
+}
+
+void AUD_SequencerEntry::setDistanceMaximum(float distance)
+{
+       m_distance_max = distance;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getDistanceReference()
+{
+       return m_distance_reference;
+}
+
+void AUD_SequencerEntry::setDistanceReference(float distance)
+{
+       m_distance_reference = distance;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getAttenuation()
+{
+       return m_attenuation;
+}
+
+void AUD_SequencerEntry::setAttenuation(float factor)
+{
+       m_attenuation = factor;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getConeAngleOuter()
+{
+       return m_cone_angle_outer;
+}
+
+void AUD_SequencerEntry::setConeAngleOuter(float angle)
+{
+       m_cone_angle_outer = angle;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getConeAngleInner()
+{
+       return m_cone_angle_inner;
+}
+
+void AUD_SequencerEntry::setConeAngleInner(float angle)
+{
+       m_cone_angle_inner = angle;
+       m_status++;
+}
+
+float AUD_SequencerEntry::getConeVolumeOuter()
+{
+       return m_cone_volume_outer;
+}
+
+void AUD_SequencerEntry::setConeVolumeOuter(float volume)
+{
+       m_cone_volume_outer = volume;
+       m_status++;
+}
diff --git a/intern/audaspace/intern/AUD_SequencerEntry.h b/intern/audaspace/intern/AUD_SequencerEntry.h
new file mode 100644 (file)
index 0000000..316cccc
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_SequencerEntry.h
+ *  \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_SEQUENCERENTRY
+#define AUD_SEQUENCERENTRY
+
+#include "AUD_Reference.h"
+#include "AUD_AnimateableProperty.h"
+#include "AUD_IFactory.h"
+
+class AUD_SequencerEntry
+{
+       friend class AUD_SequencerHandle;
+private:
+       int m_status;
+       int m_pos_status;
+       int m_sound_status;
+       int m_id;
+
+       AUD_Reference<AUD_IFactory> m_sound;
+       float m_begin;
+       float m_end;
+       float m_skip;
+       bool m_muted;
+       bool m_relative;
+       float m_volume_max;
+       float m_volume_min;
+       float m_distance_max;
+       float m_distance_reference;
+       float m_attenuation;
+       float m_cone_angle_outer;
+       float m_cone_angle_inner;
+       float m_cone_volume_outer;
+
+       AUD_AnimateableProperty m_volume;
+       AUD_AnimateableProperty m_panning;
+       AUD_AnimateableProperty m_pitch;
+       AUD_AnimateableProperty m_location;
+       AUD_AnimateableProperty m_orientation;
+
+public:
+       AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip, int id);
+
+       void setSound(AUD_Reference<AUD_IFactory> sound);
+
+       void move(float begin, float end, float skip);
+       void mute(bool mute);
+
+       int getID() const;
+
+       /**
+        * Checks whether the source location, velocity and orientation are relative
+        * to the listener.
+        * \return Whether the source is relative.
+        */
+       bool isRelative();
+
+       /**
+        * Sets whether the source location, velocity and orientation are relative
+        * to the listener.
+        * \param relative Whether the source is relative.
+        * \return Whether the action succeeded.
+        */
+       void setRelative(bool relative);
+
+       /**
+        * Retrieves the maximum volume of a source.
+        * \return The maximum volume.
+        */
+       float getVolumeMaximum();
+
+       /**
+        * Sets the maximum volume of a source.
+        * \param volume The new maximum volume.
+        * \return Whether the action succeeded.
+        */
+       void setVolumeMaximum(float volume);
+
+       /**
+        * Retrieves the minimum volume of a source.
+        * \return The minimum volume.
+        */
+       float getVolumeMinimum();
+
+       /**
+        * Sets the minimum volume of a source.
+        * \param volume The new minimum volume.
+        * \return Whether the action succeeded.
+        */
+       void setVolumeMinimum(float volume);
+
+       /**
+        * Retrieves the maximum distance of a source.
+        * If a source is further away from the reader than this distance, the
+        * volume will automatically be set to 0.
+        * \return The maximum distance.
+        */
+       float getDistanceMaximum();
+
+       /**
+        * Sets the maximum distance of a source.
+        * If a source is further away from the reader than this distance, the
+        * volume will automatically be set to 0.
+        * \param distance The new maximum distance.
+        * \return Whether the action succeeded.
+        */
+       void setDistanceMaximum(float distance);
+
+       /**
+        * Retrieves the reference distance of a source.
+        * \return The reference distance.
+        */
+       float getDistanceReference();
+
+       /**
+        * Sets the reference distance of a source.
+        * \param distance The new reference distance.
+        * \return Whether the action succeeded.
+        */
+       void setDistanceReference(float distance);
+
+       /**
+        * Retrieves the attenuation of a source.
+        * \return The attenuation.
+        */
+       float getAttenuation();
+
+       /**
+        * Sets the attenuation of a source.
+        * This value is used for distance calculation.
+        * \param factor The new attenuation.
+        * \return Whether the action succeeded.
+        */
+       void setAttenuation(float factor);
+
+       /**
+        * Retrieves the outer angle of the cone of a source.
+        * \return The outer angle of the cone.
+        */
+       float getConeAngleOuter();
+
+       /**
+        * Sets the outer angle of the cone of a source.
+        * \param angle The new outer angle of the cone.
+        * \return Whether the action succeeded.
+        */
+       void setConeAngleOuter(float angle);
+
+       /**
+        * Retrieves the inner angle of the cone of a source.
+        * \return The inner angle of the cone.
+        */
+       float getConeAngleInner();
+
+       /**
+        * Sets the inner angle of the cone of a source.
+        * \param angle The new inner angle of the cone.
+        * \return Whether the action succeeded.
+        */
+       void setConeAngleInner(float angle);
+
+       /**
+        * Retrieves the outer volume of the cone of a source.
+        * The volume between inner and outer angle is interpolated between inner
+        * volume and this value.
+        * \return The outer volume of the cone.
+        */
+       float getConeVolumeOuter();
+
+       /**
+        * Sets the outer volume of the cone of a source.
+        * The volume between inner and outer angle is interpolated between inner
+        * volume and this value.
+        * \param volume The new outer volume of the cone.
+        * \return Whether the action succeeded.
+        */
+       void setConeVolumeOuter(float volume);
+};
+
+#endif //AUD_SEQUENCERENTRY
index 6907d7683c981947601bf054966fc7b425ed7714..e26dd7d9bb5766750ca47b48d2ef72f45a80220b 100644 (file)
 
 #include "AUD_SequencerFactory.h"
 #include "AUD_SequencerReader.h"
+#include "AUD_3DMath.h"
 
-typedef std::list<AUD_Reference<AUD_SequencerReader> >::iterator AUD_ReaderIterator;
-
-AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, bool muted,
-                                                                                  void* data,
-                                                                                  AUD_volumeFunction volume) :
+AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) :
        m_specs(specs),
+       m_status(0),
+       m_entry_status(0),
+       m_id(0),
        m_muted(muted),
-       m_data(data),
-       m_volume(volume)
+       m_fps(fps),
+       m_speed_of_sound(434),
+       m_doppler_factor(1),
+       m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED),
+       m_location(3),
+       m_orientation(4)
 {
+       AUD_Quaternion q;
+       m_orientation.write(q.get());
 }
 
 AUD_SequencerFactory::~AUD_SequencerFactory()
@@ -51,9 +57,12 @@ AUD_SequencerFactory::~AUD_SequencerFactory()
 void AUD_SequencerFactory::setSpecs(AUD_Specs specs)
 {
        m_specs = specs;
+       m_status++;
+}
 
-       for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
-               (*i)->setSpecs(m_specs);
+void AUD_SequencerFactory::setFPS(float fps)
+{
+       m_fps = fps;
 }
 
 void AUD_SequencerFactory::mute(bool muted)
@@ -66,55 +75,71 @@ bool AUD_SequencerFactory::getMute() const
        return m_muted;
 }
 
-AUD_Reference<AUD_SequencerEntry> AUD_SequencerFactory::add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data)
+float AUD_SequencerFactory::getSpeedOfSound() const
 {
-       AUD_Reference<AUD_SequencerEntry> entry = new AUD_SequencerEntry;
-       entry->sound = sound;
-       entry->begin = begin;
-       entry->skip = skip;
-       entry->end = end;
-       entry->muted = false;
-       entry->data = data;
-
-       m_entries.push_front(entry);
+       return m_speed_of_sound;
+}
 
-       for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
-               (*i)->add(entry);
+void AUD_SequencerFactory::setSpeedOfSound(float speed)
+{
+       m_speed_of_sound = speed;
+       m_status++;
+}
 
-       return entry;
+float AUD_SequencerFactory::getDopplerFactor() const
+{
+       return m_doppler_factor;
 }
 
-void AUD_SequencerFactory::remove(AUD_Reference<AUD_SequencerEntry> entry)
+void AUD_SequencerFactory::setDopplerFactor(float factor)
 {
-       for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
-               (*i)->remove(entry);
+       m_doppler_factor = factor;
+       m_status++;
+}
 
-       m_entries.remove(entry);
+AUD_DistanceModel AUD_SequencerFactory::getDistanceModel() const
+{
+       return m_distance_model;
 }
 
-void AUD_SequencerFactory::move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip)
+void AUD_SequencerFactory::setDistanceModel(AUD_DistanceModel model)
 {
-       entry->begin = begin;
-       entry->skip = skip;
-       entry->end = end;
+       m_distance_model = model;
+       m_status++;
 }
 
-void AUD_SequencerFactory::mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute)
+AUD_AnimateableProperty* AUD_SequencerFactory::getAnimProperty(AUD_AnimateablePropertyType type)
 {
-       entry->muted = mute;
+       switch(type)
+       {
+       case AUD_AP_VOLUME:
+               return &m_volume;
+       case AUD_AP_LOCATION:
+               return &m_location;
+       case AUD_AP_ORIENTATION:
+               return &m_orientation;
+       default:
+               return NULL;
+       }
 }
 
-AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
+AUD_Reference<AUD_SequencerEntry> AUD_SequencerFactory::add(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip)
 {
-       AUD_Reference<AUD_SequencerReader> reader = new AUD_SequencerReader(this, m_entries,
-                                                                                                                 m_specs, m_data,
-                                                                                                                 m_volume);
-       m_readers.push_front(reader);
+       AUD_Reference<AUD_SequencerEntry> entry = new AUD_SequencerEntry(sound, begin, end, skip, m_id++);
+
+       m_entries.push_front(entry);
+       m_entry_status++;
+
+       return entry;
+}
 
-       return AUD_Reference<AUD_IReader>(reader);
+void AUD_SequencerFactory::remove(AUD_Reference<AUD_SequencerEntry> entry)
+{
+       m_entries.remove(entry);
+       m_entry_status++;
 }
 
-void AUD_SequencerFactory::removeReader(AUD_Reference<AUD_SequencerReader> reader)
+AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
 {
-       m_readers.remove(reader);
+       return new AUD_SequencerReader(this);
 }
index 4e57a224c658d3a3251897f6dc58eee5bb912270..2ad7c18733bbd970f47160e9c2f2c17ac42d886f 100644 (file)
 #define AUD_SEQUENCERFACTORY
 
 #include "AUD_IFactory.h"
+#include "AUD_AnimateableProperty.h"
 
 #include <list>
 
-typedef float (*AUD_volumeFunction)(void*, void*, float);
-
-struct AUD_SequencerEntry
-{
-       AUD_Reference<AUD_IFactory>** sound;
-       float begin;
-       float end;
-       float skip;
-       bool muted;
-       void* data;
-};
-
-class AUD_SequencerReader;
+class AUD_SequencerEntry;
 
+// AUD_XXX TODO: This class is not thread safe yet!
 /**
  * This factory creates a resampling reader that does simple linear resampling.
  */
 class AUD_SequencerFactory : public AUD_IFactory
 {
+       friend class AUD_SequencerReader;
 private:
        /**
         * The target specification.
         */
        AUD_Specs m_specs;
 
+       int m_status;
+       int m_entry_status;
+       int m_id;
        std::list<AUD_Reference<AUD_SequencerEntry> > m_entries;
-       std::list<AUD_Reference<AUD_SequencerReader> > m_readers;
        bool m_muted;
-       void* m_data;
-       AUD_volumeFunction m_volume;
+
+       float m_fps;
+
+       float m_speed_of_sound;
+       float m_doppler_factor;
+       AUD_DistanceModel m_distance_model;
+
+       AUD_AnimateableProperty m_volume;
+       AUD_AnimateableProperty m_location;
+       AUD_AnimateableProperty m_orientation;
 
        // hide copy constructor and operator=
        AUD_SequencerFactory(const AUD_SequencerFactory&);
        AUD_SequencerFactory& operator=(const AUD_SequencerFactory&);
 
 public:
-       AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, AUD_volumeFunction volume);
+       AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted);
        ~AUD_SequencerFactory();
 
        void setSpecs(AUD_Specs specs);
+       void setFPS(float fps);
 
        void mute(bool muted);
        bool getMute() const;
-       AUD_Reference<AUD_SequencerEntry> add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data);
+
+       void setSpeedOfSound(float speed);
+       float getSpeedOfSound() const;
+
+       void setDopplerFactor(float factor);
+       float getDopplerFactor() const;
+
+       void setDistanceModel(AUD_DistanceModel model);
+       AUD_DistanceModel getDistanceModel() const;
+
+       AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type);
+
+       AUD_Reference<AUD_SequencerEntry> add(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip);
        void remove(AUD_Reference<AUD_SequencerEntry> entry);
-       void move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip);
-       void mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute);
 
        virtual AUD_Reference<AUD_IReader> createReader();
-
-       void removeReader(AUD_Reference<AUD_SequencerReader> reader);
 };
 
 #endif //AUD_SEQUENCERFACTORY
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp
new file mode 100644 (file)
index 0000000..a3853d2
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_SequencerHandle.cpp
+ *  \ingroup audaspaceintern
+ */
+
+
+#include "AUD_SequencerHandle.h"
+#include "AUD_ReadDevice.h"
+
+AUD_SequencerHandle::AUD_SequencerHandle(AUD_Reference<AUD_SequencerEntry> entry, AUD_ReadDevice& device) :
+       m_entry(entry),
+       m_status(0),
+       m_pos_status(0),
+       m_sound_status(0),
+       m_device(device)
+{
+       if(!entry->m_sound.isNull())
+       {
+               m_handle = device.play(entry->m_sound, true);
+               m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle);
+       }
+}
+
+AUD_SequencerHandle::~AUD_SequencerHandle()
+{
+       stop();
+}
+
+int AUD_SequencerHandle::compare(AUD_Reference<AUD_SequencerEntry> entry) const
+{
+       if(m_entry->getID() < entry->getID())
+               return -1;
+       else if(m_entry->getID() == entry->getID())
+               return 0;
+       return 1;
+}
+
+void AUD_SequencerHandle::stop()
+{
+       if(!m_handle.isNull())
+               m_handle->stop();
+}
+
+void AUD_SequencerHandle::update(float position)
+{
+       if(!m_handle.isNull())
+       {
+               if(position >= m_entry->m_end)
+                       m_handle->pause();
+               else if(position >= m_entry->m_begin)
+                       m_handle->resume();
+
+               if(m_sound_status != m_entry->m_sound_status)
+               {
+                       if(!m_handle.isNull())
+                               m_handle->stop();
+
+                       if(!m_entry->m_sound.isNull())
+                       {
+                               m_handle = m_device.play(m_entry->m_sound, true);
+                               m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle);
+                       }
+
+                       m_sound_status = m_entry->m_sound_status;
+               }
+
+               if(m_pos_status != m_entry->m_pos_status)
+               {
+                       seek(position);
+
+                       m_pos_status = m_entry->m_pos_status;
+               }
+
+               if(m_status != m_entry->m_status)
+               {
+                       m_3dhandle->setRelative(m_entry->m_relative);
+                       m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
+                       m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
+                       m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
+                       m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
+                       m_3dhandle->setAttenuation(m_entry->m_attenuation);
+                       m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
+                       m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
+                       m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
+
+                       m_status = m_entry->m_status;
+               }
+
+               // AUD_XXX TODO: Animation data
+
+               if(m_entry->m_muted)
+                       m_handle->setVolume(0);
+       }
+}
+
+void AUD_SequencerHandle::seek(float position)
+{
+       if(!m_handle.isNull())
+       {
+               if(position >= m_entry->m_end)
+               {
+                       m_handle->pause();
+                       return;
+               }
+
+               float seekpos = position - m_entry->m_begin;
+               if(seekpos < 0)
+                       seekpos = 0;
+               seekpos += m_entry->m_skip;
+               m_handle->seek(seekpos);
+               if(position < m_entry->m_begin)
+                       m_handle->pause();
+               else
+                       m_handle->resume();
+       }
+}
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h
new file mode 100644 (file)
index 0000000..2e58d81
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_SequencerHandle.h
+ *  \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_SEQUENCERHANDLE
+#define AUD_SEQUENCERHANDLE
+
+#include "AUD_SequencerEntry.h"
+#include "AUD_IHandle.h"
+#include "AUD_I3DHandle.h"
+
+class AUD_ReadDevice;
+
+class AUD_SequencerHandle
+{
+private:
+       AUD_Reference<AUD_SequencerEntry> m_entry;
+       AUD_Reference<AUD_IHandle> m_handle;
+       AUD_Reference<AUD_I3DHandle> m_3dhandle;
+       int m_status;
+       int m_pos_status;
+       int m_sound_status;
+       AUD_ReadDevice& m_device;
+
+public:
+       AUD_SequencerHandle(AUD_Reference<AUD_SequencerEntry> entry, AUD_ReadDevice& device);
+       ~AUD_SequencerHandle();
+       int compare(AUD_Reference<AUD_SequencerEntry> entry) const;
+       void stop();
+       void update(float position);
+       void seek(float position);
+};
+
+#endif //AUD_SEQUENCERHANDLE
index a9309311d6af71d6f7c64b94c33a013cf9df067c..ee113d87a02ae47743b6a144bb9062f280360b50 100644 (file)
 
 
 #include "AUD_SequencerReader.h"
-#include "AUD_Mixer.h"
 
-#ifdef WITH_SAMPLERATE
-#include "AUD_SRCResampleReader.h"
-#else
-#include "AUD_LinearResampleReader.h"
-#endif
-#include "AUD_ChannelMapperReader.h"
-
-#include <math.h>
-
-typedef std::list<AUD_Reference<AUD_SequencerStrip> >::iterator AUD_StripIterator;
+typedef std::list<AUD_Reference<AUD_SequencerHandle> >::iterator AUD_HandleIterator;
 typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator;
 
-AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory,
-                       std::list<AUD_Reference<AUD_SequencerEntry> > &entries, AUD_Specs specs,
-                       void* data, AUD_volumeFunction volume) :
-       m_position(0), m_factory(factory), m_data(data), m_volume(volume)
+AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory) :
+       m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0)
 {
-       AUD_DeviceSpecs dspecs;
-       dspecs.specs = specs;
-       dspecs.format = AUD_FORMAT_FLOAT32;
-
-       m_mixer = new AUD_Mixer(dspecs);
-
-       AUD_Reference<AUD_SequencerStrip> strip;
-
-       for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
-       {
-               strip = new AUD_SequencerStrip;
-               strip->entry = *i;
-               strip->old_sound = NULL;
-
-               m_strips.push_front(strip);
-       }
 }
 
 AUD_SequencerReader::~AUD_SequencerReader()
 {
-       m_factory->removeReader(this);
-}
-
-void AUD_SequencerReader::add(AUD_Reference<AUD_SequencerEntry> entry)
-{
-       AUD_Reference<AUD_SequencerStrip> strip = new AUD_SequencerStrip;
-       strip->entry = entry;
-
-       m_strips.push_front(strip);
-}
-
-void AUD_SequencerReader::remove(AUD_Reference<AUD_SequencerEntry> entry)
-{
-       AUD_Reference<AUD_SequencerStrip> strip;
-       for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
-       {
-               strip = *i;
-               if(strip->entry == entry)
-               {
-                       i++;
-                       m_strips.remove(strip);
-                       return;
-               }
-       }
-}
-
-void AUD_SequencerReader::setSpecs(AUD_Specs specs)
-{
-       m_mixer->setSpecs(specs);
-
-       AUD_Reference<AUD_SequencerStrip> strip;
-       for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
-       {
-               strip = *i;
-               if(!strip->mapper.isNull())
-               {
-                       strip->mapper->setChannels(specs.channels);
-                       strip->resampler->setRate(specs.rate);
-               }
-       }
 }
 
 bool AUD_SequencerReader::isSeekable() const
@@ -119,6 +51,11 @@ bool AUD_SequencerReader::isSeekable() const
 void AUD_SequencerReader::seek(int position)
 {
        m_position = position;
+
+       for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
+       {
+               (*it)->seek(position / m_factory->m_specs.rate);
+       }
 }
 
 int AUD_SequencerReader::getLength() const
@@ -133,92 +70,98 @@ int AUD_SequencerReader::getPosition() const
 
 AUD_Specs AUD_SequencerReader::getSpecs() const
 {
-       return m_mixer->getSpecs().specs;
+       return m_factory->m_specs;
 }
 
 void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
 {
-       AUD_DeviceSpecs specs = m_mixer->getSpecs();
-       int rate = specs.rate;
-
-       int start, end, current, skip, len;
-       AUD_Reference<AUD_SequencerStrip> strip;
-       m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs));
+       if(m_factory->m_status != m_status)
+       {
+               m_device.changeSpecs(m_factory->m_specs);
+               m_device.setSpeedOfSound(m_factory->m_speed_of_sound);
+               m_device.setDistanceModel(m_factory->m_distance_model);
+               m_device.setDopplerFactor(m_factory->m_doppler_factor);
 
-       m_mixer->clear(length);
+               m_status = m_factory->m_status;
+       }
 
-       if(!m_factory->getMute())
+       if(m_factory->m_entry_status != m_entry_status)
        {
-               for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+               std::list<AUD_Reference<AUD_SequencerHandle> > handles;
+
+               AUD_HandleIterator hit = m_handles.begin();
+               AUD_EntryIterator  eit = m_factory->m_entries.begin();
+
+               int result;
+               AUD_Reference<AUD_SequencerHandle> handle;
+
+               while(hit != m_handles.end() && eit != m_factory->m_entries.end())
                {
-                       strip = *i;
-                       if(!strip->entry->muted)
+                       handle = *hit;
+                       AUD_Reference<AUD_SequencerEntry> entry = *eit;
+
+                       result = handle->compare(entry);
+
+                       if(result < 0)
                        {
-                               if(strip->old_sound != *strip->entry->sound)
-                               {
-                                       strip->old_sound = *strip->entry->sound;
-
-                                       if(strip->old_sound)
-                                       {
-                                               try
-                                               {
-                                                       strip->reader = (*strip->old_sound)->createReader();
-                                                       // resample
-                                                       #ifdef WITH_SAMPLERATE
-                                                               strip->resampler = new AUD_SRCResampleReader(strip->reader, m_mixer->getSpecs().specs);
-                                                       #else
-                                                               strip->resampler = new AUD_LinearResampleReader(strip->reader, m_mixer->getSpecs().specs);
-                                                       #endif
-
-                                                       // rechannel
-                                                       strip->mapper = new AUD_ChannelMapperReader(AUD_Reference<AUD_IReader>(strip->resampler), m_mixer->getSpecs().channels);
-                                               }
-                                               catch(AUD_Exception)
-                                               {
-                                                       strip->reader = NULL;
-                                                       strip->resampler = NULL;
-                                                       strip->mapper = NULL;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               strip->reader = NULL;
-                                               strip->resampler = NULL;
-                                               strip->mapper = NULL;
-                                       }
-                               }
-
-                               if(!strip->mapper.isNull())
-                               {
-                                       end = floor(strip->entry->end * rate);
-                                       if(m_position < end)
-                                       {
-                                               start = floor(strip->entry->begin * rate);
-                                               if(m_position + length > start)
-                                               {
-                                                       current = m_position - start;
-                                                       if(current < 0)
-                                                       {
-                                                               skip = -current;
-                                                               current = 0;
-                                                       }
-                                                       else
-                                                               skip = 0;
-                                                       current += strip->entry->skip * rate;
-                                                       len = length > end - m_position ? end - m_position : length;
-                                                       len -= skip;
-                                                       if(strip->mapper->getPosition() != current)
-                                                               strip->mapper->seek(current);
-                                                       strip->mapper->read(len, eos, m_buffer.getBuffer());
-                                                       m_mixer->mix(m_buffer.getBuffer(), skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
-                                               }
-                                       }
-                               }
+                               handle = new AUD_SequencerHandle(entry, m_device);
+                               handles.push_front(handle);
+                               eit++;
                        }
+                       else if(result == 0)
+                       {
+                               handles.push_back(handle);
+                               hit++;
+                               eit++;
+                       }
+                       else
+                       {
+                               handle->stop();
+                               hit++;
+                       }
+               }
+
+               while(hit != m_handles.end())
+               {
+                       (*hit)->stop();
+                       hit++;
                }
+
+               while(eit != m_factory->m_entries.end())
+               {
+                       handle = new AUD_SequencerHandle(*eit, m_device);
+                       handles.push_front(handle);
+                       eit++;
+               }
+
+               m_handles = handles;
+
+               m_entry_status = m_factory->m_entry_status;
        }
 
-       m_mixer->read((data_t*)buffer, 1.0f);
+       // AUD_XXX: TODO: animation data
+
+       AUD_Specs specs = m_factory->m_specs;
+       int pos = 0;
+       float time = float(m_position) / float(specs.rate);
+       int len;
+
+       while(pos < length)
+       {
+               len = int(ceil((int(floor(time * m_factory->m_fps)) + 1) / m_factory->m_fps * specs.rate)) - m_position;
+               len = AUD_MIN(length - pos, len);
+               len = AUD_MAX(len, 1);
+
+               for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
+               {
+                       (*it)->update(time);
+               }
+
+               m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len);
+
+               pos += len;
+               time += float(len) / float(specs.rate);
+       }
 
        m_position += length;
 
index 625bad3c3aed8c54dd65726e1f60087326df1c43..0cce9760b618a85844ebb44562d31068c0478f5e 100644 (file)
 #define AUD_SEQUENCERREADER
 
 #include "AUD_IReader.h"
+#include "AUD_ReadDevice.h"
 #include "AUD_SequencerFactory.h"
-#include "AUD_Buffer.h"
-#include "AUD_Mixer.h"
-#include "AUD_ResampleReader.h"
-#include "AUD_ChannelMapperReader.h"
-
-struct AUD_SequencerStrip
-{
-       AUD_Reference<AUD_IReader> reader;
-       AUD_Reference<AUD_ResampleReader> resampler;
-       AUD_Reference<AUD_ChannelMapperReader> mapper;
-       AUD_Reference<AUD_SequencerEntry> entry;
-       AUD_Reference<AUD_IFactory>* old_sound;
-};
+#include "AUD_SequencerHandle.h"
 
 /**
  * This resampling reader uses libsamplerate for resampling.
@@ -60,24 +49,19 @@ private:
        int m_position;
 
        /**
-        * The reading buffer.
+        * The read device used to mix the sounds correctly.
         */
-       AUD_Buffer m_buffer;
-
-       /**
-        * The target specification.
-        */
-       AUD_Reference<AUD_Mixer> m_mixer;
+       AUD_ReadDevice m_device;
 
        /**
         * Saves the SequencerFactory the reader belongs to.
         */
        AUD_Reference<AUD_SequencerFactory> m_factory;
 
-       std::list<AUD_Reference<AUD_SequencerStrip> > m_strips;
+       std::list<AUD_Reference<AUD_SequencerHandle> > m_handles;
 
-       void* m_data;
-       AUD_volumeFunction m_volume;
+       int m_status;
+       int m_entry_status;
 
        // hide copy constructor and operator=
        AUD_SequencerReader(const AUD_SequencerReader&);
@@ -89,17 +73,13 @@ public:
         * \param reader The reader to mix.
         * \param specs The target specification.
         */
-       AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, std::list<AUD_Reference<AUD_SequencerEntry> > &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume);
+       AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory);
 
        /**
         * Destroys the reader.
         */
        ~AUD_SequencerReader();
 
-       void add(AUD_Reference<AUD_SequencerEntry> entry);
-       void remove(AUD_Reference<AUD_SequencerEntry> entry);
-       void setSpecs(AUD_Specs specs);
-
        virtual bool isSeekable() const;
        virtual void seek(int position);
        virtual int getLength() const;
index 125b9d705dd5e6f1f1a875d1a9516572e96846a4..f8ce9ece02c7db94fccb0e728baa74d2d589d755 100644 (file)
@@ -61,8 +61,8 @@ typedef enum
 /********************** AUD_SoftwareHandle Handle Code ************************/
 /******************************************************************************/
 
-AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) :
-       m_reader(reader), m_pitch(pitch), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_volume(1.0f), m_loopcount(0),
+AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) :
+       m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_volume(1.0f), m_loopcount(0),
        m_relative(false), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
        m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
        m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
@@ -214,6 +214,12 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
                m_mapper->setMonoAngle(0);
 }
 
+void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs)
+{
+       m_mapper->setChannels(specs.channels);
+       m_resampler->setRate(specs.rate);
+}
+
 bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
 {
        if(m_status)
@@ -762,6 +768,17 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
        unlock();
 }
 
+void AUD_SoftwareDevice::setSpecs(AUD_Specs specs)
+{
+       m_specs.specs = specs;
+       m_mixer->setSpecs(specs);
+
+       for(AUD_HandleIterator it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
+       {
+               (*it)->setSpecs(specs);
+       }
+}
+
 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
 {
        return m_specs;
@@ -775,22 +792,25 @@ AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> r
        AUD_Reference<AUD_PitchReader> pitch = new AUD_PitchReader(reader, 1);
        reader = AUD_Reference<AUD_IReader>(pitch);
 
+       AUD_Reference<AUD_ResampleReader> resampler;
+
        // resample
        #ifdef WITH_SAMPLERATE
-               reader = new AUD_SRCResampleReader(reader, m_specs.specs);
+               resampler = new AUD_SRCResampleReader(reader, m_specs.specs);
        #else
-               reader = new AUD_LinearResampleReader(reader, m_specs.specs);
+               resampler = new AUD_LinearResampleReader(reader, m_specs.specs);
        #endif
+       reader = AUD_Reference<AUD_IReader>(resampler);
 
        // rechannel
        AUD_Reference<AUD_ChannelMapperReader> mapper = new AUD_ChannelMapperReader(reader, m_specs.channels);
        reader = AUD_Reference<AUD_IReader>(mapper);
 
        if(reader.isNull())
-               return NULL;
+               return AUD_Reference<AUD_IHandle>();
 
        // play sound
-       AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, mapper, keep);
+       AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep);
 
        lock();
        m_playingSounds.push_back(sound);
index c7dbf1d41ebc4987a6c817db46abface9feae118..1148f4842aadb5853042f417470de06b9fcd5537 100644 (file)
@@ -39,6 +39,7 @@
 #include "AUD_Mixer.h"
 #include "AUD_Buffer.h"
 #include "AUD_PitchReader.h"
+#include "AUD_ResampleReader.h"
 #include "AUD_ChannelMapperReader.h"
 
 #include <list>
@@ -65,6 +66,9 @@ protected:
                /// The pitch reader in between.
                AUD_Reference<AUD_PitchReader> m_pitch;
 
+               /// The resample reader in between.
+               AUD_Reference<AUD_ResampleReader> m_resampler;
+
                /// The channel mapper reader in between.
                AUD_Reference<AUD_ChannelMapperReader> m_mapper;
 
@@ -136,9 +140,10 @@ protected:
 
        public:
 
-               AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep);
+               AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep);
 
                void update();
+               void setSpecs(AUD_Specs specs);
 
                virtual ~AUD_SoftwareHandle() {}
                virtual bool pause();
@@ -218,6 +223,8 @@ protected:
         */
        virtual void playing(bool playing)=0;
 
+       void setSpecs(AUD_Specs specs);
+
 private:
        /**
         * The reading buffer.
index 308e032ff7f50d99bfe2bf8941c8ba2957334dfc..117c37b56ba7ad006ff1b16f35b12ea314a535f6 100644 (file)
@@ -138,7 +138,7 @@ typedef enum
        AUD_ERROR_FFMPEG,
        AUD_ERROR_OPENAL,
        AUD_ERROR_SDL,
-       AUD_ERROR_JACK,
+       AUD_ERROR_JACK
 } AUD_Error;
 
 /// Fading types.
@@ -157,9 +157,18 @@ typedef enum
        AUD_DISTANCE_MODEL_LINEAR,
        AUD_DISTANCE_MODEL_LINEAR_CLAMPED,
        AUD_DISTANCE_MODEL_EXPONENT,
-       AUD_DISTANCE_MODEL_EXPONENT_CLAMPED,
+       AUD_DISTANCE_MODEL_EXPONENT_CLAMPED
 } AUD_DistanceModel;
 
+typedef enum
+{
+       AUD_AP_VOLUME,
+       AUD_AP_PANNING,
+       AUD_AP_PITCH,
+       AUD_AP_LOCATION,
+       AUD_AP_ORIENTATION
+} AUD_AnimateablePropertyType;
+
 /// Sample type.(float samples)
 typedef float sample_t;
 
index bedd58876bc1926e87384146449944ec332cd515..cebf99097aa08aebc0a3b2d4b657b54414fba36b 100644 (file)
@@ -43,6 +43,7 @@ struct Scene;
 struct Sequence;
 struct Strip;
 struct StripElem;
+struct bSound;
 
 #define MAXSEQ          32
 
@@ -281,8 +282,9 @@ void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_m
 struct Sequence        *seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence * seq, int dupe_flag);
 int seq_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
 
-void seq_update_sound(struct Scene* scene, struct Sequence *seq);
+void seq_update_sound_bounds(struct Scene* scene, struct Sequence *seq);
 void seq_update_muting(struct Scene* scene, struct Editing *ed);
+void seq_update_sound(struct Scene *scene, struct bSound *sound);
 void seqbase_sound_reload(struct Scene *scene, ListBase *seqbase);
 void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq);
 void seqbase_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag);
index 7402d501120d22912e693673ba1278f7ad5c8b24..549dc4753209be09660f8a968f2196773952dac2 100644 (file)
@@ -64,6 +64,8 @@ void sound_delete(struct bContext *C, struct bSound* sound);
 
 void sound_cache(struct bSound* sound, int ignore);
 
+void sound_cache_notifying(struct Main* main, struct bSound* sound, int ignore);
+
 void sound_delete_cache(struct bSound* sound);
 
 void sound_load(struct Main *main, struct bSound* sound);
@@ -80,6 +82,8 @@ void sound_destroy_scene(struct Scene *scene);
 
 void sound_mute_scene(struct Scene *scene, int muted);
 
+void sound_update_fps(struct Scene *scene);
+
 void* sound_scene_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip);
 
 void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip);
@@ -90,6 +94,10 @@ void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute);
 
 void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip);
 
+void sound_update_scene_sound(void* handle, struct bSound* sound);
+
+void sound_update_sequencer(struct Main* main, struct bSound* sound);
+
 void sound_play_scene(struct Scene *scene);
 
 void sound_stop_scene(struct Scene *scene);
index 9673fee0b63e372ad088142424b8606401d2e394..e4dc3a31cb1fad2d54f1ab5ed97252a0c08daeea 100644 (file)
@@ -533,7 +533,7 @@ void calc_sequence_disp(Scene *scene, Sequence *seq)
                seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
        }
 
-       seq_update_sound(scene, seq);
+       seq_update_sound_bounds(scene, seq);
 }
 
 static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
@@ -3145,7 +3145,7 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
        return offset? 0:1;
 }
 
-void seq_update_sound(Scene* scene, Sequence *seq)
+void seq_update_sound_bounds(Scene* scene, Sequence *seq)
 {
        if(seq->scene_sound)
        {
@@ -3193,6 +3193,29 @@ void seq_update_muting(Scene *scene, Editing *ed)
        }
 }
 
+static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
+{
+       Sequence *seq;
+
+       for(seq=seqbasep->first; seq; seq=seq->next) {
+               if(seq->type == SEQ_META) {
+                       seq_update_sound_recursive(scene, &seq->seqbase, sound);
+               }
+               else if(seq->type == SEQ_SOUND) {
+                       if(seq->scene_sound && sound == seq->sound) {
+                               sound_update_scene_sound(seq->scene_sound, sound);
+                       }
+               }
+       }
+}
+
+void seq_update_sound(struct Scene *scene, struct bSound *sound)
+{
+       if(scene->ed) {
+               seq_update_sound_recursive(scene, &scene->ed->seqbase, sound);
+       }
+}
+
 /* in cases where we done know the sequence's listbase */
 ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq)
 {
index 493dfa09a65900e0c7700fdafad4d43cd7b3d615..64ba9ed362ae69cd5c51d068342849734d74783f 100644 (file)
@@ -34,6 +34,7 @@
 #include "BKE_packedFile.h"
 #include "BKE_fcurve.h"
 #include "BKE_animsys.h"
+#include "BKE_sequencer.h"
 
 
 struct bSound* sound_new_file(struct Main *bmain, const char *filename)
@@ -257,6 +258,12 @@ void sound_cache(struct bSound* sound, int ignore)
        sound->playback_handle = sound->cache;
 }
 
+void sound_cache_notifying(struct Main* main, struct bSound* sound, int ignore)
+{
+       sound_cache(sound, ignore);
+       sound_update_sequencer(main, sound);
+}
+
 void sound_delete_cache(struct bSound* sound)
 {
        if(sound->cache)
@@ -326,24 +333,9 @@ void sound_load(struct Main *bmain, struct bSound* sound)
                        sound->playback_handle = sound->cache;
                else
                        sound->playback_handle = sound->handle;
-       }
-}
 
-static float sound_get_volume(Scene* scene, Sequence* sequence, float time)
-{
-       AnimData *adt= BKE_animdata_from_id(&scene->id);
-       FCurve *fcu = NULL;
-       char buf[64];
-       
-       /* NOTE: this manually constructed path needs to be used here to avoid problems with RNA crashes */
-       sprintf(buf, "sequence_editor.sequences_all[\"%s\"].volume", sequence->name+2);
-       if (adt && adt->action && adt->action->curves.first)
-               fcu= list_find_fcurve(&adt->action->curves, buf, 0);
-       
-       if(fcu)
-               return evaluate_fcurve(fcu, time * (float)FPS);
-       else
-               return sequence->volume;
+               sound_update_sequencer(bmain, sound);
+       }
 }
 
 AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
@@ -360,7 +352,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
 
 void sound_create_scene(struct Scene *scene)
 {
-       scene->sound_scene = AUD_createSequencer(scene->audio.flag & AUDIO_MUTE, scene, (AUD_volumeFunction)&sound_get_volume);
+       scene->sound_scene = AUD_createSequencer(FPS, scene->audio.flag & AUDIO_MUTE);
        scene->sound_scene_handle = NULL;
        scene->sound_scrub_handle = NULL;
 }
@@ -381,31 +373,50 @@ void sound_mute_scene(struct Scene *scene, int muted)
                AUD_setSequencerMuted(scene->sound_scene, muted);
 }
 
+void sound_update_fps(struct Scene *scene)
+{
+       if(scene->sound_scene)
+               AUD_setSequencerFPS(scene->sound_scene, FPS);
+}
+
 void* sound_scene_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
 {
        if(scene != sequence->scene)
-               return AUD_addSequencer(scene->sound_scene, &(sequence->scene->sound_scene), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
+               return AUD_addSequence(scene->sound_scene, sequence->scene->sound_scene, startframe / FPS, endframe / FPS, frameskip / FPS);
        return NULL;
 }
 
 void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
 {
-       return AUD_addSequencer(scene->sound_scene, &(sequence->sound->playback_handle), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
+       return AUD_addSequence(scene->sound_scene, sequence->sound->playback_handle, startframe / FPS, endframe / FPS, frameskip / FPS);
 }
 
 void sound_remove_scene_sound(struct Scene *scene, void* handle)
 {
-       AUD_removeSequencer(scene->sound_scene, handle);
+       AUD_removeSequence(scene->sound_scene, handle);
 }
 
 void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute)
 {
-       AUD_muteSequencer(scene->sound_scene, handle, mute);
+       AUD_muteSequence(handle, mute);
 }
 
 void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip)
 {
-       AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS);
+       AUD_moveSequence(handle, startframe / FPS, endframe / FPS, frameskip / FPS);
+}
+
+void sound_update_scene_sound(void* handle, struct bSound* sound)
+{
+       AUD_updateSequenceSound(handle, sound->playback_handle);
+}
+
+void sound_update_sequencer(struct Main* main, struct bSound* sound)
+{
+       struct Scene* scene;
+
+       for(scene = main->scene.first; scene; scene = scene->id.next)
+               seq_update_sound(scene, sound);
 }
 
 static void sound_start_play_scene(struct Scene *scene)
index 8cfae0d9c7e45d24db56e35db1a321b4d24dba3a..87f2a72cfe035ee80ddcbe31312dce9e4115926f 100644 (file)
@@ -5590,7 +5590,7 @@ static void lib_link_sound(FileData *fd, Main *main)
                        sound_load(main, sound);
 
                        if(sound->cache)
-                               sound_cache(sound, 1);
+                               sound_cache_notifying(main, sound, 1);
                }
                sound= sound->id.next;
        }
index 2923bb620008630e58880b934181e496a56e68ae..3a3a805f3ceba4e290d30466ec89c2ad2dc926ae 100644 (file)
@@ -100,14 +100,6 @@ EnumPropertyItem snap_element_items[] = {
        {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
        {0, NULL, 0, NULL, NULL}};
 
-static EnumPropertyItem audio_channel_items[] = {
-       {1, "MONO", 0, "Mono", "Set audio channels to mono"},
-       {2, "STEREO", 0, "Stereo", "Set audio channels to stereo"},
-       {4, "SURROUND4", 0, "4 Channels", "Set audio channels to 4 channels"},
-       {6, "SURROUND51", 0, "5.1 Surround", "Set audio channels to 5.1 surround sound"},
-       {8, "SURROUND71", 0, "7.1 Surround", "Set audio channels to 7.1 surround sound"},
-       {0, NULL, 0, NULL, NULL}};
-
 EnumPropertyItem image_type_items[] = {
        {0, "", 0, "Image", NULL},
        {R_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
@@ -340,6 +332,11 @@ static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
        DAG_on_visible_update(bmain, FALSE);
 }
 
+static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+       sound_update_fps(scene);
+}
+
 static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
 {      
        scene->r.framelen= (float)scene->r.framapto/(float)scene->r.images;
@@ -2153,6 +2150,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 #endif
 
 #ifdef WITH_FFMPEG
+       static EnumPropertyItem audio_channel_items[] = {
+               {1, "MONO", 0, "Mono", "Set audio channels to mono"},
+               {2, "STEREO", 0, "Stereo", "Set audio channels to stereo"},
+               {4, "SURROUND4", 0, "4 Channels", "Set audio channels to 4 channels"},
+               {6, "SURROUND51", 0, "5.1 Surround", "Set audio channels to 5.1 surround sound"},
+               {8, "SURROUND71", 0, "7.1 Surround", "Set audio channels to 7.1 surround sound"},
+               {0, NULL, 0, NULL, NULL}};
+
        static EnumPropertyItem ffmpeg_format_items[] = {
                {FFMPEG_MPEG1, "MPEG1", 0, "MPEG-1", ""},
                {FFMPEG_MPEG2, "MPEG2", 0, "MPEG-2", ""},
@@ -2497,14 +2502,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 1, 120);
        RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_fps_update");
        
        prop= RNA_def_property(srna, "fps_base", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "frs_sec_base");
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.1f, 120.0f);
        RNA_def_property_ui_text(prop, "FPS Base", "Framerate base");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_fps_update");
        
        /* frame mapping */
        prop= RNA_def_property(srna, "frame_map_old", PROP_INT, PROP_NONE);
index eb2d38e97780e51d18f6acf8d81a98be34fe2210..3dab8266c2f7f0ed1c3a2237d64067a48fa1f3f7 100644 (file)
@@ -560,7 +560,7 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p
        free_imbuf_seq(scene, &ed->seqbase, FALSE, TRUE);
 
        if(RNA_struct_is_a(ptr->type, &RNA_SoundSequence))
-               seq_update_sound(scene, ptr->data);
+               seq_update_sound_bounds(scene, ptr->data);
 }
 
 static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
@@ -570,7 +570,7 @@ static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene,
        free_imbuf_seq(scene, &ed->seqbase, FALSE, FALSE);
 
        if(RNA_struct_is_a(ptr->type, &RNA_SoundSequence))
-               seq_update_sound(scene, ptr->data);
+               seq_update_sound_bounds(scene, ptr->data);
 }
 
 static void rna_Sequence_mute_update(Main *bmain, Scene *scene, PointerRNA *ptr)
index 9733905879437249a758648a060241145fd72b3e..f471e5e0fe57ce6c4c83615549d7653b6836e7ad 100644 (file)
@@ -41,7 +41,7 @@
 #include "BKE_sound.h"
 #include "BKE_context.h"
 
-static void rna_Sound_filepath_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Sound_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
 {
        sound_load(bmain, (bSound*)ptr->data);
 }
@@ -61,6 +61,11 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value)
                sound_delete_cache(sound);
 }
 
+static void rna_Sound_caching_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       sound_update_sequencer(bmain, (bSound*)(ptr->data));
+}
+
 #else
 
 static void rna_def_sound(BlenderRNA *brna)
@@ -87,7 +92,7 @@ static void rna_def_sound(BlenderRNA *brna)
        prop= RNA_def_property(srna, "use_memory_cache", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_funcs(prop, "rna_Sound_caching_get", "rna_Sound_caching_set");
        RNA_def_property_ui_text(prop, "Caching", "The sound file is decoded and loaded into RAM");
-       RNA_def_property_update(prop, 0, "rna_Sound_filepath_update");
+       RNA_def_property_update(prop, 0, "rna_Sound_caching_update");
 }
 
 void RNA_def_sound(BlenderRNA *brna)