Skip to content

Commit fdbd5f3

Browse files
committed
add time variant EMA for #58
1 parent f4a3d60 commit fdbd5f3

File tree

7 files changed

+32
-14
lines changed

7 files changed

+32
-14
lines changed

data/locale/en-US.ini

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@ slope="Slope"
7979
rolloff_q="Roll-off Bandwidth (Octaves)"
8080
rolloff_rate="Roll-off Rate (dB/Octave)"
8181

82-
gravity="Gravity"
82+
gravity="Inertia"
8383
temporal_smoothing="Temporal Smoothing"
84-
exp_moving_avg="Exponential Moving Average"
84+
exp_moving_avg="Simple EMA"
85+
tv_exp_moving_avg="Time Variant EMA"
8586
fast_peaks="Fast Peaks"
8687

8788
color_base="Base Color"

src/settings.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ static inline bool p_equ(const char *s1, const char *s2) { return std::strcmp(s1
105105
#define P_GRAVITY "gravity"
106106
#define P_TSMOOTHING "temporal_smoothing"
107107
#define P_EXPAVG "exp_moving_avg"
108+
#define P_TVEXPAVG "tv_exp_moving_avg"
108109
#define P_FAST_PEAKS "fast_peaks"
109110

110111
#define P_COLOR_BASE "color_base"

src/source.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ namespace callbacks {
376376
auto tsmoothlist = obs_properties_add_list(props, P_TSMOOTHING, T(P_TSMOOTHING), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
377377
obs_property_list_add_string(tsmoothlist, T(P_NONE), P_NONE);
378378
obs_property_list_add_string(tsmoothlist, T(P_EXPAVG), P_EXPAVG);
379+
obs_property_list_add_string(tsmoothlist, T(P_TVEXPAVG), P_TVEXPAVG);
379380
auto grav = obs_properties_add_float_slider(props, P_GRAVITY, T(P_GRAVITY), 0.0, 1.0, 0.01);
380381
auto peaks = obs_properties_add_bool(props, P_FAST_PEAKS, T(P_FAST_PEAKS));
381382
obs_property_set_long_description(tsmoothlist, T(P_TEMPORAL_DESC));
@@ -603,6 +604,8 @@ void WAVSource::get_settings(obs_data_t *settings)
603604

604605
if(p_equ(tsmoothing, P_EXPAVG))
605606
m_tsmoothing = TSmoothingMode::EXPONENTIAL;
607+
else if(p_equ(tsmoothing, P_TVEXPAVG))
608+
m_tsmoothing = TSmoothingMode::TVEXPONENTIAL;
606609
else
607610
m_tsmoothing = TSmoothingMode::NONE;
608611

src/source.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ enum class FilterMode
5656
enum class TSmoothingMode
5757
{
5858
NONE,
59-
EXPONENTIAL
59+
EXPONENTIAL,
60+
TVEXPONENTIAL
6061
};
6162

6263
enum class RenderMode
@@ -288,6 +289,16 @@ class WAVSource
288289
return DB_MIN;
289290
}
290291

292+
inline float get_gravity(float seconds)
293+
{
294+
constexpr float denom = 0.03868924705242879469662125316986f;
295+
constexpr float hi = denom * 5.0f;
296+
constexpr float lo = 0.0f;
297+
if((m_tsmoothing == TSmoothingMode::NONE) || (m_gravity <= 0.0f))
298+
return 0.0f;
299+
return (m_tsmoothing == TSmoothingMode::TVEXPONENTIAL) ? std::exp(-seconds / lerp(lo, hi, m_gravity)) : m_gravity;
300+
}
301+
291302
public:
292303
WAVSource(obs_source_t *source);
293304
virtual ~WAVSource();

src/source_avx.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

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

141-
if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
143+
if(m_tsmoothing != TSmoothingMode::NONE)
142144
{
143145
auto oldval = _mm256_load_ps(&m_tsmooth_buf[channel][i]);
144146
if(m_fast_peaks)
@@ -280,9 +282,9 @@ void WAVSourceAVX::tick_meter([[maybe_unused]] float seconds)
280282
out = horizontal_max(_mm256_max_ps(max1, max2));
281283
}
282284

283-
if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
285+
if(m_tsmoothing != TSmoothingMode::NONE)
284286
{
285-
const auto g = m_gravity;
287+
const auto g = get_gravity(seconds);
286288
const auto g2 = 1.0f - g;
287289
if(!m_fast_peaks || (out <= m_meter_buf[channel]))
288290
out = (g * m_meter_buf[channel]) + (g2 * out);

src/source_avx2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void WAVSourceAVX2::tick_spectrum([[maybe_unused]] float seconds)
118118
// normalize FFT output and convert to dBFS
119119
const auto shuffle_mask = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7);
120120
const auto mag_coefficient = _mm256_set1_ps(2.0f / m_window_sum);
121-
const auto g = _mm256_set1_ps(m_gravity);
121+
const auto g = _mm256_set1_ps(get_gravity(seconds));
122122
const auto g2 = _mm256_sub_ps(_mm256_set1_ps(1.0), g); // 1 - gravity
123123
const bool slope = m_slope > 0.0f;
124124
for(size_t i = 0; i < outsz; i += step)
@@ -143,7 +143,7 @@ void WAVSourceAVX2::tick_spectrum([[maybe_unused]] float seconds)
143143
mag = _mm256_mul_ps(mag, _mm256_load_ps(&m_slope_modifiers[i]));
144144

145145
// time domain smoothing
146-
if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
146+
if(m_tsmoothing != TSmoothingMode::NONE)
147147
{
148148
auto oldval = _mm256_load_ps(&m_tsmooth_buf[channel][i]);
149149
// take new values immediately if larger

src/source_generic.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,20 @@ void WAVSourceGeneric::tick_spectrum([[maybe_unused]] float seconds)
108108
continue;
109109

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

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

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

124-
if(m_tsmoothing == TSmoothingMode::EXPONENTIAL)
124+
if(m_tsmoothing != TSmoothingMode::NONE)
125125
{
126126
auto oldval = m_tsmooth_buf[channel][i];
127127
if(m_fast_peaks)
@@ -249,9 +249,9 @@ void WAVSourceGeneric::tick_meter([[maybe_unused]] float seconds)
249249
out = std::max(out, std::abs(m_decibels[channel][i]));
250250
}
251251

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

0 commit comments

Comments
 (0)