3D Audio GSoC:
authorJoerg Mueller <nexyon@gmail.com>
Wed, 3 Aug 2011 09:25:40 +0000 (09:25 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Wed, 3 Aug 2011 09:25:40 +0000 (09:25 +0000)
* Minor audaspace library improvements.
* Considering location, velocity and orientation in AUD_SequencerReader and AUD_SequencerHandle.
* Bugfix: Maximum and Minimum volume weren't used before in the software device.
* Bugfix: Adding speaker objects via info space crashed.
* Listener settings now get updated in the audio system.

14 files changed:
intern/audaspace/intern/AUD_3DMath.h
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_SequencerEntry.cpp
intern/audaspace/intern/AUD_SequencerEntry.h
intern/audaspace/intern/AUD_SequencerHandle.cpp
intern/audaspace/intern/AUD_SequencerReader.cpp
intern/audaspace/intern/AUD_SoftwareDevice.cpp
release/scripts/startup/bl_ui/space_info.py
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/sound.c
source/blender/editors/object/object_add.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c

index 3a6abf811ce2b739cc473ce143ef545ec2b4cf40..007682df2914dbe60d07100a907108e00e8f13dd 100644 (file)
@@ -98,6 +98,15 @@ public:
                destination[2] = m_z;
        }
 
+       /**
+        * Retrieves the components of the vector.
+        * \return The components as float[3].
+        */
+       inline float* get()
+       {
+               return m_v;
+       }
+
        /**
         * Retrieves the components of the vector.
         * \return The components as float[3].
@@ -152,6 +161,14 @@ public:
        {
                return AUD_Vector3(-m_x, -m_y, -m_z);
        }
+
+       inline AUD_Vector3& operator-=(const AUD_Vector3& op)
+       {
+               m_x -= op.m_x;
+               m_y -= op.m_y;
+               m_z -= op.m_z;
+               return *this;
+       }
 };
 
 class AUD_Quaternion
@@ -230,6 +247,15 @@ public:
                destination[3] = m_z;
        }
 
+       /**
+        * Retrieves the components of the vector.
+        * \return The components as float[4].
+        */
+       inline float* get()
+       {
+               return m_v;
+       }
+
        /**
         * Retrieves the components of the vector.
         * \return The components as float[4].
index c365f8b9c5e76167f36633c8f2399bcbb0c310e4..23245b56b200e863e6e0eec7c37caa826038efc6 100644 (file)
@@ -39,6 +39,7 @@
 #include "AUD_PyAPI.h"
 #endif
 
+#include <set>
 #include <cstdlib>
 #include <cstring>
 #include <cmath>
@@ -898,12 +899,12 @@ void AUD_destroySequencer(AUD_Sound* sequencer)
 
 void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->mute(muted);
+       dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->mute(muted);
 }
 
 void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->setFPS(fps);
+       dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->setFPS(fps);
 }
 
 AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
@@ -916,7 +917,7 @@ AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
 
 void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->remove(*entry);
+       dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->remove(*entry);
        delete entry;
 }
 
@@ -930,6 +931,11 @@ void AUD_muteSequence(AUD_SEntry* entry, char mute)
        (*entry)->mute(mute);
 }
 
+void AUD_setRelativeSequence(AUD_SEntry* entry, char relative)
+{
+       (*entry)->setRelative(relative);
+}
+
 void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound)
 {
        if(sound)
@@ -949,21 +955,38 @@ void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type
 
 void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
 {
-       AUD_AnimateableProperty* prop = ((AUD_SequencerFactory*)sequencer->get())->getAnimProperty(type);
+       AUD_AnimateableProperty* prop = dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->getAnimProperty(type);
        if(animated)
                prop->write(data, frame, 1);
        else
                prop->write(data);
 }
 
+void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min,
+                                                       float distance_max, float distance_reference, float attenuation,
+                                                       float cone_angle_outer, float cone_angle_inner, float cone_volume_outer)
+{
+       (*entry)->updateAll(volume_max, volume_min, distance_max, distance_reference, attenuation,
+                                               cone_angle_outer, cone_angle_inner, cone_volume_outer);
+}
+
+void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound,
+                                                        float factor, AUD_DistanceModel model)
+{
+       AUD_SequencerFactory* f = dynamic_cast<AUD_SequencerFactory*>(sequencer->get());
+       f->setSpeedOfSound(speed_of_sound);
+       f->setDopplerFactor(factor);
+       f->setDistanceModel(model);
+}
+
 void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
+       dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
 }
 
 void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs)
 {
-       ((AUD_SequencerFactory*)sequencer->get())->setSpecs(specs);
+       dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->setSpecs(specs);
 }
 
 void AUD_seekSequencer(AUD_Handle* handle, float time)
@@ -1090,3 +1113,43 @@ void AUD_freeHandle(AUD_Handle* handle)
 {
        delete handle;
 }
+
+void* AUD_createSet()
+{
+       return new std::set<void*>();
+}
+
+void AUD_destroySet(void* set)
+{
+       delete reinterpret_cast<std::set<void*>*>(set);
+}
+
+char AUD_removeSet(void* set, void* entry)
+{
+       if(set)
+               return reinterpret_cast<std::set<void*>*>(set)->erase(entry);
+       return 0;
+}
+
+void AUD_addSet(void* set, void* entry)
+{
+       if(entry)
+               reinterpret_cast<std::set<void*>*>(set)->insert(entry);
+}
+
+void* AUD_getSet(void* set)
+{
+       if(set)
+       {
+               std::set<void*>* rset = reinterpret_cast<std::set<void*>*>(set);
+               if(!rset->empty())
+               {
+                       std::set<void*>::iterator it = rset->begin();
+                       void* result = *it;
+                       rset->erase(it);
+                       return result;
+               }
+       }
+
+       return NULL;
+}
index 8b7112bfa3f19598f3312d33bf25c1826694e2e1..a6ef34280c2ed751ff008a64c9704fe6d8e12302 100644 (file)
@@ -469,12 +469,21 @@ extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float sk
 
 extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
 
+extern void AUD_setRelativeSequence(AUD_SEntry* entry, char relative);
+
 extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
 
 extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
 
 extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
 
+extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min,
+                                                                  float distance_max, float distance_reference, float attenuation,
+                                                                  float cone_angle_outer, float cone_angle_inner, float cone_volume_outer);
+
+extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound,
+                                                                       float factor, AUD_DistanceModel model);
+
 extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
 
 extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
@@ -499,6 +508,16 @@ extern AUD_Sound* AUD_copy(AUD_Sound* sound);
 
 extern void AUD_freeHandle(AUD_Handle* channel);
 
+extern void* AUD_createSet();
+
+extern void AUD_destroySet(void* set);
+
+extern char AUD_removeSet(void* set, void* entry);
+
+extern void AUD_addSet(void* set, void* entry);
+
+extern void* AUD_getSet(void* set);
+
 #ifdef WITH_PYTHON
 extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
 
index 5ba35955f3c52135c8833ed932173c67005392e1..54993befb41988b5c47cca4ac3a046741784e06d 100644 (file)
@@ -66,8 +66,11 @@ AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float
 
 void AUD_SequencerEntry::setSound(AUD_Reference<AUD_IFactory> sound)
 {
-       m_sound = sound;
-       m_sound_status++;
+       if(m_sound.get() != sound.get())
+       {
+               m_sound = sound;
+               m_sound_status++;
+       }
 }
 
 void AUD_SequencerEntry::move(float begin, float end, float skip)
@@ -110,6 +113,59 @@ AUD_AnimateableProperty* AUD_SequencerEntry::getAnimProperty(AUD_AnimateableProp
        }
 }
 
+void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float distance_max,
+                                                                  float distance_reference, float attenuation, float cone_angle_outer,
+                                                                  float cone_angle_inner, float cone_volume_outer)
+{
+       if(volume_max != m_volume_max)
+       {
+               m_volume_max = volume_max;
+               m_status++;
+       }
+
+       if(volume_min != m_volume_min)
+       {
+               m_volume_min = volume_min;
+               m_status++;
+       }
+
+       if(distance_max != m_distance_max)
+       {
+               m_distance_max = distance_max;
+               m_status++;
+       }
+
+       if(distance_reference != m_distance_reference)
+       {
+               m_distance_reference = distance_reference;
+               m_status++;
+       }
+
+       if(attenuation != m_attenuation)
+       {
+               m_attenuation = attenuation;
+               m_status++;
+       }
+
+       if(cone_angle_outer != m_cone_angle_outer)
+       {
+               m_cone_angle_outer = cone_angle_outer;
+               m_status++;
+       }
+
+       if(cone_angle_inner != m_cone_angle_inner)
+       {
+               m_cone_angle_inner = cone_angle_inner;
+               m_status++;
+       }
+
+       if(cone_volume_outer != m_cone_volume_outer)
+       {
+               m_cone_volume_outer = cone_volume_outer;
+               m_status++;
+       }
+}
+
 bool AUD_SequencerEntry::isRelative()
 {
        return m_relative;
@@ -117,8 +173,11 @@ bool AUD_SequencerEntry::isRelative()
 
 void AUD_SequencerEntry::setRelative(bool relative)
 {
-       m_relative = relative;
-       m_status++;
+       if(m_relative != relative)
+       {
+               m_relative = relative;
+               m_status++;
+       }
 }
 
 float AUD_SequencerEntry::getVolumeMaximum()
index 950e0fd95507209b88dfc711c52756ced4986cf6..5c68b4c7ab218f129d604675afd32c016c0abc12 100644 (file)
@@ -78,6 +78,10 @@ public:
 
        AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type);
 
+       void updateAll(float volume_max, float volume_min, float distance_max,
+                                  float distance_reference, float attenuation, float cone_angle_outer,
+                                  float cone_angle_inner, float cone_volume_outer);
+
        /**
         * Checks whether the source location, velocity and orientation are relative
         * to the listener.
index dead6fdf07b0d076f8b1cc589e23dc4db8875ee3..006dafe2026e8486b9bed021fca88c44a786fba8 100644 (file)
@@ -70,7 +70,7 @@ void AUD_SequencerHandle::update(float position, float frame)
 {
        if(!m_handle.isNull())
        {
-               if(position >= m_entry->m_end)
+               if(position >= m_entry->m_end && m_entry->m_end >= 0)
                        m_handle->pause();
                else if(position >= m_entry->m_begin)
                        m_handle->resume();
@@ -120,7 +120,16 @@ void AUD_SequencerHandle::update(float position, float frame)
                m_entry->m_panning.read(frame, &value);
                AUD_SoftwareDevice::setPanning(m_handle.get(), value);
 
-               // AUD_XXX: TODO: animation data
+               AUD_Vector3 v, v2;
+               AUD_Quaternion q;
+
+               m_entry->m_orientation.read(frame, q.get());
+               m_3dhandle->setSourceOrientation(q);
+               m_entry->m_location.read(frame, v.get());
+               m_3dhandle->setSourceLocation(v);
+               m_entry->m_location.read(frame + 1, v2.get());
+               v2 -= v;
+               m_3dhandle->setSourceVelocity(v2);
 
                if(m_entry->m_muted)
                        m_handle->setVolume(0);
@@ -131,7 +140,7 @@ void AUD_SequencerHandle::seek(float position)
 {
        if(!m_handle.isNull())
        {
-               if(position >= m_entry->m_end)
+               if(position >= m_entry->m_end && m_entry->m_end >= 0)
                {
                        m_handle->pause();
                        return;
index c20132e27e1d3c3fe8fd333b4bbb80b78380ea11..e01da34651fab9257c605c63f3022f5b90ddf302 100644 (file)
@@ -139,13 +139,14 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
                m_entry_status = m_factory->m_entry_status;
        }
 
-       // AUD_XXX: TODO: animation data
-
        AUD_Specs specs = m_factory->m_specs;
        int pos = 0;
        float time = float(m_position) / float(specs.rate);
-       float value, frame;
+       float volume, frame;
        int len, cfra;
+       AUD_Vector3 v, v2;
+       AUD_Quaternion q;
+
 
        while(pos < length)
        {
@@ -161,9 +162,16 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
                        (*it)->update(time, frame);
                }
 
-               m_factory->m_volume.read(frame, &value);
+               m_factory->m_volume.read(frame, &volume);
+               m_device.setVolume(volume);
 
-               m_device.setVolume(value);
+               m_factory->m_orientation.read(frame, q.get());
+               m_device.setListenerOrientation(q);
+               m_factory->m_location.read(frame, v.get());
+               m_device.setListenerLocation(v);
+               m_factory->m_location.read(frame + 1, v2.get());
+               v2 -= v;
+               m_device.setListenerVelocity(v2);
 
                m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len);
 
index 1c93ebe9ad0c3dbeb5bfa6fe896cf3d7e6c3a7fc..bc041eb97e35c2a0543c9b8d465379ebe9d0e23f 100644 (file)
@@ -184,6 +184,11 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
                        }
                }
 
+               if(m_volume > m_volume_max)
+                       m_volume = m_volume_max;
+               else if(m_volume < m_volume_min)
+                       m_volume = m_volume_min;
+
                // Volume
 
                m_volume *= m_user_volume;
index eba2581252a551d4e4a4cd73e1f62a17c8753134..6c3dc7517c56d8957b79199f065701288bac2949 100644 (file)
@@ -287,14 +287,14 @@ class INFO_MT_add(bpy.types.Menu):
         layout.operator("object.add", text="Empty", icon='OUTLINER_OB_EMPTY').type = 'EMPTY'
         layout.separator()
 
+        layout.operator("object.speaker_add", text="Speaker", icon='SPEAKER')
+        layout.separator()
+
         layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
         layout.operator_context = 'EXEC_SCREEN'
         layout.operator_menu_enum("object.lamp_add", "type", text="Lamp", icon='OUTLINER_OB_LAMP')
         layout.separator()
 
-        layout.operator("object.speaker_add", text="Speaker", icon='SPEAKER')
-        layout.separator()
-
         layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_EMPTY')
         layout.separator()
 
index 5ccb34338af840253d632d62a6655be29cbc0454..632a2a0bb3b39e8048324197410cef9e9d39c03a 100644 (file)
@@ -84,6 +84,8 @@ void sound_mute_scene(struct Scene *scene, int muted);
 
 void sound_update_fps(struct Scene *scene);
 
+void sound_update_scene_listener(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);
index 6e8b26c6ca61a31404d042044f39560d16187775..59f5cdb678e9065b462b40f89cc4eda4292e8245 100644 (file)
@@ -354,8 +354,11 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start,
 void sound_create_scene(struct Scene *scene)
 {
        scene->sound_scene = AUD_createSequencer(FPS, scene->audio.flag & AUDIO_MUTE);
+       AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound,
+                                                       scene->audio.doppler_factor, scene->audio.distance_model);
        scene->sound_scene_handle = NULL;
        scene->sound_scrub_handle = NULL;
+       scene->speaker_handles = NULL;
 }
 
 void sound_destroy_scene(struct Scene *scene)
@@ -366,6 +369,8 @@ void sound_destroy_scene(struct Scene *scene)
                AUD_stop(scene->sound_scrub_handle);
        if(scene->sound_scene)
                AUD_destroySequencer(scene->sound_scene);
+       if(scene->speaker_handles)
+               AUD_destroySet(scene->speaker_handles);
 }
 
 void sound_mute_scene(struct Scene *scene, int muted)
@@ -380,6 +385,12 @@ void sound_update_fps(struct Scene *scene)
                AUD_setSequencerFPS(scene->sound_scene, FPS);
 }
 
+void sound_update_scene_listener(struct Scene *scene)
+{
+       AUD_updateSequencerData(scene->sound_scene, scene->audio.speed_of_sound,
+                                                       scene->audio.doppler_factor, scene->audio.distance_model);
+}
+
 void* sound_scene_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
 {
        if(scene != sequence->scene)
index 48e138dfcdce14439f5582a3f0d7d27608eb0764..97a98d2017fe01b0c87ab053178ad42547d9f342 100644 (file)
@@ -789,14 +789,13 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
        ot->idname= "OBJECT_OT_speaker_add";
 
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
        ot->exec= object_speaker_add_exec;
        ot->poll= ED_operator_objectmode;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 
-       ED_object_add_generic_props(ot, FALSE);
+       ED_object_add_generic_props(ot, TRUE);
 }
 
 /* only used as menu */
