Compute window function as alpha16 (UNORM16) coefficients in [0, 1]. Uses fixed-point arithmetic throughout to avoid float on MCUs.
| 490 | // Compute window function as alpha16 (UNORM16) coefficients in [0, 1]. |
| 491 | // Uses fixed-point arithmetic throughout to avoid float on MCUs. |
| 492 | static void computeWindow(fl::vector<alpha16> &win, int N, Window type) { |
| 493 | using FP = fl::fixed_point<16, 16>; |
| 494 | win.resize(N); |
| 495 | |
| 496 | // NONE: rectangular window (all coefficients = 1.0) |
| 497 | if (type == Window::NONE) { |
| 498 | for (int n = 0; n < N; ++n) { |
| 499 | win[n] = alpha16(65535); |
| 500 | } |
| 501 | return; |
| 502 | } |
| 503 | |
| 504 | const FP two_pi(6.2831853f); // 2π |
| 505 | const FP invNm1 = FP(1) / FP(N - 1); |
| 506 | const FP phase_step = two_pi * invNm1; |
| 507 | |
| 508 | // Blackman-Harris coefficients |
| 509 | constexpr FP bh_a0(0.35875f); |
| 510 | constexpr FP bh_a1(0.48829f); |
| 511 | constexpr FP bh_a2(0.14128f); |
| 512 | constexpr FP bh_a3(0.01168f); |
| 513 | // Hanning coefficients |
| 514 | constexpr FP half(0.5f); |
| 515 | constexpr FP one(1.0f); |
| 516 | |
| 517 | FP phase(0.0f); |
| 518 | for (int n = 0; n < N; ++n) { |
| 519 | FP w; |
| 520 | switch (type) { |
| 521 | case Window::BLACKMAN_HARRIS: { |
| 522 | // 4-term Blackman-Harris: -92 dB sidelobe rejection |
| 523 | FP phase2 = phase + phase; |
| 524 | FP phase3 = phase2 + phase; |
| 525 | w = bh_a0 - bh_a1 * FP::cos(phase) |
| 526 | + bh_a2 * FP::cos(phase2) |
| 527 | - bh_a3 * FP::cos(phase3); |
| 528 | break; |
| 529 | } |
| 530 | case Window::HANNING: |
| 531 | default: |
| 532 | w = half * (one - FP::cos(phase)); |
| 533 | break; |
| 534 | } |
| 535 | i32 raw = w.raw(); |
| 536 | if (raw < 0) raw = 0; // guard against FP rounding |
| 537 | if (raw > 65535) raw = 65535; // 1.0 in s16x16 = 65536, clamp for u16 |
| 538 | win[n] = alpha16(static_cast<unsigned short>(raw)); |
| 539 | phase = phase + phase_step; |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | // Apply window: out[i] = sample[i] * win[i] |
| 544 | // Window coefficients are alpha16 (UNORM16 [0,1]); uses scale_signed(). |