Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Mueller <nexyon@gmail.com>2011-07-26 17:56:31 +0400
committerJoerg Mueller <nexyon@gmail.com>2011-07-26 17:56:31 +0400
commit9077b8bffc6731062bbd6997379b4bf6badd13e2 (patch)
tree641b4fdb97c201727107c398517233ca313d1f38
parentc0373fb7ea2b6d36b57a7c43706626aa254c70b3 (diff)
3D Audio GSoC:
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
-rw-r--r--intern/audaspace/CMakeLists.txt6
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp4
-rw-r--r--intern/audaspace/intern/AUD_AnimateableProperty.cpp103
-rw-r--r--intern/audaspace/intern/AUD_AnimateableProperty.h94
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp173
-rw-r--r--intern/audaspace/intern/AUD_C-API.h28
-rw-r--r--intern/audaspace/intern/AUD_I3DHandle.h5
-rw-r--r--intern/audaspace/intern/AUD_IHandle.h2
-rw-r--r--intern/audaspace/intern/AUD_NULLDevice.cpp4
-rw-r--r--intern/audaspace/intern/AUD_ReadDevice.cpp15
-rw-r--r--intern/audaspace/intern/AUD_ReadDevice.h8
-rw-r--r--intern/audaspace/intern/AUD_Reference.h21
-rw-r--r--intern/audaspace/intern/AUD_SequencerEntry.cpp188
-rw-r--r--intern/audaspace/intern/AUD_SequencerEntry.h208
-rw-r--r--intern/audaspace/intern/AUD_SequencerFactory.cpp105
-rw-r--r--intern/audaspace/intern/AUD_SequencerFactory.h54
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.cpp141
-rw-r--r--intern/audaspace/intern/AUD_SequencerHandle.h61
-rw-r--r--intern/audaspace/intern/AUD_SequencerReader.cpp231
-rw-r--r--intern/audaspace/intern/AUD_SequencerReader.h36
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp32
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.h9
-rw-r--r--intern/audaspace/intern/AUD_Space.h13
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h4
-rw-r--r--source/blender/blenkernel/BKE_sound.h8
-rw-r--r--source/blender/blenkernel/intern/sequencer.c27
-rw-r--r--source/blender/blenkernel/intern/sound.c57
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c25
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c4
-rw-r--r--source/blender/makesrna/intern/rna_sound.c9
31 files changed, 1291 insertions, 386 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index 603e98a5782..6f3d184dd0b 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -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
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index 684ad50792b..40fc8a55f03 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -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
index 00000000000..bc517819f37
--- /dev/null
+++ b/intern/audaspace/intern/AUD_AnimateableProperty.cpp
@@ -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
index 00000000000..5fb9509267b
--- /dev/null
+++ b/intern/audaspace/intern/AUD_AnimateableProperty.h
@@ -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
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index db76b9b4faf..477dc61fd53 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -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);
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index 72d423e847b..949bb89d9e5 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -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);
diff --git a/intern/audaspace/intern/AUD_I3DHandle.h b/intern/audaspace/intern/AUD_I3DHandle.h
index 259c702bf86..afb8cb29c53 100644
--- a/intern/audaspace/intern/AUD_I3DHandle.h
+++ b/intern/audaspace/intern/AUD_I3DHandle.h
@@ -42,6 +42,11 @@ class AUD_I3DHandle
{
public:
/**
+ * Destroys the handle.
+ */
+ virtual ~AUD_I3DHandle() {}
+
+ /**
* Retrieves the location of a source.
* \return The location.
*/
diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h
index 51d8e0ca2e5..5b8695131e4 100644
--- a/intern/audaspace/intern/AUD_IHandle.h
+++ b/intern/audaspace/intern/AUD_IHandle.h
@@ -43,7 +43,7 @@ class AUD_IHandle
{
public:
/**
- * Destroys the device.
+ * Destroys the handle.
*/
virtual ~AUD_IHandle() {}
diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp
index 6cb13111a43..c3a8c754cb2 100644
--- a/intern/audaspace/intern/AUD_NULLDevice.cpp
+++ b/intern/audaspace/intern/AUD_NULLDevice.cpp
@@ -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()
diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp
index 5c1876aeb34..24e92d22038 100644
--- a/intern/audaspace/intern/AUD_ReadDevice.cpp
+++ b/intern/audaspace/intern/AUD_ReadDevice.cpp
@@ -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;
diff --git a/intern/audaspace/intern/AUD_ReadDevice.h b/intern/audaspace/intern/AUD_ReadDevice.h
index 0a77f74b9f6..3ec48e6ebca 100644
--- a/intern/audaspace/intern/AUD_ReadDevice.h
+++ b/intern/audaspace/intern/AUD_ReadDevice.h
@@ -60,6 +60,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.
*/
virtual ~AUD_ReadDevice();
@@ -73,6 +79,8 @@ public:
* silence.
*/
bool read(data_t* buffer, int length);
+
+ void changeSpecs(AUD_Specs specs);
};
#endif //AUD_READDEVICE
diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h
index 3ddeab2eff1..25cc7bcda58 100644
--- a/intern/audaspace/intern/AUD_Reference.h
+++ b/intern/audaspace/intern/AUD_Reference.h
@@ -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
index 00000000000..23dc3f383b5
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp
@@ -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
index 00000000000..316ccccf643
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerEntry.h
@@ -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
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp
index 6907d7683c9..e26dd7d9bb5 100644
--- a/intern/audaspace/intern/AUD_SequencerFactory.cpp
+++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp
@@ -31,17 +31,23 @@
#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);
}
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h
index 4e57a224c65..2ad7c18733b 100644
--- a/intern/audaspace/intern/AUD_SequencerFactory.h
+++ b/intern/audaspace/intern/AUD_SequencerFactory.h
@@ -33,60 +33,70 @@
#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
index 00000000000..a3853d2b71c
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp
@@ -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
index 00000000000..2e58d815fe1
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerHandle.h
@@ -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
diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp
index a9309311d6a..ee113d87a02 100644
--- a/intern/audaspace/intern/AUD_SequencerReader.cpp
+++ b/intern/audaspace/intern/AUD_SequencerReader.cpp
@@ -30,85 +30,17 @@
#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;
diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h
index 625bad3c3ae..0cce9760b61 100644
--- a/intern/audaspace/intern/AUD_SequencerReader.h
+++ b/intern/audaspace/intern/AUD_SequencerReader.h
@@ -33,20 +33,9 @@
#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;
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index 125b9d705dd..f8ce9ece02c 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -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);
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index c7dbf1d41eb..1148f4842aa 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -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.
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index 308e032ff7f..117c37b56ba 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -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;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index bedd58876bc..cebf99097aa 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 7402d501120..549dc475320 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 9673fee0b63..e4dc3a31cb1 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -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)
{
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 493dfa09a65..64ba9ed362a 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -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)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 8cfae0d9c7e..87f2a72cfe0 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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;
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 2923bb62000..3a3a805f3ce 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -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);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index eb2d38e9778..3dab8266c2f 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -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)
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index 97339058794..f471e5e0fe5 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -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)