@@ -1636,7 +1635,6 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                }
                                break;
                        case OB_SPEAKER:
-                               // AUD_XXX TODO: always duplicate Speakers on speaker object duplication?
                                if(dupflag!=0) {
                                        ID_NEW_US2(obn->data )
                                        else {
index 7a5d417b59c33bd043abd22076b5b11c1697b5c4..542aea00b00523067d2ac89999f13fc7ef0efd69 100644 (file)
@@ -806,6 +806,7 @@ typedef struct Scene {
        void *sound_scene;
        void *sound_scene_handle;
        void *sound_scrub_handle;
+       void *speaker_handles;
        
        void *fps_info;                                 /* (runtime) info/cache used for presenting playback framerate info to the user */
        
index 0a97344928f57940b57478fc1a55d262d9e00c87..f2618280fa26d4a5de7e7b34f6c11c30d93dfa72 100644 (file)
@@ -337,6 +337,11 @@ static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *
        sound_update_fps(scene);
 }
 
+static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+       sound_update_scene_listener(scene);
+}
+
 static void rna_Scene_volume_set(PointerRNA *ptr, float value)
 {
        Scene *scene= (Scene*)(ptr->data);
@@ -3462,21 +3467,24 @@ void RNA_def_scene(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "audio_doppler_speed", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "audio.speed_of_sound");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.01f, FLT_MAX);
        RNA_def_property_ui_text(prop, "Speed of Sound", "Speed of sound for Doppler effect calculation");
-       RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
 
        prop= RNA_def_property(srna, "audio_doppler_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "audio.doppler_factor");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.0, FLT_MAX);
        RNA_def_property_ui_text(prop, "Doppler Factor", "Pitch factor for Doppler effect calculation");
-       RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
 
        prop= RNA_def_property(srna, "audio_distance_model", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "audio.distance_model");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_enum_items(prop, audio_distance_model_items);
        RNA_def_property_ui_text(prop, "Distance Model", "Distance model for distance attenuation calculation");
-       RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
 
        prop= RNA_def_property(srna, "audio_volume", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "audio.volume");