Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
// gen_final.c: correct Huffman encoder table generator
// The key insight: leaf>>8 is only the FINAL flush.
// Total bits = sum of all intermediate flushes + leaf>>8.
// Only the first peek (5 bits) is NOT flushed if we get a direct hit.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "tabs_data.h"
static const int tmax[] = {
0, 1, 2, 2, 0, 3, 3, 5, 5, 5, 7, 7, 7, 15, 0, 15,
15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15
};
typedef struct { uint32_t code; uint8_t len; } henc_t;
static henc_t enc[16][16];
// Walk the minimp3 tree and return {leaf, total_bits_consumed}
// Returns -1 if cannot decode
static int walk_tree(const int16_t *codebook, uint32_t bits, int nbits,
int *total_consumed) {
uint32_t cache = (nbits < 32) ? (bits << (32 - nbits)) : bits;
int w = 5;
int leaf = codebook[cache >> (32 - w)];
int flushed = 0; // bits flushed so far
if (leaf >= 0) {
// Direct hit: only flush leaf>>8 bits (subset of the initial 5 peeked)
*total_consumed = leaf >> 8;
return leaf;
}
// Tree traversal: flush the initial 5 bits, then follow nodes
cache <<= w;
flushed = w;
while (leaf < 0) {
w = leaf & 7;
if (w == 0) return -1;
int peek = (int)(cache >> (32 - w));
int idx = peek - (leaf >> 3);
leaf = codebook[idx];
if (leaf < 0) {
// Not a leaf yet, flush these w bits and continue
cache <<= w;
flushed += w;
if (flushed > 30) return -1;
}
}
// leaf is positive: flush leaf>>8 more bits
*total_consumed = flushed + (leaf >> 8);
return leaf;
}
static void build_pair_table(int tab_num) {
int mx = tmax[tab_num];
memset(enc, 0, sizeof(enc));
const int16_t *codebook = tabs + tabindex[tab_num];
for (int len = 1; len <= 19; len++) {
for (uint32_t code = 0; code < (1u << len); code++) {
int total = 0;
int leaf = walk_tree(codebook, code, len, &total);
if (leaf < 0) continue;
if (total != len) continue;
int x = (leaf >> 4) & 0xF;
int y = leaf & 0xF;
if (x > mx || y > mx) continue;
if (enc[x][y].len == 0) {
enc[x][y].code = code;
enc[x][y].len = (uint8_t)len;
}
}
}
}
int main(void) {
// Verify completeness first
int ok = 1;
for (int t = 1; t < 32; t++) {
if (t == 0 || t == 4 || t == 14) continue;
int mx = tmax[t]; if (mx == 0) continue;
build_pair_table(t);
int dim = mx + 1, found = 0;
for (int x = 0; x < dim; x++)
for (int y = 0; y < dim; y++)
if (enc[x][y].len > 0) found++;
int expected = dim * dim;
if (found != expected) {
fprintf(stderr, "Table %2d: %d/%d INCOMPLETE\n", t, found, expected);
ok = 0;
} else {
fprintf(stderr, "Table %2d: %d/%d OK\n", t, found, expected);
}
}
if (!ok) {
fprintf(stderr, "WARNING: some tables incomplete\n");
}
// Generate output
printf("// mp3 Huffman encoder lookup tables\n");
printf("// Generated from minimp3 (CC0). ISO 11172-3 Table B.7.\n");
printf("// code = MSB first bit pattern. len = number of bits.\n");
printf("// Append sign bits for nonzero |x| and |y|.\n");
printf("// Values >= 15 use linbits extension.\n\n");
printf("static const uint8_t mp3enc_linbits[32] = {\n");
printf(" 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n");
printf(" 1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13\n};\n\n");
for (int t = 1; t < 32; t++) {
if (t == 0 || t == 4 || t == 14) continue;
int mx = tmax[t]; if (mx == 0) continue;
// Skip duplicate trees
int skip = 0;
for (int j = 1; j < t; j++) {
if (j == 4 || j == 14) continue;
if (tabindex[t] == tabindex[j] && tmax[t] == tmax[j]) {
printf("// table %d: same tree as table %d (linbits=%d)\n\n", t, j, g_linbits[t]);
skip = 1; break;
}
}
if (skip) continue;
build_pair_table(t);
int dim = mx + 1;
printf("static const uint16_t mp3enc_hcode_%d[%d][%d] = {\n", t, dim, dim);
for (int x = 0; x < dim; x++) {
printf(" {");
for (int y = 0; y < dim; y++) {
printf("0x%x", enc[x][y].code);
if (y < dim-1) printf(",");
}
printf("}%s\n", x < dim-1 ? "," : "");
}
printf("};\nstatic const uint8_t mp3enc_hlen_%d[%d][%d] = {\n", t, dim, dim);
for (int x = 0; x < dim; x++) {
printf(" {");
for (int y = 0; y < dim; y++) {
printf("%d", enc[x][y].len);
if (y < dim-1) printf(",");
}
printf("}%s\n", x < dim-1 ? "," : "");
}
printf("};\n\n");
}
// Count1 tables
for (int tbl = 0; tbl < 2; tbl++) {
const uint8_t *cb = tbl ? tab33 : tab32;
printf("// count1 table %c (count1table_select=%d)\n", 'A'+tbl, tbl);
printf("// index = v*8 + w*4 + x*2 + y\n");
uint32_t codes[16]={0}; uint8_t lens[16]={0};
for (int len = 1; len <= 10; len++) {
for (uint32_t code = 0; code < (1u<<len); code++) {
uint32_t cache = (len<32) ? (code<<(32-len)) : code;
int peek4 = (int)(cache>>28);
int leaf = cb[peek4];
int consumed;
if (leaf & 8) { consumed = leaf & 7; }
else {
int extra = leaf & 3, offset = leaf >> 3;
cache <<= 4;
int peek2 = (int)(cache >> (32-extra));
leaf = cb[offset + peek2];
consumed = leaf & 7;
}
if (consumed != len) continue;
int v=(leaf>>7)&1, w=(leaf>>6)&1, x=(leaf>>5)&1, y=(leaf>>4)&1;
int idx = v*8+w*4+x*2+y;
if (lens[idx]==0) { codes[idx]=code; lens[idx]=(uint8_t)consumed; }
}
}
printf("static const uint8_t mp3enc_count1%c_code[16] = {\n ", 'a'+tbl);
for (int i=0;i<16;i++) { printf("%d",codes[i]); if(i<15) printf(","); if(i==7) printf("\n "); }
printf("\n};\nstatic const uint8_t mp3enc_count1%c_len[16] = {\n ", 'a'+tbl);
for (int i=0;i<16;i++) { printf("%d",lens[i]); if(i<15) printf(","); if(i==7) printf("\n "); }
printf("\n};\n\n");
}
return 0;
}