Page MenuHome
Paste P418

Proof of concept of linear interpolation between audio volume animation in between video frames - see T49764
ActivePublic

Authored by Olly Funkster (Funkster) on Oct 19 2016, 12:47 PM.
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
index f0e4782..32b53f8 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
@@ -120,6 +120,7 @@ private:
virtual AUD_Status getStatus();
virtual float getVolume();
virtual bool setVolume(float volume);
+ virtual bool setEndVolume(float volume) { return true; };
virtual float getPitch();
virtual bool setPitch(float pitch);
virtual int getLoopCount();
diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h
index c80fb40..0da165a 100644
--- a/intern/audaspace/intern/AUD_IHandle.h
+++ b/intern/audaspace/intern/AUD_IHandle.h
@@ -133,7 +133,16 @@ public:
* - false if the handle is invalid.
*/
virtual bool setVolume(float volume)=0;
-
+
+ /**
+ * Sets the volume of a playing sound at the end of a pending run of samples.
+ * \param volume The volume.
+ * \return
+ * - true if the handle is valid.
+ * - false if the handle is invalid.
+ */
+ virtual bool setEndVolume(float volume)=0;
+
/**
* Retrieves the pitch of a playing sound.
* \return The pitch.
diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp
index 380affa..480fd5b 100644
--- a/intern/audaspace/intern/AUD_Mixer.cpp
+++ b/intern/audaspace/intern/AUD_Mixer.cpp
@@ -84,15 +84,19 @@ void AUD_Mixer::clear(int length)
memset(m_buffer.getBuffer(), 0, length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs));
}
-void AUD_Mixer::mix(sample_t* buffer, int start, int length, float volume)
+void AUD_Mixer::mix(sample_t* buffer, int start, int length, float start_volume, float end_volume)
{
+ float interp_volume;
sample_t* out = m_buffer.getBuffer();
length = (AUD_MIN(m_length, length + start) - start) * m_specs.channels;
start *= m_specs.channels;
- for(int i = 0; i < length; i++)
- out[i + start] += buffer[i] * volume;
+ for(int i = 0; i < length; i++) {
+ // Funkster: linear interpolate between start and end volumes
+ interp_volume = start_volume + ((end_volume - start_volume) * ((float)(i / m_specs.channels) / (float)(length / m_specs.channels)));
+ out[i + start] += buffer[i] * interp_volume;
+ }
}
void AUD_Mixer::read(data_t* buffer, float volume)
diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h
index 3dd03b0..ea5cc5d 100644
--- a/intern/audaspace/intern/AUD_Mixer.h
+++ b/intern/audaspace/intern/AUD_Mixer.h
@@ -92,8 +92,9 @@ public:
* \param start The start sample of the buffer.
* \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
+ * \param end_volume The mixing volume at the end of this run, for linear interpolation. Must be a value between 0.0 and 1.0
*/
- void mix(sample_t* buffer, int start, int length, float volume);
+ void mix(sample_t* buffer, int start, int length, float volume, float end_volume);
/**
* Writes the mixing buffer into an output buffer.
diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h
index ae1435b..dbabe15 100644
--- a/intern/audaspace/intern/AUD_NULLDevice.h
+++ b/intern/audaspace/intern/AUD_NULLDevice.h
@@ -57,6 +57,7 @@ private:
virtual AUD_Status getStatus();
virtual float getVolume();
virtual bool setVolume(float volume);
+ virtual bool setEndVolume(float volume) { return true; };
virtual float getPitch();
virtual bool setPitch(float pitch);
virtual int getLoopCount();
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp
index aa742f7..eba4349 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.cpp
+++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp
@@ -148,7 +148,7 @@ void AUD_SequencerHandle::stop()
m_3dhandle = boost::shared_ptr<AUD_I3DHandle>();
}
-void AUD_SequencerHandle::update(float position, float frame, float fps)
+void AUD_SequencerHandle::update(float position, float frame, float fps, float endframe)
{
if(m_sound_status != m_entry->m_sound_status)
{
@@ -217,6 +217,8 @@ void AUD_SequencerHandle::update(float position, float frame, float fps)
m_entry->m_volume.read(frame, &value);
m_handle->setVolume(value);
+ m_entry->m_volume.read(endframe, &value);
+ m_handle->setEndVolume(value);
m_entry->m_pitch.read(frame, &value);
m_handle->setPitch(value);
m_entry->m_panning.read(frame, &value);
diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h
index 306df4a..9479fc5 100644
--- a/intern/audaspace/intern/AUD_SequencerHandle.h
+++ b/intern/audaspace/intern/AUD_SequencerHandle.h
@@ -108,8 +108,9 @@ public:
* \param position The current time during playback.
* \param frame The current frame during playback.
* \param fps The animation frames per second.
+ * \param endframe The frame that will be at the end of a pending run of samples.
*/
- void update(float position, float frame, float fps);
+ void update(float position, float frame, float fps, float endframe);
/**
* Seeks the handle to a specific time position.
diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp
index aef93cd..e2a3410 100644
--- a/intern/audaspace/intern/AUD_SequencerReader.cpp
+++ b/intern/audaspace/intern/AUD_SequencerReader.cpp
@@ -159,7 +159,7 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
AUD_Specs specs = m_sequence->m_specs;
int pos = 0;
float time = float(m_position) / float(specs.rate);
- float volume, frame;
+ float volume, frame, endframe;
int len, cfra;
AUD_Vector3 v, v2;
AUD_Quaternion q;
@@ -173,10 +173,14 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
len = int(ceil((cfra + 1) / m_sequence->m_fps * specs.rate)) - m_position;
len = AUD_MIN(length - pos, len);
len = AUD_MAX(len, 1);
+
+ // Funkster: move the time increment here from the end of the loop so it can be used for the endframe calculation
+ time += float(len) / float(specs.rate);
+ endframe = time * m_sequence->m_fps;
for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
{
- (*it)->update(time, frame, m_sequence->m_fps);
+ (*it)->update(time, frame, m_sequence->m_fps, endframe);
}
m_sequence->m_volume.read(frame, &volume);
@@ -195,7 +199,6 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len);
pos += len;
- time += float(len) / float(specs.rate);
}
m_position += length;
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index c4277a6..9bd9314 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -115,6 +115,7 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
if(m_pitch->getSpecs().channels != AUD_CHANNELS_MONO)
{
m_volume = m_user_volume;
+ m_end_volume = m_user_end_volume;
m_pitch->setPitch(m_user_pitch);
return;
}
@@ -220,7 +221,9 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
// Volume
+ m_end_volume = m_volume;
m_volume *= m_user_volume;
+ m_end_volume *= m_user_end_volume;
}
// 3D Cue
@@ -413,6 +416,23 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume)
return true;
}
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::setEndVolume(float volume)
+{
+ if(!m_status)
+ return false;
+ m_user_end_volume = volume;
+
+ if(volume == 0)
+ {
+ m_end_volume = volume;
+ m_flags |= AUD_RENDER_VOLUME;
+ }
+ else
+ m_flags &= ~AUD_RENDER_VOLUME;
+
+ return true;
+}
+
float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch()
{
return m_user_pitch;
@@ -772,7 +792,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
// in case of looping
while(pos + len < length && sound->m_loopcount && eos)
{
- m_mixer->mix(buf, pos, len, sound->m_volume);
+ m_mixer->mix(buf, pos, len, sound->m_volume, sound->m_end_volume);
pos += len;
@@ -789,7 +809,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
break;
}
- m_mixer->mix(buf, pos, len, sound->m_volume);
+ m_mixer->mix(buf, pos, len, sound->m_volume, sound->m_end_volume);
// in case the end of the sound is reached
if(eos && !sound->m_loopcount)
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index 3c8c1e4..da0f518 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -79,11 +79,17 @@ protected:
/// The user set volume of the source.
float m_user_volume;
+ /// The user set volume of the source at the end of the pending run of samples.
+ float m_user_end_volume;
+
/// The user set panning for non-3D sources
float m_user_pan;
/// The calculated final volume of the source.
float m_volume;
+
+ /// The calculated final volume of the source at the end of the pending run of samples.
+ float m_end_volume;
/// The loop count of the source.
int m_loopcount;
@@ -176,6 +182,7 @@ protected:
virtual AUD_Status getStatus();
virtual float getVolume();
virtual bool setVolume(float volume);
+ virtual bool setEndVolume(float volume);
virtual float getPitch();
virtual bool setPitch(float pitch);
virtual int getLoopCount();

Event Timeline