From d5ee031f76137339e3af0fdadb706fbb8db4c961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= Date: Sat, 22 Oct 2016 13:38:41 +0200 Subject: Fix T49764: Audio strips crackle when animating the volume - Implemented linear interpolation for volume changes in the software mixer. - Using this in the software device. --- intern/audaspace/intern/AUD_Mixer.cpp | 15 +++++++++++++++ intern/audaspace/intern/AUD_Mixer.h | 2 ++ intern/audaspace/intern/AUD_SoftwareDevice.cpp | 10 ++++++---- intern/audaspace/intern/AUD_SoftwareDevice.h | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp index 380affa6bd1..78dfaddd27a 100644 --- a/intern/audaspace/intern/AUD_Mixer.cpp +++ b/intern/audaspace/intern/AUD_Mixer.cpp @@ -95,6 +95,21 @@ void AUD_Mixer::mix(sample_t* buffer, int start, int length, float volume) out[i + start] += buffer[i] * volume; } +void AUD_Mixer::mix(sample_t* buffer, int start, int length, float volume_to, float volume_from) +{ + sample_t* out = m_buffer.getBuffer(); + + length = (std::min(m_length, length + start) - start); + + for(int i = 0; i < length; i++) + { + float volume = volume_from * (1.0f - i / float(length)) + volume_to * (i / float(length)); + + for(int c = 0; c < m_specs.channels; c++) + out[(i + start) * m_specs.channels + c] += buffer[i * m_specs.channels + c] * volume; + } +} + void AUD_Mixer::read(data_t* buffer, float volume) { sample_t* out = m_buffer.getBuffer(); diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 3dd03b0a3fe..0735fee715b 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -95,6 +95,8 @@ public: */ void mix(sample_t* buffer, int start, int length, float volume); + void mix(sample_t* buffer, int start, int length, float volume_to, float volume_from); + /** * Writes the mixing buffer into an output buffer. * \param buffer The target buffer for superposing. diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index c4277a6d02e..15594d340be 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -89,7 +89,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause(bool keep) } AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr reader, boost::shared_ptr pitch, boost::shared_ptr resampler, boost::shared_ptr 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_user_pan(0.0f), m_volume(1.0f), m_loopcount(0), + 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_old_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) @@ -100,6 +100,8 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update() { int flags = 0; + m_old_volume = m_volume; + AUD_Vector3 SL; if(m_relative) SL = -m_location; @@ -404,7 +406,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume) if(volume == 0) { - m_volume = volume; + m_old_volume = m_volume = volume; m_flags |= AUD_RENDER_VOLUME; } else @@ -772,7 +774,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_old_volume); pos += len; @@ -789,7 +791,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_old_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 3c8c1e438a3..54e49c87b27 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -84,6 +84,7 @@ protected: /// The calculated final volume of the source. float m_volume; + float m_old_volume; /// The loop count of the source. int m_loopcount; -- cgit v1.2.3