| 499 | static constexpr int kLUTCacheSlots = 4; |
| 500 | |
| 501 | static void build_quantize_lut(const float* codebook, unsigned char* lut) { |
| 502 | // codebook has 256 sorted entries in [-1, 1]. |
| 503 | // We discretize the [-1, 1] range into 65536 bins and find the nearest codebook entry for each. |
| 504 | // Precompute midpoints between consecutive codebook entries for nearest-neighbor lookup. |
| 505 | float midpoints[kCodebookSize - 1]; |
| 506 | for (int i = 0; i < kCodebookSize - 1; ++i) { |
| 507 | midpoints[i] = 0.5f * (codebook[i] + codebook[i + 1]); |
| 508 | } |
| 509 | |
| 510 | int code_idx = 0; |
| 511 | for (int i = 0; i < kLUTSize; ++i) { |
| 512 | // Map LUT index to normalized value in [-1, 1] |
| 513 | float val = -1.0f + (2.0f * i) / (kLUTSize - 1); |
| 514 | // Advance code_idx while the next midpoint is still below val |
| 515 | while (code_idx < kCodebookSize - 1 && midpoints[code_idx] < val) { |
| 516 | ++code_idx; |
| 517 | } |
| 518 | lut[i] = static_cast<unsigned char>(code_idx); |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | // Per-thread LUT cache with multiple slots to avoid rebuilding when alternating codebooks |
| 523 | struct LUTCache { |