From bd6ca0570e089afc1d29b4f18b8bb6cc086545ea Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Thu, 28 Jul 2011 13:58:59 +0000 Subject: 3D Audio GSoC: Implemented basic audio animation. * AnimatableProperty: Propper cache writing and spline interpolation for reading (the solution for stair steps in audio animation) * Animatable properties so far are: volume, pitch, panning * Users note: Changing the pitch of a sound results in wrong seeking, due to the resulting playback length difference. * Users note: Panning only works for mono sources, values are in the range [-2..2], this basically controls the angle of the sound, 0 is front, -1 left, 1 right and 2 and -2 are back. Typical stereo panning only supports [-1..1]. * Disabled animation of audio related ffmpeg output parameters. * Scene Audio Panel: 3D Listener settings also for Renderer, new Volume property (animatable!), Update/Bake buttons for animation problems, moved sampling rate and channel count here --- .../audaspace/intern/AUD_AnimateableProperty.cpp | 81 ++++++++++++++++++++-- intern/audaspace/intern/AUD_AnimateableProperty.h | 2 +- intern/audaspace/intern/AUD_C-API.cpp | 18 +++++ intern/audaspace/intern/AUD_C-API.h | 4 ++ intern/audaspace/intern/AUD_SequencerEntry.cpp | 32 +++++++-- intern/audaspace/intern/AUD_SequencerEntry.h | 2 + intern/audaspace/intern/AUD_SequencerFactory.cpp | 2 + intern/audaspace/intern/AUD_SequencerHandle.cpp | 13 +++- intern/audaspace/intern/AUD_SequencerHandle.h | 2 +- intern/audaspace/intern/AUD_SequencerReader.cpp | 14 +++- intern/audaspace/intern/AUD_SoftwareDevice.cpp | 12 +++- intern/audaspace/intern/AUD_SoftwareDevice.h | 6 ++ 12 files changed, 169 insertions(+), 19 deletions(-) (limited to 'intern/audaspace') diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.cpp b/intern/audaspace/intern/AUD_AnimateableProperty.cpp index bc517819f37..03d2d3a5ea1 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.cpp +++ b/intern/audaspace/intern/AUD_AnimateableProperty.cpp @@ -32,6 +32,7 @@ #include "AUD_AnimateableProperty.h" #include +#include AUD_AnimateableProperty::AUD_AnimateableProperty(int count) : AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false), m_changed(false) @@ -78,16 +79,85 @@ void AUD_AnimateableProperty::write(const float* data, int position, int count) lock(); m_isAnimated = true; - m_changed = true; + + int pos = getSize() / (sizeof(float) * m_count); + assureSize((count + position) * m_count * sizeof(float), true); - memcpy(getBuffer() + position * m_count, data, count * m_count * sizeof(float)); + + float* buf = getBuffer(); + + memcpy(buf + position * m_count, data, count * m_count * sizeof(float)); + + for(int i = pos; i < position; i++) + memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float)); unlock(); } -const float* AUD_AnimateableProperty::read(int position) const +void AUD_AnimateableProperty::read(float position, float* out) { - return getBuffer() + position * m_count; + lock(); + + if(!m_isAnimated) + { + memcpy(out, getBuffer(), m_count * sizeof(float)); + unlock(); + return; + } + + float last = (getSize() / (sizeof(float) * m_count) - 1); + float t = position - floor(position); + + if(position > last) + { + position = last; + t = 0; + } + + if(t == 0) + { + memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float)); + } + else + { + int pos = int(floor(position)) * m_count; + float t2 = t * t; + float t3 = t2 * t; + float m0, m1; + float* p0; + float* p1 = getBuffer() + pos; + float* p2; + float* p3; + + if(pos == 0) + p0 = p1; + else + p0 = p1 - m_count; + + if(pos > last) + { + p3 = p2 = p1; + } + else + { + p2 = p1 + m_count; + if(pos + m_count > last) + p3 = p2; + else + p3 = p2 + m_count; + } + + for(int i = 0; i < m_count; i++) + { + m0 = (p2[i] - p0[i]) / 2.0f; + m1 = (p3[i] - p1[i]) / 2.0f; + + out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] + + (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; + } + } + + unlock(); } bool AUD_AnimateableProperty::isAnimated() const @@ -97,6 +167,9 @@ bool AUD_AnimateableProperty::isAnimated() const bool AUD_AnimateableProperty::hasChanged() { + if(m_isAnimated) + return true; + 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 index 5fb9509267b..d3b2e29c036 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.h +++ b/intern/audaspace/intern/AUD_AnimateableProperty.h @@ -84,7 +84,7 @@ public: void write(const float* data, int position, int count); - const float* read(int position) const; + void read(float position, float* out); bool isAnimated() const; diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 477dc61fd53..c365f8b9c5e 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -938,6 +938,24 @@ void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound) (*entry)->setSound(AUD_Sound()); } +void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated) +{ + AUD_AnimateableProperty* prop = (*entry)->getAnimProperty(type); + if(animated) + prop->write(data, frame, 1); + else + prop->write(data); +} + +void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated) +{ + AUD_AnimateableProperty* prop = ((AUD_SequencerFactory*)sequencer->get())->getAnimProperty(type); + if(animated) + prop->write(data, frame, 1); + else + prop->write(data); +} + void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer) { ((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs); diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 949bb89d9e5..8b7112bfa3f 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -471,6 +471,10 @@ extern void AUD_muteSequence(AUD_SEntry* entry, char mute); 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_setSequencerDeviceSpecs(AUD_Sound* sequencer); extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs); diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp index 23dc3f383b5..110e5c6a931 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.cpp +++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp @@ -45,7 +45,7 @@ AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference sound, float m_end(end), m_skip(skip), m_muted(false), - m_relative(false), + m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits::max()), @@ -72,10 +72,13 @@ void AUD_SequencerEntry::setSound(AUD_Reference sound) void AUD_SequencerEntry::move(float begin, float end, float skip) { - m_begin = begin; - m_skip = skip; - m_end = end; - m_pos_status++; + if(m_begin != begin || m_skip != skip || m_end != end) + { + m_begin = begin; + m_skip = skip; + m_end = end; + m_pos_status++; + } } void AUD_SequencerEntry::mute(bool mute) @@ -88,6 +91,25 @@ int AUD_SequencerEntry::getID() const return m_id; } +AUD_AnimateableProperty* AUD_SequencerEntry::getAnimProperty(AUD_AnimateablePropertyType type) +{ + switch(type) + { + case AUD_AP_VOLUME: + return &m_volume; + case AUD_AP_PITCH: + return &m_pitch; + case AUD_AP_PANNING: + return &m_panning; + case AUD_AP_LOCATION: + return &m_location; + case AUD_AP_ORIENTATION: + return &m_orientation; + default: + return NULL; + } +} + bool AUD_SequencerEntry::isRelative() { return m_relative; diff --git a/intern/audaspace/intern/AUD_SequencerEntry.h b/intern/audaspace/intern/AUD_SequencerEntry.h index 316ccccf643..950e0fd9550 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.h +++ b/intern/audaspace/intern/AUD_SequencerEntry.h @@ -76,6 +76,8 @@ public: int getID() const; + AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type); + /** * Checks whether the source location, velocity and orientation are relative * to the listener. diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index e26dd7d9bb5..dd856dc0701 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -48,6 +48,8 @@ AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool mute { AUD_Quaternion q; m_orientation.write(q.get()); + float f = 1; + m_volume.write(&f); } AUD_SequencerFactory::~AUD_SequencerFactory() diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp index a3853d2b71c..dead6fdf07b 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.cpp +++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp @@ -66,7 +66,7 @@ void AUD_SequencerHandle::stop() m_handle->stop(); } -void AUD_SequencerHandle::update(float position) +void AUD_SequencerHandle::update(float position, float frame) { if(!m_handle.isNull()) { @@ -111,7 +111,16 @@ void AUD_SequencerHandle::update(float position) m_status = m_entry->m_status; } - // AUD_XXX TODO: Animation data + float value; + + m_entry->m_volume.read(frame, &value); + m_handle->setVolume(value); + m_entry->m_pitch.read(frame, &value); + m_handle->setPitch(value); + m_entry->m_panning.read(frame, &value); + AUD_SoftwareDevice::setPanning(m_handle.get(), value); + + // AUD_XXX: TODO: animation data if(m_entry->m_muted) m_handle->setVolume(0); diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h index 2e58d815fe1..49d74a85fea 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.h +++ b/intern/audaspace/intern/AUD_SequencerHandle.h @@ -54,7 +54,7 @@ public: ~AUD_SequencerHandle(); int compare(AUD_Reference entry) const; void stop(); - void update(float position); + void update(float position, float frame); void seek(float position); }; diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index ee113d87a02..c20132e27e1 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -144,19 +144,27 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) AUD_Specs specs = m_factory->m_specs; int pos = 0; float time = float(m_position) / float(specs.rate); - int len; + float value, frame; + int len, cfra; while(pos < length) { - len = int(ceil((int(floor(time * m_factory->m_fps)) + 1) / m_factory->m_fps * specs.rate)) - m_position; + frame = time * m_factory->m_fps; + cfra = int(floor(frame)); + + len = int(ceil((cfra + 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); + (*it)->update(time, frame); } + m_factory->m_volume.read(frame, &value); + + m_device.setVolume(value); + m_device.read(reinterpret_cast(buffer + specs.channels * pos), len); pos += len; diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index f8ce9ece02c..1c93ebe9ad0 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -62,8 +62,8 @@ typedef enum /******************************************************************************/ 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_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_user_pan(0.0f), m_volume(1.0f), m_loopcount(0), + m_relative(true), 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) { @@ -211,7 +211,7 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update() m_mapper->setMonoAngle(phi); } else - m_mapper->setMonoAngle(0); + m_mapper->setMonoAngle(m_relative ? m_user_pan * M_PI / 2.0 : 0); } void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs) @@ -768,6 +768,12 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) unlock(); } +void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan) +{ + AUD_SoftwareDevice::AUD_SoftwareHandle* h = dynamic_cast(handle); + h->m_user_pan = pan; +} + void AUD_SoftwareDevice::setSpecs(AUD_Specs specs) { m_specs.specs = specs; diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index 1148f4842aa..da317834d2c 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -81,6 +81,9 @@ protected: /// The user set volume of the source. float m_user_volume; + /// The user set panning for non-3D sources + float m_user_pan; + /// The calculated final volume of the source. float m_volume; @@ -278,6 +281,9 @@ private: int m_flags; public: + + static void setPanning(AUD_IHandle* handle, float pan); + virtual AUD_DeviceSpecs getSpecs() const; virtual AUD_Reference play(AUD_Reference reader, bool keep = false); virtual AUD_Reference play(AUD_Reference factory, bool keep = false); -- cgit v1.2.3