Source browser

examples/shaders/signal_window.cpp

Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.

File fingerprint
1// Apply a rectangular, Hann, Hamming, or Blackman window before a block FFT.
2#ifdef __cplusplus // Include the runtime only in the generated C++ build.
3#include "shdr.h" // Use portable complex storage for real or complex input.
4#endif // Finish the C++ runtime include guard.
5layout(local_size_x = 64) in; // Each invocation windows one input value.
6layout(std430, binding = 0) readonly buffer Input { // Read the original block.
7    vec2 input_values[]; // Read the original block.
8}; // Read the original block.
9layout(std430, binding = 1) writeonly buffer Output { // Store the windowed complex output block.
10    vec2 output_values[]; // Store the windowed complex output block.
11}; // Store the windowed complex output block.
12uniform uint block_length; // Number of values in each windowed block.
13uniform uint channels; // Number of independent blocks.
14uniform uint mode; // Select rectangular 0, Hann 1, Hamming 2, or Blackman 3.
15void main() { // Both real and imaginary components get the same gain.
16    uint index = gl_GlobalInvocationID.x; // Locate one value across all channels.
17    if (index >= block_length * channels) // Ignore extra invocations.
18        return; // Ignore extra invocations.
19    float gain = 1.0; // Rectangular and single-sample windows use unity gain.
20    if (block_length > 1u && mode != 0u) { // Symmetric windows include both endpoints.
21        float phase = 6.28318530717958647692 * float(index % block_length) / // Sweep one full period over the block.
22                      float(block_length - 1u); // Sweep one full period over the block.
23        if (mode == 1u) // Hann endpoints reach zero.
24            gain = 0.5 - 0.5 * cos(phase); // Hann endpoints reach zero.
25        if (mode == 2u) // Hamming retains a small endpoint weight.
26            gain = 0.54 - 0.46 * cos(phase); // Hamming retains a small endpoint weight.
27        if (mode == 3u) // Blackman uses a second cosine to reduce sidelobes.
28            gain = 0.42 - 0.5 * cos(phase) + // Blackman uses a second cosine to reduce sidelobes.
29                   0.08 * cos(2.0 * phase); // Blackman uses a second cosine to reduce sidelobes.
30    } // Window gains define the amplitudes represented by subsequent FFTs.
31    output_values[index] = input_values[index] * gain; // Store the weighted complex value.
32} // Link this output to the first FFT stage when spectral analysis needs a window.