24
24
#include < glib.h>
25
25
#include < sys/types.h>
26
26
#include < algorithm>
27
+ #include < cassert>
27
28
#include < cmath>
28
29
#include < cstddef>
29
30
#include < mutex>
@@ -45,6 +46,16 @@ Spectrum::Spectrum(const std::string& tag,
45
46
real_input.resize (n_bands);
46
47
output.resize (n_bands / 2U + 1U );
47
48
49
+ latest_samples_mono.resize (n_bands);
50
+
51
+ // Precompute the Hann window, which is an expensive operation.
52
+ // https://en.wikipedia.org/wiki/Hann_function
53
+ hann_window.resize (n_bands);
54
+ for (size_t n = 0 ; n < n_bands; n++) {
55
+ hann_window[n] = 0 .5F * (1 .0F - std::cos (2 .0F * std::numbers::pi_v<float > *
56
+ static_cast <float >(n) / static_cast <float >(n_bands-1 )));
57
+ }
58
+
48
59
complex_output = fftwf_alloc_complex (n_bands);
49
60
50
61
plan = fftwf_plan_dft_r2c_1d (static_cast <int >(n_bands), real_input.data (), complex_output, FFTW_ESTIMATE);
@@ -78,21 +89,8 @@ Spectrum::~Spectrum() {
78
89
}
79
90
80
91
void Spectrum::setup () {
81
- deque_in_mono.resize (0U );
82
-
83
92
std::ranges::fill (real_input, 0 .0F );
84
-
85
- /*
86
- real_input size is hardcoded to 8192. THe same maxium buffer size hardcoded in PipeWire
87
- https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/src/pipewire/filter.c#L48. If we reevei a smaller
88
- array we have to insert some zeros in the beginning.
89
- */
90
-
91
- if (n_samples < real_input.size ()) {
92
- while (deque_in_mono.size () != real_input.size () - n_samples) {
93
- deque_in_mono.push_back (0 .0F );
94
- }
95
- }
93
+ std::ranges::fill (latest_samples_mono, 0 .0F );
96
94
}
97
95
98
96
void Spectrum::process (std::span<float >& left_in,
@@ -108,27 +106,23 @@ void Spectrum::process(std::span<float>& left_in,
108
106
return ;
109
107
}
110
108
111
- for (uint n = 0U ; n < left_in.size (); n++) {
112
- deque_in_mono.push_back (0 .5F * (left_in[n] + right_in[n]));
109
+ if (n_samples < n_bands) {
110
+ // Drop the oldest quantum.
111
+ for (size_t n = 0 ; n < n_bands - n_samples; n++)
112
+ latest_samples_mono[n] = latest_samples_mono[n_samples + n];
113
+
114
+ // Copy the new quantum.
115
+ for (size_t n = 0 ; n < n_samples; n++)
116
+ latest_samples_mono[n_bands - n_samples + n] = 0 .5F * (left_in[n] + right_in[n]);
117
+ } else {
118
+ // Copy the latest n_bands samples.
119
+ for (size_t n = 0 ; n < n_bands; n++)
120
+ latest_samples_mono[n] = 0 .5F * (left_in[n_samples - n_bands + n] +
121
+ right_in[n_samples - n_bands + n]);
113
122
}
114
123
115
- for (size_t n = 0 ; n < deque_in_mono.size (); n++) {
116
- if (n < real_input.size ()) {
117
- // https : // en.wikipedia.org/wiki/Hann_function
118
-
119
- const float w = 0 .5F * (1 .0F - std::cos (2 .0F * std::numbers::pi_v<float > * static_cast <float >(n) /
120
- static_cast <float >(real_input.size () - 1U )));
121
-
122
- real_input[n] = deque_in_mono[n] * w;
123
- }
124
- }
125
-
126
- size_t count = 0U ;
127
-
128
- while (count < n_samples && !deque_in_mono.empty ()) {
129
- deque_in_mono.pop_front ();
130
-
131
- count++;
124
+ for (size_t n = 0 ; n < n_bands; n++) {
125
+ real_input[n] = latest_samples_mono[n] * hann_window[n];
132
126
}
133
127
134
128
if (send_notifications) {
0 commit comments