Skip to content

Commit 2a4810f

Browse files
committed
autoplaylist filter improvements
* initialize slow and fast filters with current values (first call only) - reduces time for filter stabilization * use slightly optimized variant of "rolling average" filter (result is exactly the same) --> replaced `xX = xX * (1-a) + newX * a;` by `xX = xX + a * (newX - Xx);` * use constants for filter parameters (for tinkering and improved readability)
1 parent 5186c0f commit 2a4810f

File tree

1 file changed

+38
-9
lines changed

1 file changed

+38
-9
lines changed

usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@ class AutoPlaylistUsermod : public Usermod {
1212

1313
private:
1414

15+
#if 0
16+
// experimental parameters by softhack007 - more balanced but need testing
17+
const uint_fast32_t ENERGY_SCALE = 24000;
18+
const float FILTER_SLOW1 = 0.0075f; // for "slow" energy
19+
const float FILTER_SLOW2 = 0.005f; // for "slow" lfc / zcr
20+
const float FILTER_FAST1 = 0.2f; // for "fast" energy
21+
const float FILTER_FAST2 = 0.25f; // for "fast" lfc / zcr
22+
const float FILTER_VOLUME = 0.03f; // for volumeSmth averaging - takes 8-10sec until "silence"
23+
#else
24+
// parameters used by TroyHacks / netmindz - behaviour is mainly driven by "energy"
25+
const uint_fast32_t ENERGY_SCALE = 10000;
26+
// softhack007: original code used FILTER_SLOW = 0.002f
27+
const float FILTER_SLOW1 = 0.01f; // for "slow" energy
28+
const float FILTER_SLOW2 = 0.01f; // for "slow" lfc / zcr
29+
const float FILTER_FAST1 = 0.1f; // for "fast" energy
30+
const float FILTER_FAST2 = 0.1f; // for "fast" lfc / zcr
31+
const float FILTER_VOLUME = 0.01f; // for volumeSmth averaging - takes 12-15sec until "silence"
32+
#endif
33+
1534
bool initDone = false;
1635
bool functionality_enabled = false;
1736
bool silenceDetected = true;
@@ -35,6 +54,7 @@ class AutoPlaylistUsermod : public Usermod {
3554
float avg_short_lfc = 1000;
3655
float avg_short_zcr = 500;
3756

57+
bool resetFilters = true; // to (re)initialize filters on first run
3858
uint_fast32_t vector_energy = 0;
3959
uint_fast32_t vector_lfc = 0;
4060
uint_fast32_t vector_zcr = 0;
@@ -94,7 +114,7 @@ class AutoPlaylistUsermod : public Usermod {
94114
}
95115

96116
energy *= energy;
97-
energy /= 10000; // scale down so we get 0 sometimes
117+
energy /= ENERGY_SCALE; // scale down so we get 0 sometimes
98118

99119
uint8_t lfc = fftResult[0];
100120
uint16_t zcr = *(uint16_t*)um_data->u_data[11];
@@ -103,15 +123,24 @@ class AutoPlaylistUsermod : public Usermod {
103123
// and the individual vector distances.
104124

105125
if (volumeSmth > 1.0f) {
126+
// initialize filters on first run
127+
if (resetFilters) {
128+
avg_short_energy = avg_long_energy = energy;
129+
avg_short_lfc = avg_long_lfc = lfc;
130+
avg_short_zcr = avg_long_zcr = zcr;
131+
resetFilters = false;
132+
#ifdef USERMOD_AUTO_PLAYLIST_DEBUG
133+
USER_PRINTLN("autoplaylist: filters reset.");
134+
#endif
135+
}
106136

107-
// softhack007: original code used 0.998f as decay factor
108-
avg_long_energy = avg_long_energy * 0.99f + energy * 0.01f;
109-
avg_long_lfc = avg_long_lfc * 0.99f + lfc * 0.01f;
110-
avg_long_zcr = avg_long_zcr * 0.99f + zcr * 0.01f;
137+
avg_long_energy = avg_long_energy + FILTER_SLOW1 * (float(energy) - avg_long_energy);
138+
avg_long_lfc = avg_long_lfc + FILTER_SLOW2 * (float(lfc) - avg_long_lfc);
139+
avg_long_zcr = avg_long_zcr + FILTER_SLOW2 * (float(zcr) - avg_long_zcr);
111140

112-
avg_short_energy = avg_short_energy * 0.90f + energy * 0.10f;
113-
avg_short_lfc = avg_short_lfc * 0.90f + lfc * 0.10f;
114-
avg_short_zcr = avg_short_zcr * 0.90f + zcr * 0.10f;
141+
avg_short_energy = avg_short_energy + FILTER_FAST1 * (float(energy) - avg_short_energy);
142+
avg_short_lfc = avg_short_lfc + FILTER_FAST2 * (float(lfc) - avg_short_lfc);
143+
avg_short_zcr = avg_short_zcr + FILTER_FAST2 * (float(zcr) - avg_short_zcr);
115144

116145
// allegedly this is faster than pow(whatever,2)
117146
vector_lfc = (avg_short_lfc-avg_long_lfc)*(avg_short_lfc-avg_long_lfc);
@@ -284,7 +313,7 @@ class AutoPlaylistUsermod : public Usermod {
284313

285314
float volumeSmth = *(float*)um_data->u_data[0];
286315

287-
avg_volumeSmth = avg_volumeSmth * 0.99f + volumeSmth * 0.01f;
316+
avg_volumeSmth = avg_volumeSmth + FILTER_VOLUME * (volumeSmth - avg_volumeSmth);
288317

289318
if (avg_volumeSmth >= 1.0f) {
290319
lastSoundTime = millis();

0 commit comments

Comments
 (0)