From 9077b8bffc6731062bbd6997379b4bf6badd13e2 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Tue, 26 Jul 2011 13:56:31 +0000 Subject: 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 --- intern/audaspace/CMakeLists.txt | 6 + intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 4 +- .../audaspace/intern/AUD_AnimateableProperty.cpp | 103 +++++++++ intern/audaspace/intern/AUD_AnimateableProperty.h | 94 +++++++++ intern/audaspace/intern/AUD_C-API.cpp | 173 ++++++++------- intern/audaspace/intern/AUD_C-API.h | 28 +-- intern/audaspace/intern/AUD_I3DHandle.h | 5 + intern/audaspace/intern/AUD_IHandle.h | 2 +- intern/audaspace/intern/AUD_NULLDevice.cpp | 4 +- intern/audaspace/intern/AUD_ReadDevice.cpp | 15 ++ intern/audaspace/intern/AUD_ReadDevice.h | 8 + intern/audaspace/intern/AUD_Reference.h | 21 +- intern/audaspace/intern/AUD_SequencerEntry.cpp | 188 +++++++++++++++++ intern/audaspace/intern/AUD_SequencerEntry.h | 208 +++++++++++++++++++ intern/audaspace/intern/AUD_SequencerFactory.cpp | 105 ++++++---- intern/audaspace/intern/AUD_SequencerFactory.h | 54 +++-- intern/audaspace/intern/AUD_SequencerHandle.cpp | 141 +++++++++++++ intern/audaspace/intern/AUD_SequencerHandle.h | 61 ++++++ intern/audaspace/intern/AUD_SequencerReader.cpp | 231 ++++++++------------- intern/audaspace/intern/AUD_SequencerReader.h | 36 +--- intern/audaspace/intern/AUD_SoftwareDevice.cpp | 32 ++- intern/audaspace/intern/AUD_SoftwareDevice.h | 9 +- intern/audaspace/intern/AUD_Space.h | 13 +- 23 files changed, 1196 insertions(+), 345 deletions(-) create mode 100644 intern/audaspace/intern/AUD_AnimateableProperty.cpp create mode 100644 intern/audaspace/intern/AUD_AnimateableProperty.h create mode 100644 intern/audaspace/intern/AUD_SequencerEntry.cpp create mode 100644 intern/audaspace/intern/AUD_SequencerEntry.h create mode 100644 intern/audaspace/intern/AUD_SequencerHandle.cpp create mode 100644 intern/audaspace/intern/AUD_SequencerHandle.h (limited to 'intern/audaspace') 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_OpenALDevice::play(AUD_Reference rea // check format if(specs.channels == AUD_CHANNELS_INVALID) - return NULL; + return AUD_Reference(); if(m_specs.format != AUD_FORMAT_FLOAT32) reader = new AUD_ConverterReader(reader, m_specs); @@ -1176,7 +1176,7 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference rea ALenum format; if(!getFormat(format, specs)) - return NULL; + return AUD_Reference(); 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 + +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 + +/** + * 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 dev = NULL; + AUD_Reference 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_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* sequencer = new AUD_Reference(new AUD_SequencerFactory(specs, muted, data, volume)); - return reinterpret_cast(sequencer); + AUD_Sound* sequencer = new AUD_Sound(AUD_Reference(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_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_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data)); + ((AUD_SequencerFactory*)sequencer->get())->setFPS(fps); } -void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference* 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* 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* 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_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_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_device.get()); + if(device) + device->startPlayback(); +#endif +} + +void AUD_stopPlayback() +{ +#ifdef WITH_JACK + AUD_JackDevice* device = dynamic_cast(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_device.get()); + if(device) + device->setSyncCallback(function, data); +} +#endif + +int AUD_doesPlayback() +{ +#ifdef WITH_JACK + AUD_JackDevice* device = dynamic_cast(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_device.get()); - if(device) - device->startPlayback(); -#endif -} - -void AUD_stopPlayback() -{ -#ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(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_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_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_device.get()); - if(device) - device->setSyncCallback(function, data); -} -#endif - -int AUD_doesPlayback() -{ -#ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) - return device->doesPlayback(); -#endif - return -1; -} - AUD_Sound* AUD_copy(AUD_Sound* sound) { return new AUD_Reference(*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 @@ -41,6 +41,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_NULLDevice::play(AUD_Reference reader, bool keep) { - return 0; + return AUD_Reference(); } AUD_Reference AUD_NULLDevice::play(AUD_Reference factory, bool keep) { - return 0; + return AUD_Reference(); } 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 @@ -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 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 +// #define MEM_DEBUG + #ifdef MEM_DEBUG #include #include @@ -89,24 +91,33 @@ public: * Creates a new reference counter. * \param reference The reference. */ - AUD_Reference(T* reference = 0) + template + AUD_Reference(U* reference) { - m_original = m_reference = reference; - AUD_ReferenceHandler::incref(reference); + m_original = reference; + m_reference = dynamic_cast(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 +#include + +AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference 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::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 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 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 sound, float begin, float end, float skip, int id); + + void setSound(AUD_Reference 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 >::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_SequencerFactory::add(AUD_Reference** sound, float begin, float end, float skip, void* data) +float AUD_SequencerFactory::getSpeedOfSound() const { - AUD_Reference 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 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 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 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_SequencerFactory::createReader() +AUD_Reference AUD_SequencerFactory::add(AUD_Reference sound, float begin, float end, float skip) { - AUD_Reference reader = new AUD_SequencerReader(this, m_entries, - m_specs, m_data, - m_volume); - m_readers.push_front(reader); + AUD_Reference entry = new AUD_SequencerEntry(sound, begin, end, skip, m_id++); + + m_entries.push_front(entry); + m_entry_status++; + + return entry; +} - return AUD_Reference(reader); +void AUD_SequencerFactory::remove(AUD_Reference entry) +{ + m_entries.remove(entry); + m_entry_status++; } -void AUD_SequencerFactory::removeReader(AUD_Reference reader) +AUD_Reference 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 -typedef float (*AUD_volumeFunction)(void*, void*, float); - -struct AUD_SequencerEntry -{ - AUD_Reference** 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 > m_entries; - std::list > 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 add(AUD_Reference** 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 add(AUD_Reference sound, float begin, float end, float skip); void remove(AUD_Reference entry); - void move(AUD_Reference entry, float begin, float end, float skip); - void mute(AUD_Reference entry, bool mute); virtual AUD_Reference createReader(); - - void removeReader(AUD_Reference 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 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(m_handle); + } +} + +AUD_SequencerHandle::~AUD_SequencerHandle() +{ + stop(); +} + +int AUD_SequencerHandle::compare(AUD_Reference 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(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 m_entry; + AUD_Reference m_handle; + AUD_Reference m_3dhandle; + int m_status; + int m_pos_status; + int m_sound_status; + AUD_ReadDevice& m_device; + +public: + AUD_SequencerHandle(AUD_Reference entry, AUD_ReadDevice& device); + ~AUD_SequencerHandle(); + int compare(AUD_Reference 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 - -typedef std::list >::iterator AUD_StripIterator; +typedef std::list >::iterator AUD_HandleIterator; typedef std::list >::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_Reference factory, - std::list > &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 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 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 entry) -{ - AUD_Reference strip = new AUD_SequencerStrip; - strip->entry = entry; - - m_strips.push_front(strip); -} - -void AUD_SequencerReader::remove(AUD_Reference entry) -{ - AUD_Reference 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 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 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 > handles; + + AUD_HandleIterator hit = m_handles.begin(); + AUD_EntryIterator eit = m_factory->m_entries.begin(); + + int result; + AUD_Reference handle; + + while(hit != m_handles.end() && eit != m_factory->m_entries.end()) { - strip = *i; - if(!strip->entry->muted) + handle = *hit; + AUD_Reference 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(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(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 reader; - AUD_Reference resampler; - AUD_Reference mapper; - AUD_Reference entry; - AUD_Reference* 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 m_mixer; + AUD_ReadDevice m_device; /** * Saves the SequencerFactory the reader belongs to. */ AUD_Reference m_factory; - std::list > m_strips; + std::list > 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 factory, std::list > &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); + AUD_SequencerReader(AUD_Reference factory); /** * Destroys the reader. */ ~AUD_SequencerReader(); - void add(AUD_Reference entry); - void remove(AUD_Reference 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 reader, AUD_Reference pitch, AUD_Reference 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 reader, AUD_Reference pitch, AUD_Reference resampler, AUD_Reference 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::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_SoftwareDevice::play(AUD_Reference r AUD_Reference pitch = new AUD_PitchReader(reader, 1); reader = AUD_Reference(pitch); + AUD_Reference 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(resampler); // rechannel AUD_Reference mapper = new AUD_ChannelMapperReader(reader, m_specs.channels); reader = AUD_Reference(mapper); if(reader.isNull()) - return NULL; + return AUD_Reference(); // play sound - AUD_Reference sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, mapper, keep); + AUD_Reference 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 @@ -65,6 +66,9 @@ protected: /// The pitch reader in between. AUD_Reference m_pitch; + /// The resample reader in between. + AUD_Reference m_resampler; + /// The channel mapper reader in between. AUD_Reference m_mapper; @@ -136,9 +140,10 @@ protected: public: - AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference reader, AUD_Reference pitch, AUD_Reference mapper, bool keep); + AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference reader, AUD_Reference pitch, AUD_Reference resampler, AUD_Reference 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; -- cgit v1.2.3