Skip to content

Commit

Permalink
add time variant EMA for #58
Browse files Browse the repository at this point in the history
  • Loading branch information
phandasm committed Nov 13, 2023
1 parent f4a3d60 commit fdbd5f3
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 14 deletions.
5 changes: 3 additions & 2 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ slope="Slope"
rolloff_q="Roll-off Bandwidth (Octaves)"
rolloff_rate="Roll-off Rate (dB/Octave)"

gravity="Gravity"
gravity="Inertia"
temporal_smoothing="Temporal Smoothing"
exp_moving_avg="Exponential Moving Average"
exp_moving_avg="Simple EMA"
tv_exp_moving_avg="Time Variant EMA"
fast_peaks="Fast Peaks"

color_base="Base Color"
Expand Down
1 change: 1 addition & 0 deletions src/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ static inline bool p_equ(const char *s1, const char *s2) { return std::strcmp(s1
#define P_GRAVITY "gravity"
#define P_TSMOOTHING "temporal_smoothing"
#define P_EXPAVG "exp_moving_avg"
#define P_TVEXPAVG "tv_exp_moving_avg"
#define P_FAST_PEAKS "fast_peaks"

#define P_COLOR_BASE "color_base"
Expand Down
3 changes: 3 additions & 0 deletions src/source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ namespace callbacks {
auto tsmoothlist = obs_properties_add_list(props, P_TSMOOTHING, T(P_TSMOOTHING), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(tsmoothlist, T(P_NONE), P_NONE);
obs_property_list_add_string(tsmoothlist, T(P_EXPAVG), P_EXPAVG);
obs_property_list_add_string(tsmoothlist, T(P_TVEXPAVG), P_TVEXPAVG);
auto grav = obs_properties_add_float_slider(props, P_GRAVITY, T(P_GRAVITY), 0.0, 1.0, 0.01);
auto peaks = obs_properties_add_bool(props, P_FAST_PEAKS, T(P_FAST_PEAKS));
obs_property_set_long_description(tsmoothlist, T(P_TEMPORAL_DESC));
Expand Down Expand Up @@ -603,6 +604,8 @@ void WAVSource::get_settings(obs_data_t *settings)

if(p_equ(tsmoothing, P_EXPAVG))
m_tsmoothing = TSmoothingMode::EXPONENTIAL;
else if(p_equ(tsmoothing, P_TVEXPAVG))
m_tsmoothing = TSmoothingMode::TVEXPONENTIAL;
else
m_tsmoothing = TSmoothingMode::NONE;

Expand Down
13 changes: 12 additions & 1 deletion src/source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ enum class FilterMode
enum class TSmoothingMode
{
NONE,
EXPONENTIAL
EXPONENTIAL,
TVEXPONENTIAL
};

enum class RenderMode
Expand Down Expand Up @@ -288,6 +289,16 @@ class WAVSource
return DB_MIN;
}

inline float get_gravity(float seconds)
{
constexpr float denom = 0.03868924705242879469662125316986f;
constexpr float hi = denom * 5.0f;
constexpr float lo = 0.0f;
if((m_tsmoothing == TSmoothingMode::NONE) || (m_gravity <= 0.0f))
return 0.0f;
return (m_tsmoothing == TSmoothingMode::TVEXPONENTIAL) ? std::exp(-seconds / lerp(lo, hi, m_gravity)) : m_gravity;
}

public:
WAVSource(obs_source_t *source);
virtual ~WAVSource();
Expand Down
10 changes: 6 additions & 4 deletions src/source_avx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

// adaptation of WAVSourceAVX2 to support CPUs without AVX2
// see comments of WAVSourceAVX2
// FIXME: this specialization should be removed.
// The only CPUs with FMA3 but not AVX2 are ancient AMD chips that prefer SSE code anyway.
void WAVSourceAVX::tick_spectrum([[maybe_unused]] float seconds)
{
//std::lock_guard lock(m_mtx); // now locked in tick()
Expand Down Expand Up @@ -114,7 +116,7 @@ void WAVSourceAVX::tick_spectrum([[maybe_unused]] float seconds)
constexpr auto shuffle_mask_r = 0 | (2 << 2) | (0 << 4) | (2 << 6);
constexpr auto shuffle_mask_i = 1 | (3 << 2) | (1 << 4) | (3 << 6);
const auto mag_coefficient = _mm256_set1_ps(2.0f / m_window_sum);
const auto g = _mm256_set1_ps(m_gravity);
const auto g = _mm256_set1_ps(get_gravity(seconds));
const auto g2 = _mm256_sub_ps(_mm256_set1_ps(1.0), g);
const bool slope = m_slope > 0.0f;
for(size_t i = 0; i < outsz; i += step)
Expand All @@ -138,7 +140,7 @@ void WAVSourceAVX::tick_spectrum([[maybe_unused]] float seconds)
if(slope)
mag = _mm256_mul_ps(mag, _mm256_load_ps(&m_slope_modifiers[i]));

if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
if(m_tsmoothing != TSmoothingMode::NONE)
{
auto oldval = _mm256_load_ps(&m_tsmooth_buf[channel][i]);
if(m_fast_peaks)
Expand Down Expand Up @@ -280,9 +282,9 @@ void WAVSourceAVX::tick_meter([[maybe_unused]] float seconds)
out = horizontal_max(_mm256_max_ps(max1, max2));
}

if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
if(m_tsmoothing != TSmoothingMode::NONE)
{
const auto g = m_gravity;
const auto g = get_gravity(seconds);
const auto g2 = 1.0f - g;
if(!m_fast_peaks || (out <= m_meter_buf[channel]))
out = (g * m_meter_buf[channel]) + (g2 * out);
Expand Down
4 changes: 2 additions & 2 deletions src/source_avx2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void WAVSourceAVX2::tick_spectrum([[maybe_unused]] float seconds)
// normalize FFT output and convert to dBFS
const auto shuffle_mask = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7);
const auto mag_coefficient = _mm256_set1_ps(2.0f / m_window_sum);
const auto g = _mm256_set1_ps(m_gravity);
const auto g = _mm256_set1_ps(get_gravity(seconds));
const auto g2 = _mm256_sub_ps(_mm256_set1_ps(1.0), g); // 1 - gravity
const bool slope = m_slope > 0.0f;
for(size_t i = 0; i < outsz; i += step)
Expand All @@ -143,7 +143,7 @@ void WAVSourceAVX2::tick_spectrum([[maybe_unused]] float seconds)
mag = _mm256_mul_ps(mag, _mm256_load_ps(&m_slope_modifiers[i]));

// time domain smoothing
if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
if(m_tsmoothing != TSmoothingMode::NONE)
{
auto oldval = _mm256_load_ps(&m_tsmooth_buf[channel][i]);
// take new values immediately if larger
Expand Down
10 changes: 5 additions & 5 deletions src/source_generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,20 @@ void WAVSourceGeneric::tick_spectrum([[maybe_unused]] float seconds)
continue;

const auto mag_coefficient = 2.0f / m_window_sum;
const auto g = m_gravity;
const auto g = get_gravity(seconds);
const auto g2 = 1.0f - g;
const bool slope = m_slope > 0.0f;
for(size_t i = 0; i < outsz; i += step)
{
auto real = m_fft_output[i][0];
auto imag = m_fft_output[i][1];

auto mag = std::sqrt((real * real) + (imag * imag)) * mag_coefficient;
auto mag = std::hypot(real, imag) * mag_coefficient;

if(slope)
mag *= m_slope_modifiers[i];

if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
if(m_tsmoothing != TSmoothingMode::NONE)
{
auto oldval = m_tsmooth_buf[channel][i];
if(m_fast_peaks)
Expand Down Expand Up @@ -249,9 +249,9 @@ void WAVSourceGeneric::tick_meter([[maybe_unused]] float seconds)
out = std::max(out, std::abs(m_decibels[channel][i]));
}

if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
if(m_tsmoothing != TSmoothingMode::NONE)
{
const auto g = m_gravity;
const auto g = get_gravity(seconds);
const auto g2 = 1.0f - g;
if(!m_fast_peaks || (out <= m_meter_buf[channel]))
out = (g * m_meter_buf[channel]) + (g2 * out);
Expand Down

0 comments on commit fdbd5f3

Please sign in to comment.