Initial release
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
#pragma once
|
||||
// mp3enc-bits.h
|
||||
// Bitstream writer, frame header, side information packer.
|
||||
// Part of mp3enc. MIT license.
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
// Bitstream writer: accumulates bits MSB first into a byte buffer.
|
||||
// The encoder writes frame header, side info, and Huffman data through this.
|
||||
struct mp3enc_bs {
|
||||
uint8_t * buf; // output buffer (caller owned)
|
||||
int capacity; // total bytes available
|
||||
int byte_pos; // current byte offset
|
||||
int bit_pos; // bits used in current byte (0..7, 0 = empty)
|
||||
|
||||
void init(uint8_t * dst, int cap) {
|
||||
buf = dst;
|
||||
capacity = cap;
|
||||
byte_pos = 0;
|
||||
bit_pos = 0;
|
||||
memset(dst, 0, cap);
|
||||
}
|
||||
|
||||
// Write n bits (1..32) from val, MSB first.
|
||||
void put(uint32_t val, int n) {
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
buf[byte_pos] |= (uint8_t) (((val >> i) & 1) << (7 - bit_pos));
|
||||
bit_pos++;
|
||||
if (bit_pos == 8) {
|
||||
bit_pos = 0;
|
||||
byte_pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Total bits written so far
|
||||
int total_bits() const { return byte_pos * 8 + bit_pos; }
|
||||
|
||||
// Byte align (pad with zeros)
|
||||
void align() {
|
||||
if (bit_pos > 0) {
|
||||
byte_pos++;
|
||||
bit_pos = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Frame header: 4 bytes, fixed format for MPEG1 Layer III.
|
||||
// ISO 11172-3, clause 2.4.2.3
|
||||
struct mp3enc_header {
|
||||
int bitrate_kbps; // from mp3enc_bitrate_kbps[]
|
||||
int samplerate; // 44100, 48000, or 32000
|
||||
int mode; // 0=stereo, 1=joint, 2=dual, 3=mono
|
||||
int mode_ext; // for joint stereo: bit0=intensity, bit1=ms
|
||||
int padding; // 0 or 1
|
||||
|
||||
// Compute bitrate_index from kbps
|
||||
int bitrate_index() const {
|
||||
// Match against the Layer III table
|
||||
static const int br[] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
|
||||
for (int i = 1; i < 15; i++) {
|
||||
if (br[i] == bitrate_kbps) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0; // free format
|
||||
}
|
||||
|
||||
// Compute sampling_frequency field
|
||||
int sr_index() const {
|
||||
if (samplerate == 44100) {
|
||||
return 0;
|
||||
}
|
||||
if (samplerate == 48000) {
|
||||
return 1;
|
||||
}
|
||||
if (samplerate == 32000) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Frame size in bytes (including header)
|
||||
int frame_bytes() const { return 144 * bitrate_kbps * 1000 / samplerate + padding; }
|
||||
|
||||
// Write 4 byte header to bitstream
|
||||
void write(mp3enc_bs & bs) const {
|
||||
bs.put(0xFFF, 12); // syncword
|
||||
bs.put(1, 1); // ID = MPEG1
|
||||
bs.put(1, 2); // layer = III (01)
|
||||
bs.put(1, 1); // protection_bit = 1 (no CRC)
|
||||
bs.put(bitrate_index(), 4); // bitrate_index
|
||||
bs.put(sr_index(), 2); // sampling_frequency
|
||||
bs.put(padding, 1); // padding_bit
|
||||
bs.put(0, 1); // private_bit
|
||||
bs.put(mode, 2); // mode
|
||||
bs.put(mode_ext, 2); // mode_extension
|
||||
bs.put(0, 1); // copyright
|
||||
bs.put(1, 1); // original
|
||||
bs.put(0, 2); // emphasis = none
|
||||
}
|
||||
};
|
||||
|
||||
// Granule side information for one channel.
|
||||
// ISO 11172-3, clause 2.4.1.7
|
||||
struct mp3enc_granule_info {
|
||||
int part2_3_length; // total bits: scalefactors + Huffman data
|
||||
int big_values; // number of pairs in big_values region
|
||||
int global_gain; // quantizer step size (0..255)
|
||||
int scalefac_compress; // index into slen table (0..15)
|
||||
int block_type; // 0=normal, 1=start, 2=short, 3=stop
|
||||
int mixed_block_flag; // 1 if lower bands use long windows
|
||||
int table_select[3]; // Huffman table for each region
|
||||
int subblock_gain[3]; // gain offset per short window
|
||||
int region0_count; // sfb count in region 0
|
||||
int region1_count; // sfb count in region 1
|
||||
int preflag; // high frequency boost
|
||||
int scalefac_scale; // 0 = sqrt(2) step, 1 = 2 step
|
||||
int count1table_select; // 0 = table A, 1 = table B
|
||||
|
||||
// Scale factors (filled by quantization loop)
|
||||
int scalefac_l[21]; // long block scalefactors
|
||||
int scalefac_s[12][3]; // short block scalefactors
|
||||
};
|
||||
|
||||
// Side information for one frame.
|
||||
// Stereo: 32 bytes, mono: 17 bytes.
|
||||
struct mp3enc_side_info {
|
||||
int main_data_begin; // bit reservoir backpointer (bytes)
|
||||
int scfsi[2][4]; // scalefactor selection info per channel
|
||||
mp3enc_granule_info gr[2][2]; // [granule][channel]
|
||||
|
||||
// Write side info to bitstream (after header).
|
||||
// nch = 1 for mono, 2 for stereo/joint/dual
|
||||
void write(mp3enc_bs & bs, int nch) const {
|
||||
bs.put(main_data_begin, 9);
|
||||
|
||||
// private bits
|
||||
if (nch == 1) {
|
||||
bs.put(0, 5);
|
||||
} else {
|
||||
bs.put(0, 3);
|
||||
}
|
||||
|
||||
// scfsi
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
for (int band = 0; band < 4; band++) {
|
||||
bs.put(scfsi[ch][band], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// per granule, per channel
|
||||
for (int g = 0; g < 2; g++) {
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
const mp3enc_granule_info & gi = gr[g][ch];
|
||||
bs.put(gi.part2_3_length, 12);
|
||||
bs.put(gi.big_values, 9);
|
||||
bs.put(gi.global_gain, 8);
|
||||
bs.put(gi.scalefac_compress, 4);
|
||||
|
||||
int window_switching = (gi.block_type != 0) ? 1 : 0;
|
||||
bs.put(window_switching, 1);
|
||||
|
||||
if (window_switching) {
|
||||
bs.put(gi.block_type, 2);
|
||||
bs.put(gi.mixed_block_flag, 1);
|
||||
for (int r = 0; r < 2; r++) {
|
||||
bs.put(gi.table_select[r], 5);
|
||||
}
|
||||
for (int w = 0; w < 3; w++) {
|
||||
bs.put(gi.subblock_gain[w], 3);
|
||||
}
|
||||
} else {
|
||||
for (int r = 0; r < 3; r++) {
|
||||
bs.put(gi.table_select[r], 5);
|
||||
}
|
||||
bs.put(gi.region0_count, 4);
|
||||
bs.put(gi.region1_count, 3);
|
||||
}
|
||||
|
||||
bs.put(gi.preflag, 1);
|
||||
bs.put(gi.scalefac_scale, 1);
|
||||
bs.put(gi.count1table_select, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Write scalefactors for one granule/channel into main_data.
|
||||
// Returns number of bits written.
|
||||
static int mp3enc_write_scalefactors(mp3enc_bs & bs,
|
||||
const mp3enc_granule_info & gi,
|
||||
int gr,
|
||||
int nch_unused,
|
||||
const int scfsi[4]) {
|
||||
(void) nch_unused;
|
||||
int slen1 = mp3enc_slen[0][gi.scalefac_compress];
|
||||
int slen2 = mp3enc_slen[1][gi.scalefac_compress];
|
||||
int bits = 0;
|
||||
|
||||
// Long blocks: 21 scalefactor bands, split by scfsi
|
||||
// bands 0..5 (scfsi band 0)
|
||||
// bands 6..10 (scfsi band 1)
|
||||
// bands 11..15 (scfsi band 2)
|
||||
// bands 16..20 (scfsi band 3)
|
||||
static const int band_start[4] = { 0, 6, 11, 16 };
|
||||
static const int band_end[4] = { 6, 11, 16, 21 };
|
||||
|
||||
for (int b = 0; b < 4; b++) {
|
||||
if (gr == 0 || scfsi[b] == 0) {
|
||||
int slen = (b < 2) ? slen1 : slen2;
|
||||
for (int sfb = band_start[b]; sfb < band_end[b]; sfb++) {
|
||||
bs.put(gi.scalefac_l[sfb], slen);
|
||||
bits += slen;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
// mp3enc-filter.h
|
||||
// Polyphase analysis filterbank: 32 new PCM samples in, 32 subband samples out.
|
||||
// ISO 11172-3 clause 2.4.3.2 (encoder side, Annex C).
|
||||
// Part of mp3enc. MIT license.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
// The analysis filterbank state for one channel.
|
||||
// Holds the 512 sample FIFO and produces 32 subband outputs per call.
|
||||
struct mp3enc_filter {
|
||||
float buf[512]; // circular buffer of past PCM samples
|
||||
int off; // current write offset into buf
|
||||
|
||||
void init() {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
off = 0;
|
||||
}
|
||||
|
||||
// Feed 32 new PCM samples, produce 32 subband samples.
|
||||
// pcm: pointer to 32 float samples (mono, this channel only)
|
||||
// sb_out: output array of 32 subband values
|
||||
//
|
||||
// Algorithm (ISO 11172-3 Annex C, encoding process):
|
||||
// 1. Shift 32 new samples into the 512 sample FIFO
|
||||
// 2. Window: multiply by 512 Ci coefficients (mp3enc_enwindow)
|
||||
// 3. Partial sum: 512 windowed values -> 64 values
|
||||
// 4. Matrixing: 64 values -> 32 subband samples via DCT
|
||||
void process(const float * pcm, float * sb_out) {
|
||||
// Step 1: shift new samples into the buffer.
|
||||
// The newest sample goes at buf[off], oldest at buf[off+31].
|
||||
// We store them in reverse order so windowing is a straight multiply.
|
||||
off = (off - 32) & 511;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
buf[(off + i) & 511] = pcm[31 - i];
|
||||
}
|
||||
|
||||
// Step 2 + 3: window and partial sum.
|
||||
// z[i] = sum over j=0..7 of: buf[(off + i + 64*j) & 511] * Ci[i + 64*j]
|
||||
// This produces 64 values from the 512 windowed samples.
|
||||
float z[64];
|
||||
for (int i = 0; i < 64; i++) {
|
||||
float sum = 0.0f;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int buf_idx = (off + i + 64 * j) & 511;
|
||||
int win_idx = i + 64 * j;
|
||||
sum += buf[buf_idx] * mp3enc_enwindow[win_idx];
|
||||
}
|
||||
z[i] = sum;
|
||||
}
|
||||
|
||||
// Step 4: matrixing (ISO 11172-3, Annex C, analysis filter).
|
||||
// sb_out[k] = sum over i=0..63 of: z[i] * cos((2*k + 1) * (16 - i) * PI / 64)
|
||||
// for k = 0..31 (subbands)
|
||||
// Formula verified against ISO 11172-3 Table C.1
|
||||
for (int k = 0; k < 32; k++) {
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
float angle = (float) M_PI * (float) (2 * k + 1) * (float) (16 - i) / 64.0f;
|
||||
sum += z[i] * cosf(angle);
|
||||
}
|
||||
sb_out[k] = sum;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,357 @@
|
||||
#pragma once
|
||||
// mp3enc-huff.h
|
||||
// Huffman encoding of quantized spectral values.
|
||||
// ISO 11172-3 clause 2.4.2.7.
|
||||
// Part of mp3enc. MIT license.
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
// Count trailing zero pairs in quantized spectrum.
|
||||
// Returns number of pairs of zeros from the end.
|
||||
static int mp3enc_count_rzero(const int * ix, int n) {
|
||||
int i = n - 2;
|
||||
while (i >= 0 && ix[i] == 0 && ix[i + 1] == 0) {
|
||||
i -= 2;
|
||||
}
|
||||
return (n - i - 2) / 2;
|
||||
}
|
||||
|
||||
// Count quadruples with |val| <= 1 after big_values region.
|
||||
// start: index right after big_values*2
|
||||
// end: index right before rzero
|
||||
// Returns number of quadruples.
|
||||
static int mp3enc_count_count1(const int * ix, int start, int end) {
|
||||
int count = 0;
|
||||
int i = end - 4;
|
||||
while (i >= start) {
|
||||
if (abs(ix[i]) <= 1 && abs(ix[i + 1]) <= 1 && abs(ix[i + 2]) <= 1 && abs(ix[i + 3]) <= 1) {
|
||||
count++;
|
||||
i -= 4;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Compute bits needed to encode a pair (x, y) with a given table.
|
||||
// Returns total bits (Huffman code + linbits + sign bits).
|
||||
static int mp3enc_pair_bits(int table, int x, int y) {
|
||||
if (table == 0) {
|
||||
return 0; // table 0 = all zeros, no bits emitted
|
||||
}
|
||||
int ax = abs(x);
|
||||
int ay = abs(y);
|
||||
int bits = 0;
|
||||
|
||||
// Clamp to 15 for Huffman lookup; excess goes to linbits
|
||||
int cx = (ax < 15) ? ax : 15;
|
||||
int cy = (ay < 15) ? ay : 15;
|
||||
int lb = mp3enc_linbits[table];
|
||||
|
||||
// Get Huffman code length.
|
||||
// Tables share trees; we select the right code/len arrays based on table number.
|
||||
// For phase 1, we use tables 1, 2, 5, 6, 7, 10, 13, 15 (the common choices).
|
||||
int hlen = 0;
|
||||
switch (table) {
|
||||
case 1:
|
||||
hlen = mp3enc_hlen_1[cy][cx];
|
||||
break;
|
||||
case 2:
|
||||
hlen = mp3enc_hlen_2[cy][cx];
|
||||
break;
|
||||
case 3:
|
||||
hlen = mp3enc_hlen_3[cy][cx];
|
||||
break;
|
||||
case 5:
|
||||
hlen = mp3enc_hlen_5[cy][cx];
|
||||
break;
|
||||
case 6:
|
||||
hlen = mp3enc_hlen_6[cy][cx];
|
||||
break;
|
||||
case 7:
|
||||
hlen = mp3enc_hlen_7[cy][cx];
|
||||
break;
|
||||
case 8:
|
||||
hlen = mp3enc_hlen_8[cy][cx];
|
||||
break;
|
||||
case 9:
|
||||
hlen = mp3enc_hlen_9[cy][cx];
|
||||
break;
|
||||
case 10:
|
||||
hlen = mp3enc_hlen_10[cy][cx];
|
||||
break;
|
||||
case 11:
|
||||
hlen = mp3enc_hlen_11[cy][cx];
|
||||
break;
|
||||
case 12:
|
||||
hlen = mp3enc_hlen_12[cy][cx];
|
||||
break;
|
||||
case 13:
|
||||
hlen = mp3enc_hlen_13[cy][cx];
|
||||
break;
|
||||
case 15:
|
||||
hlen = mp3enc_hlen_15[cy][cx];
|
||||
break;
|
||||
// 16..23 use table 16 tree; 24..31 use table 24 tree
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
hlen = mp3enc_hlen_16[cy][cx];
|
||||
break;
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
hlen = mp3enc_hlen_24[cy][cx];
|
||||
break;
|
||||
default:
|
||||
return 9999; // invalid table
|
||||
}
|
||||
|
||||
if (hlen == 0 && (cx || cy)) {
|
||||
return 9999; // no valid code
|
||||
}
|
||||
|
||||
bits = hlen;
|
||||
if (ax >= 15) {
|
||||
bits += lb; // linbits for x
|
||||
}
|
||||
if (ay >= 15) {
|
||||
bits += lb; // linbits for y
|
||||
}
|
||||
if (ax > 0) {
|
||||
bits += 1; // sign bit for x
|
||||
}
|
||||
if (ay > 0) {
|
||||
bits += 1; // sign bit for y
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Write a Huffman coded pair to the bitstream.
|
||||
static void mp3enc_write_pair(mp3enc_bs & bs, int table, int x, int y) {
|
||||
if (table == 0) {
|
||||
return; // table 0 = all zeros, nothing to write
|
||||
}
|
||||
int ax = abs(x);
|
||||
int ay = abs(y);
|
||||
int cx = (ax < 15) ? ax : 15;
|
||||
int cy = (ay < 15) ? ay : 15;
|
||||
int lb = mp3enc_linbits[table];
|
||||
|
||||
// Get Huffman code and length
|
||||
uint16_t code = 0;
|
||||
int len = 0;
|
||||
switch (table) {
|
||||
case 1:
|
||||
code = mp3enc_hcode_1[cy][cx];
|
||||
len = mp3enc_hlen_1[cy][cx];
|
||||
break;
|
||||
case 2:
|
||||
code = mp3enc_hcode_2[cy][cx];
|
||||
len = mp3enc_hlen_2[cy][cx];
|
||||
break;
|
||||
case 3:
|
||||
code = mp3enc_hcode_3[cy][cx];
|
||||
len = mp3enc_hlen_3[cy][cx];
|
||||
break;
|
||||
case 5:
|
||||
code = mp3enc_hcode_5[cy][cx];
|
||||
len = mp3enc_hlen_5[cy][cx];
|
||||
break;
|
||||
case 6:
|
||||
code = mp3enc_hcode_6[cy][cx];
|
||||
len = mp3enc_hlen_6[cy][cx];
|
||||
break;
|
||||
case 7:
|
||||
code = mp3enc_hcode_7[cy][cx];
|
||||
len = mp3enc_hlen_7[cy][cx];
|
||||
break;
|
||||
case 8:
|
||||
code = mp3enc_hcode_8[cy][cx];
|
||||
len = mp3enc_hlen_8[cy][cx];
|
||||
break;
|
||||
case 9:
|
||||
code = mp3enc_hcode_9[cy][cx];
|
||||
len = mp3enc_hlen_9[cy][cx];
|
||||
break;
|
||||
case 10:
|
||||
code = mp3enc_hcode_10[cy][cx];
|
||||
len = mp3enc_hlen_10[cy][cx];
|
||||
break;
|
||||
case 11:
|
||||
code = mp3enc_hcode_11[cy][cx];
|
||||
len = mp3enc_hlen_11[cy][cx];
|
||||
break;
|
||||
case 12:
|
||||
code = mp3enc_hcode_12[cy][cx];
|
||||
len = mp3enc_hlen_12[cy][cx];
|
||||
break;
|
||||
case 13:
|
||||
code = mp3enc_hcode_13[cy][cx];
|
||||
len = mp3enc_hlen_13[cy][cx];
|
||||
break;
|
||||
case 15:
|
||||
code = mp3enc_hcode_15[cy][cx];
|
||||
len = mp3enc_hlen_15[cy][cx];
|
||||
break;
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
code = mp3enc_hcode_16[cy][cx];
|
||||
len = mp3enc_hlen_16[cy][cx];
|
||||
break;
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
code = mp3enc_hcode_24[cy][cx];
|
||||
len = mp3enc_hlen_24[cy][cx];
|
||||
break;
|
||||
}
|
||||
|
||||
bs.put(code, len);
|
||||
if (cx == 15 && lb > 0) {
|
||||
bs.put(ax - 15, lb);
|
||||
}
|
||||
if (ax > 0) {
|
||||
bs.put(x < 0 ? 1 : 0, 1);
|
||||
}
|
||||
if (cy == 15 && lb > 0) {
|
||||
bs.put(ay - 15, lb);
|
||||
}
|
||||
if (ay > 0) {
|
||||
bs.put(y < 0 ? 1 : 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Write count1 region (quadruples of {-1, 0, 1}).
|
||||
static void mp3enc_write_count1(mp3enc_bs & bs, const int * ix, int start, int count, int table_sel) {
|
||||
const uint8_t * ctab_code = table_sel ? mp3enc_count1b_code : mp3enc_count1a_code;
|
||||
const uint8_t * ctab_len = table_sel ? mp3enc_count1b_len : mp3enc_count1a_len;
|
||||
|
||||
for (int q = 0; q < count; q++) {
|
||||
int i = start + q * 4;
|
||||
int v = abs(ix[i]);
|
||||
int w = abs(ix[i + 1]);
|
||||
int x = abs(ix[i + 2]);
|
||||
int y = abs(ix[i + 3]);
|
||||
int idx = v * 8 + w * 4 + x * 2 + y;
|
||||
|
||||
bs.put(ctab_code[idx], ctab_len[idx]);
|
||||
if (v) {
|
||||
bs.put(ix[i] < 0 ? 1 : 0, 1);
|
||||
}
|
||||
if (w) {
|
||||
bs.put(ix[i + 1] < 0 ? 1 : 0, 1);
|
||||
}
|
||||
if (x) {
|
||||
bs.put(ix[i + 2] < 0 ? 1 : 0, 1);
|
||||
}
|
||||
if (y) {
|
||||
bs.put(ix[i + 3] < 0 ? 1 : 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose the best Huffman table for a region of pairs.
|
||||
// Tries all candidate tables and returns the one with fewest bits.
|
||||
static int mp3enc_choose_table(const int * ix, int start, int count) {
|
||||
if (count <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find max absolute value in this region
|
||||
int maxval = 0;
|
||||
for (int i = start; i < start + count * 2; i++) {
|
||||
int a = abs(ix[i]);
|
||||
if (a > maxval) {
|
||||
maxval = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxval == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Candidate tables grouped by max entry:
|
||||
// max 1: tables 1
|
||||
// max 2: tables 2, 3
|
||||
// max 3: tables 5, 6
|
||||
// max 5: tables 7, 8, 9
|
||||
// max 7: tables 10, 11, 12
|
||||
// max 15: tables 13, 15
|
||||
// max >15: tables 16..31 (with linbits)
|
||||
static const int candidates[][8] = {
|
||||
{ 1, 0 }, // maxval = 1
|
||||
{ 2, 3, 0 }, // maxval = 2
|
||||
{ 5, 6, 0 }, // maxval = 3
|
||||
{ 7, 8, 9, 0 }, // maxval = 4..5
|
||||
{ 7, 8, 9, 0 }, // (same)
|
||||
{ 10, 11, 12, 0 }, // maxval = 6..7
|
||||
{ 10, 11, 12, 0 }, // (same)
|
||||
{ 13, 15, 0 }, // maxval = 8..15
|
||||
};
|
||||
// For values > 15, need linbits tables
|
||||
static const int linbit_tables[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0 };
|
||||
|
||||
const int * cands;
|
||||
if (maxval <= 1) {
|
||||
cands = candidates[0];
|
||||
} else if (maxval <= 2) {
|
||||
cands = candidates[1];
|
||||
} else if (maxval <= 3) {
|
||||
cands = candidates[2];
|
||||
} else if (maxval <= 5) {
|
||||
cands = candidates[3];
|
||||
} else if (maxval <= 7) {
|
||||
cands = candidates[5];
|
||||
} else if (maxval <= 15) {
|
||||
cands = candidates[7];
|
||||
} else {
|
||||
cands = linbit_tables;
|
||||
}
|
||||
|
||||
int best_table = cands[0];
|
||||
int best_bits = 999999;
|
||||
|
||||
for (int c = 0; cands[c] != 0; c++) {
|
||||
int t = cands[c];
|
||||
// For linbits tables, skip if linbits too small for our max value
|
||||
if (maxval > 15 && mp3enc_linbits[t] > 0) {
|
||||
int max_encodable = 15 + (1 << mp3enc_linbits[t]) - 1;
|
||||
if (maxval > max_encodable) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
for (int p = 0; p < count; p++) {
|
||||
total += mp3enc_pair_bits(t, ix[start + p * 2], ix[start + p * 2 + 1]);
|
||||
}
|
||||
if (total < best_bits) {
|
||||
best_bits = total;
|
||||
best_table = t;
|
||||
}
|
||||
}
|
||||
return best_table;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
// mp3enc-mdct.h
|
||||
// Forward MDCT for the MP3 encoder: 36 subband samples -> 18 frequency lines.
|
||||
// Window and MDCT are combined into a single step (ISO 11172-3 Annex C).
|
||||
// Part of mp3enc. MIT license.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
// Forward MDCT-36 for long blocks.
|
||||
// in[36] = prev[18] + cur[18] (raw subband samples)
|
||||
// out[18] = MDCT frequency coefficients
|
||||
//
|
||||
// Formula (ISO 11172-3 Annex C):
|
||||
// out[k] = (1/9) * sum(n=0..35) in[n] * sin(pi/36*(n+0.5)) * cos(pi/72*(2n+19)*(2k+1))
|
||||
static void mp3enc_mdct36(const float * in, float * out) {
|
||||
for (int k = 0; k < 18; k++) {
|
||||
float sum = 0.0f;
|
||||
for (int n = 0; n < 36; n++) {
|
||||
float w = sinf((float) M_PI / 36.0f * ((float) n + 0.5f));
|
||||
float c = cosf((float) M_PI / 72.0f * (float) (2 * n + 19) * (float) (2 * k + 1));
|
||||
sum += in[n] * w * c;
|
||||
}
|
||||
out[k] = sum * (1.0f / 9.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Alias reduction butterfly between adjacent subbands.
|
||||
// Applied after MDCT, before quantization.
|
||||
// ISO 11172-3 Table B.9 coefficients (from minimp3 CC0).
|
||||
//
|
||||
// For each pair of adjacent bands (band, band+1):
|
||||
// mdct[band][17-i] and mdct[band+1][i] are butterflied with cs/ca.
|
||||
static void mp3enc_alias_reduce(float * mdct_out) {
|
||||
for (int band = 1; band < 32; band++) {
|
||||
float * a = mdct_out + (band - 1) * 18; // previous band
|
||||
float * b = mdct_out + band * 18; // current band
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float u = a[17 - i];
|
||||
float d = b[i];
|
||||
a[17 - i] = u * mp3enc_cs[i] - d * mp3enc_ca[i];
|
||||
b[i] = d * mp3enc_cs[i] + u * mp3enc_ca[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all 32 subbands for one granule (long blocks only).
|
||||
// sb_samples layout: prev_gr[32][18] and cur_gr[32][18] (band major).
|
||||
// mdct_out[576]: output frequency lines (32 subbands * 18 lines)
|
||||
static void mp3enc_mdct_granule(const float sb_prev[32][18], const float sb_cur[32][18], float * mdct_out) {
|
||||
for (int band = 0; band < 32; band++) {
|
||||
float mdct_in[36];
|
||||
for (int k = 0; k < 18; k++) {
|
||||
mdct_in[k] = sb_prev[band][k];
|
||||
mdct_in[k + 18] = sb_cur[band][k];
|
||||
}
|
||||
mp3enc_mdct36(mdct_in, mdct_out + band * 18);
|
||||
}
|
||||
|
||||
mp3enc_alias_reduce(mdct_out);
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
#pragma once
|
||||
// mp3enc-psy.h
|
||||
// Psychoacoustic model for MP3 encoding.
|
||||
// Computes masking thresholds per scalefactor band from MDCT coefficients.
|
||||
//
|
||||
// Based on ISO 11172-3 Annex D principles:
|
||||
// - Absolute threshold of hearing (ATH)
|
||||
// - Bark-domain asymmetric spreading function (Schroeder)
|
||||
// - Tonal vs noise masking detection (spectral flatness)
|
||||
// - Variable masking offset: tonal -14.5 dB, noise -5.5 dB
|
||||
//
|
||||
// Constants from ISO 11172-3 Annex D and Zwicker (1961).
|
||||
// MIT license.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// Number of scalefactor bands for long blocks
|
||||
#define MP3ENC_PSY_SFB_MAX 21
|
||||
|
||||
// Absolute threshold of hearing in dB SPL.
|
||||
// ISO formula: ATH(f) = 3.64*(f/1000)^-0.8 - 6.5*exp(-0.6*(f/1000-3.3)^2) + 1e-3*(f/1000)^4
|
||||
// Minimum clamped at -20 dB to avoid numerical issues.
|
||||
static inline float mp3enc_ath_db(float freq_hz) {
|
||||
if (freq_hz < 10.0f) {
|
||||
freq_hz = 10.0f;
|
||||
}
|
||||
float fk = freq_hz * 0.001f;
|
||||
float ath = 3.64f * powf(fk, -0.8f) - 6.5f * expf(-0.6f * (fk - 3.3f) * (fk - 3.3f)) + 0.001f * fk * fk * fk * fk;
|
||||
if (ath < -20.0f) {
|
||||
ath = -20.0f;
|
||||
}
|
||||
return ath;
|
||||
}
|
||||
|
||||
// Convert frequency in Hz to Bark scale.
|
||||
// Traunmuller (1990) approximation, accurate to ~0.05 Bark.
|
||||
static inline float mp3enc_hz_to_bark(float f) {
|
||||
if (f < 1.0f) {
|
||||
f = 1.0f;
|
||||
}
|
||||
return 13.0f * atanf(0.00076f * f) + 3.5f * atanf((f / 7500.0f) * (f / 7500.0f));
|
||||
}
|
||||
|
||||
// Schroeder spreading function in dB.
|
||||
// dz = bark distance from masker to maskee (positive = maskee above masker).
|
||||
// This models the asymmetric excitation pattern of the basilar membrane:
|
||||
// steep below the masker (~27 dB/Bark), shallow above (~10-25 dB/Bark).
|
||||
// From Schroeder, Atal, Hall (1979).
|
||||
static inline float mp3enc_spreading_db(float dz) {
|
||||
float t = dz + 0.474f;
|
||||
return 15.81f + 7.5f * t - 17.5f * sqrtf(1.0f + t * t);
|
||||
}
|
||||
|
||||
// Psychoacoustic model state.
|
||||
struct mp3enc_psy {
|
||||
// Output: allowed distortion energy per SFB
|
||||
float xmin[MP3ENC_PSY_SFB_MAX];
|
||||
|
||||
// Output: perceptual entropy for this granule/channel (ISO 11172-3 Annex D).
|
||||
// Higher PE = more complex signal = needs more bits.
|
||||
float pe;
|
||||
|
||||
// Forward masking: previous granule's masking energy (per channel)
|
||||
float prev_mask[2][MP3ENC_PSY_SFB_MAX];
|
||||
|
||||
// Pre-echo control: 2 previous granules of spread energy (per channel).
|
||||
// Used to prevent masking threshold from rising too fast on transients
|
||||
// (ISO 11172-3 Annex D, l3psy.c lines 610-616).
|
||||
float nb_1[2][MP3ENC_PSY_SFB_MAX]; // previous granule spread energy
|
||||
float nb_2[2][MP3ENC_PSY_SFB_MAX]; // 2 granules ago spread energy
|
||||
|
||||
// Precomputed per-SFB data (set once per sample rate)
|
||||
float ath_energy[3][MP3ENC_PSY_SFB_MAX]; // [sr_index][sfb]: ATH in linear power
|
||||
float sfb_bark[3][MP3ENC_PSY_SFB_MAX]; // [sr_index][sfb]: center freq in Bark
|
||||
bool ath_valid;
|
||||
|
||||
void init() {
|
||||
ath_valid = false;
|
||||
pe = 0.0f;
|
||||
memset(xmin, 0, sizeof(xmin));
|
||||
memset(prev_mask, 0, sizeof(prev_mask));
|
||||
memset(nb_1, 0, sizeof(nb_1));
|
||||
memset(nb_2, 0, sizeof(nb_2));
|
||||
}
|
||||
|
||||
// Precompute ATH energy and Bark positions per SFB.
|
||||
// Must be called once before compute().
|
||||
void init_ath(int sr_index, const uint8_t * sfb_table, int sample_rate) {
|
||||
// MDCT has 576 lines covering 0 to samplerate/2.
|
||||
// Each line represents a frequency bin of width samplerate / (2*576).
|
||||
float freq_per_line = (float) sample_rate / (2.0f * 576.0f);
|
||||
|
||||
int pos = 0;
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
int width = sfb_table[sfb];
|
||||
if (width == 0) {
|
||||
ath_energy[sr_index][sfb] = 1e-20f;
|
||||
sfb_bark[sr_index][sfb] = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Center frequency of this SFB
|
||||
float center_freq = ((float) pos + (float) width * 0.5f) * freq_per_line;
|
||||
sfb_bark[sr_index][sfb] = mp3enc_hz_to_bark(center_freq);
|
||||
|
||||
// ATH: minimum of all lines in the band (most permissive)
|
||||
float ath_min_db = 200.0f;
|
||||
for (int j = 0; j < width; j++) {
|
||||
float freq = ((float) (pos + j) + 0.5f) * freq_per_line;
|
||||
float db = mp3enc_ath_db(freq);
|
||||
if (db < ath_min_db) {
|
||||
ath_min_db = db;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert dB SPL to linear power, scaled by band width.
|
||||
// Reference at 120 dB SPL (tuned empirically). A higher reference
|
||||
// makes the ATH floor less dominant relative to the spreading
|
||||
// function, so bits are spent on perceptual masking rather than
|
||||
// fighting the absolute hearing threshold in quiet passages.
|
||||
float ath_linear = powf(10.0f, (ath_min_db - 120.0f) * 0.1f) * (float) width;
|
||||
ath_energy[sr_index][sfb] = ath_linear;
|
||||
|
||||
pos += width;
|
||||
}
|
||||
ath_valid = true;
|
||||
}
|
||||
|
||||
// Compute masking thresholds for one granule/channel.
|
||||
//
|
||||
// Algorithm:
|
||||
// 1. Compute energy per SFB from MDCT coefficients
|
||||
// 2. Estimate tonality per SFB (spectral flatness measure)
|
||||
// 3. Compute masking offset per SFB based on tonality
|
||||
// 4. Apply Bark-domain spreading function
|
||||
// 5. Combine spread masking with ATH
|
||||
//
|
||||
// mdct: 576 MDCT coefficients (after MS stereo if applicable)
|
||||
// sfb_table: SFB widths for this sample rate
|
||||
// sr_index: sample rate index
|
||||
void compute(const float * mdct, const uint8_t * sfb_table, int sr_index, int ch = 0) {
|
||||
float energy[MP3ENC_PSY_SFB_MAX];
|
||||
float tonality[MP3ENC_PSY_SFB_MAX];
|
||||
|
||||
// Step 1: compute energy per SFB
|
||||
int pos = 0;
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
int width = sfb_table[sfb];
|
||||
float e = 0.0f;
|
||||
for (int j = 0; j < width; j++) {
|
||||
float x = mdct[pos + j];
|
||||
e += x * x;
|
||||
}
|
||||
energy[sfb] = e;
|
||||
pos += width;
|
||||
}
|
||||
|
||||
// Step 2: estimate tonality per SFB using spectral flatness measure (SFM).
|
||||
// SFM = geometric_mean(power) / arithmetic_mean(power)
|
||||
// SFM = 1.0 for flat noise, SFM -> 0 for a single tone.
|
||||
// We use log domain to avoid overflow: log(geometric_mean) = mean(log(power)).
|
||||
pos = 0;
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
int width = sfb_table[sfb];
|
||||
if (width == 0 || energy[sfb] < 1e-20f) {
|
||||
tonality[sfb] = 0.5f; // default: assume mixed
|
||||
pos += width;
|
||||
continue;
|
||||
}
|
||||
|
||||
float log_sum = 0.0f;
|
||||
float arith = 0.0f;
|
||||
int n_active = 0;
|
||||
for (int j = 0; j < width; j++) {
|
||||
float p = mdct[pos + j] * mdct[pos + j];
|
||||
if (p > 1e-20f) {
|
||||
log_sum += logf(p);
|
||||
n_active++;
|
||||
}
|
||||
arith += p;
|
||||
}
|
||||
|
||||
if (n_active < 2) {
|
||||
// Single line or silence: treat as tonal
|
||||
tonality[sfb] = 0.0f;
|
||||
} else {
|
||||
float geom_log = log_sum / (float) n_active;
|
||||
float arith_mean = arith / (float) n_active;
|
||||
// SFM in log domain: log(geom/arith) = geom_log - log(arith)
|
||||
float sfm_log = geom_log - logf(arith_mean);
|
||||
// sfm_log is <= 0. For flat spectrum sfm_log ~ 0, for tonal sfm_log << 0.
|
||||
// Map to tonality index alpha in [0,1]:
|
||||
// alpha = min(sfm_log / log(0.01), 1.0)
|
||||
// log(0.01) = -4.605; so if sfm_log < -4.6 we consider it fully tonal.
|
||||
float alpha = sfm_log / -4.605f;
|
||||
if (alpha < 0.0f) {
|
||||
alpha = 0.0f;
|
||||
}
|
||||
if (alpha > 1.0f) {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
tonality[sfb] = alpha; // 0 = noise, 1 = tonal
|
||||
}
|
||||
pos += width;
|
||||
}
|
||||
|
||||
// Step 3: compute masking offset per SFB.
|
||||
// TMN/NMT from ISO 11172-3, relaxed empirically for 128kbps.
|
||||
// TMN=13.0 (tonal masking noise), NMT=4.5 (noise masking tone).
|
||||
float offset_linear[MP3ENC_PSY_SFB_MAX];
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
float alpha = tonality[sfb];
|
||||
float offset_db = alpha * 13.0f + (1.0f - alpha) * 4.5f;
|
||||
offset_linear[sfb] = powf(10.0f, -offset_db * 0.1f);
|
||||
}
|
||||
|
||||
// Step 4: Bark-domain spreading function.
|
||||
// For each target SFB, sum the spread contributions from all source SFBs.
|
||||
// The spreading function is asymmetric: steep below, shallow above.
|
||||
float spread_energy[MP3ENC_PSY_SFB_MAX];
|
||||
for (int j = 0; j < MP3ENC_PSY_SFB_MAX; j++) {
|
||||
float sum = 0.0f;
|
||||
float bark_j = sfb_bark[sr_index][j];
|
||||
|
||||
for (int i = 0; i < MP3ENC_PSY_SFB_MAX; i++) {
|
||||
if (energy[i] < 1e-20f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float bark_i = sfb_bark[sr_index][i];
|
||||
float dz_raw = bark_j - bark_i;
|
||||
|
||||
// Asymmetric spreading (ISO 11172-3 psy model 2, L3para_read).
|
||||
// Upward masking (dz > 0): gentle slope, low freqs mask highs well.
|
||||
// Downward masking (dz < 0): steep slope, highs mask lows poorly.
|
||||
float dz = (dz_raw >= 0.0f) ? dz_raw * 1.35f : dz_raw * 2.7f;
|
||||
|
||||
// Spreading function value in dB
|
||||
float sf_db = mp3enc_spreading_db(dz);
|
||||
|
||||
// Only apply if spreading is above -60 dB (optimization)
|
||||
if (sf_db < -60.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float sf_linear = powf(10.0f, sf_db * 0.1f);
|
||||
sum += energy[i] * sf_linear;
|
||||
}
|
||||
spread_energy[j] = sum;
|
||||
}
|
||||
|
||||
// Step 5: combine spreading + offset, then apply pre-echo control.
|
||||
// Pre-echo (ISO 11172-3 Annex D): prevent threshold from rising too fast
|
||||
// on transients. Clamp current nb by 2x previous and 16x two-back.
|
||||
// xmin = max(ath, min(nb, 2*nb_1, 16*nb_2))
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
float nb = spread_energy[sfb] * offset_linear[sfb];
|
||||
|
||||
// Pre-echo clamp: use history to limit sudden threshold rises
|
||||
float clamped = nb;
|
||||
float lim1 = 2.0f * nb_1[ch][sfb];
|
||||
float lim2 = 16.0f * nb_2[ch][sfb];
|
||||
if (lim1 > 0.0f && lim1 < clamped) {
|
||||
clamped = lim1;
|
||||
}
|
||||
if (lim2 > 0.0f && lim2 < clamped) {
|
||||
clamped = lim2;
|
||||
}
|
||||
|
||||
// Update history (store UN-clamped nb for future reference)
|
||||
nb_2[ch][sfb] = nb_1[ch][sfb];
|
||||
nb_1[ch][sfb] = nb;
|
||||
|
||||
// ATH floor
|
||||
float ath = ath_energy[sr_index][sfb];
|
||||
xmin[sfb] = (clamped > ath) ? clamped : ath;
|
||||
}
|
||||
|
||||
// Step 6: forward masking (temporal).
|
||||
// A loud granule raises the masking threshold for the next granule.
|
||||
// At 44.1kHz one granule = 13ms. Forward masking decays ~12dB over 13ms.
|
||||
// Decay factor: 10^(-12/10) = ~0.063.
|
||||
static const float fwd_decay = 0.063f;
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
float fwd = prev_mask[ch][sfb] * fwd_decay;
|
||||
if (fwd > xmin[sfb]) {
|
||||
xmin[sfb] = fwd;
|
||||
}
|
||||
// Save current mask (spread_energy, not xmin) for next granule
|
||||
prev_mask[ch][sfb] = spread_energy[sfb];
|
||||
}
|
||||
|
||||
// Step 7: perceptual entropy (ISO 11172-3 Annex D).
|
||||
// PE = sum of width * log(energy/threshold) for bands where energy > threshold.
|
||||
// Used by the bit reservoir to give more bits to complex granules.
|
||||
pe = 0.0f;
|
||||
for (int sfb = 0; sfb < MP3ENC_PSY_SFB_MAX; sfb++) {
|
||||
if (energy[sfb] > xmin[sfb] && xmin[sfb] > 1e-20f) {
|
||||
pe += (float) sfb_table[sfb] * logf(energy[sfb] / xmin[sfb]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,650 @@
|
||||
#pragma once
|
||||
// mp3enc-quant.h
|
||||
// Quantization: inner loop (global_gain search) + outer loop (scalefactor iteration).
|
||||
// ISO 11172-3 Annex C, encoding process.
|
||||
// Part of mp3enc. MIT license.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
// Quantize one MDCT coefficient using the MP3 power law quantizer.
|
||||
// xr = input MDCT value (float)
|
||||
// istep = 2^(-3/16 * (global_gain - 210))
|
||||
// Returns quantized integer (always >= 0; sign stored separately).
|
||||
static inline int mp3enc_quantize_value(float xr, float istep) {
|
||||
float ax = fabsf(xr);
|
||||
// ix = nint(ax^0.75 * istep)
|
||||
float val = sqrtf(ax * sqrtf(ax)) * istep;
|
||||
if (val > 8191.0f) {
|
||||
return 8191;
|
||||
}
|
||||
int ix = (int) (val + 0.36f); // rounding bias for better SNR
|
||||
return ix;
|
||||
}
|
||||
|
||||
// Quantize 576 MDCT coefficients with per-band scalefactors.
|
||||
// The scalefactor amplifies each band's coefficients before quantization,
|
||||
// giving finer resolution to bands that need it.
|
||||
//
|
||||
// Decoder (minimp3) dequantization:
|
||||
// scf_shift = scalefac_scale + 1
|
||||
// band_gain = 2^(-(sf << scf_shift) / 4)
|
||||
// which gives 2^(-sf/2) for scalefac_scale=0, 2^(-sf) for scalefac_scale=1
|
||||
//
|
||||
// Encoder compensates: sfb_amp = 2^(ss * sf) where ss = 0.5 or 1.0
|
||||
static void mp3enc_quantize_sfb(const float * xr,
|
||||
int * ix,
|
||||
int global_gain,
|
||||
const int * scalefac,
|
||||
int scalefac_scale,
|
||||
int preflag,
|
||||
const uint8_t * sfb_table) {
|
||||
float istep = powf(2.0f, -0.1875f * (float) (global_gain - 210));
|
||||
float ss = scalefac_scale ? 1.0f : 0.5f;
|
||||
|
||||
int pos = 0;
|
||||
for (int sfb = 0; sfb_table[sfb] != 0 && pos < 576; sfb++) {
|
||||
int width = sfb_table[sfb];
|
||||
|
||||
int sf = scalefac[sfb] + (preflag ? mp3enc_pretab[sfb] : 0);
|
||||
float sfb_amp = (sf > 0) ? powf(2.0f, ss * (float) sf) : 1.0f;
|
||||
|
||||
for (int j = 0; j < width && pos < 576; j++, pos++) {
|
||||
float xr_adj = fabsf(xr[pos]) * sfb_amp;
|
||||
float val = sqrtf(xr_adj * sqrtf(xr_adj)) * istep;
|
||||
int q;
|
||||
if (val > 8191.0f) {
|
||||
q = 8191;
|
||||
} else {
|
||||
q = (int) (val + 0.36f);
|
||||
}
|
||||
ix[pos] = (xr[pos] >= 0.0f) ? q : -q;
|
||||
}
|
||||
}
|
||||
while (pos < 576) {
|
||||
ix[pos++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple quantize without scalefactors (Phase 1 compatible).
|
||||
// Kept for the initial global_gain search before outer loop kicks in.
|
||||
static void mp3enc_quantize(const float * xr, int * ix, int global_gain) {
|
||||
float istep = powf(2.0f, -0.1875f * (float) (global_gain - 210));
|
||||
for (int i = 0; i < 576; i++) {
|
||||
int q = mp3enc_quantize_value(xr[i], istep);
|
||||
ix[i] = (xr[i] >= 0.0f) ? q : -q;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute quantization noise energy per SFB.
|
||||
// Noise = sum((xr[i] - dequant(ix[i]))^2) for each band.
|
||||
// Dequant matches minimp3: xr = |ix|^(4/3) * 2^((gg-210)/4) * 2^(-ss*sf)
|
||||
// where ss = 0.5 (scalefac_scale=0) or 1.0 (scalefac_scale=1).
|
||||
static void mp3enc_calc_noise(const float * xr,
|
||||
const int * ix,
|
||||
int global_gain,
|
||||
const int * scalefac,
|
||||
int scalefac_scale,
|
||||
int preflag,
|
||||
const uint8_t * sfb_table,
|
||||
float * noise) {
|
||||
float step = powf(2.0f, 0.25f * (float) (global_gain - 210));
|
||||
float ss = scalefac_scale ? 1.0f : 0.5f;
|
||||
|
||||
int pos = 0;
|
||||
for (int sfb = 0; sfb_table[sfb] != 0 && pos < 576; sfb++) {
|
||||
int width = sfb_table[sfb];
|
||||
int sf = scalefac[sfb] + (preflag ? mp3enc_pretab[sfb] : 0);
|
||||
float sfb_gain = (sf > 0) ? powf(2.0f, -ss * (float) sf) : 1.0f;
|
||||
|
||||
float n = 0.0f;
|
||||
for (int j = 0; j < width && pos < 576; j++, pos++) {
|
||||
// Dequantize
|
||||
int aix = abs(ix[pos]);
|
||||
float dequant = (float) aix;
|
||||
// |ix|^(4/3): use pow for accuracy
|
||||
if (aix > 0) {
|
||||
dequant = powf((float) aix, 4.0f / 3.0f) * step * sfb_gain;
|
||||
} else {
|
||||
dequant = 0.0f;
|
||||
}
|
||||
if (ix[pos] < 0) {
|
||||
dequant = -dequant;
|
||||
}
|
||||
float diff = xr[pos] - dequant;
|
||||
n += diff * diff;
|
||||
}
|
||||
noise[sfb] = n;
|
||||
}
|
||||
}
|
||||
|
||||
// Count total Huffman bits for 576 quantized values.
|
||||
// Also fills out granule info: big_values, table_select, count1, etc.
|
||||
// Returns total bits for Huffman data (not including scalefactors).
|
||||
static int mp3enc_count_bits(const int * ix, mp3enc_granule_info & gi, const uint8_t * sfb_table, int sr_index) {
|
||||
(void) sr_index;
|
||||
|
||||
// Find the three regions: big_values, count1, rzero
|
||||
int rzero_pairs = mp3enc_count_rzero(ix, 576);
|
||||
int nz_end = 576 - rzero_pairs * 2;
|
||||
|
||||
// count1: quadruples with |val| <= 1, scanning from end of nonzero region
|
||||
int c1_start = nz_end;
|
||||
int c1_count = 0;
|
||||
{
|
||||
int i = nz_end - 4;
|
||||
while (i >= 0 && abs(ix[i]) <= 1 && abs(ix[i + 1]) <= 1 && abs(ix[i + 2]) <= 1 && abs(ix[i + 3]) <= 1) {
|
||||
c1_start = i;
|
||||
c1_count++;
|
||||
i -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
gi.big_values = c1_start / 2;
|
||||
|
||||
int bv_end = c1_start; // end of big_values region (pair aligned)
|
||||
|
||||
// Region boundaries from SFB table.
|
||||
int region_end[3] = { 0, 0, bv_end };
|
||||
|
||||
if (gi.block_type == 0) {
|
||||
// Try a few region0_count values and pick the best.
|
||||
int total_sfb = 0;
|
||||
int sfb_acc[22] = {};
|
||||
{
|
||||
int acc = 0;
|
||||
for (int sfb = 0; sfb < 22; sfb++) {
|
||||
acc += sfb_table[sfb];
|
||||
sfb_acc[sfb] = acc;
|
||||
if (acc <= bv_end) {
|
||||
total_sfb = sfb + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int best_r0 = 7, best_r1 = 0, best_rbits = 999999;
|
||||
for (int r0t = 5; r0t < 11 && r0t < total_sfb; r0t++) {
|
||||
int r1t = total_sfb - r0t - 1;
|
||||
if (r1t < 0) {
|
||||
r1t = 0;
|
||||
}
|
||||
if (r1t > 7) {
|
||||
r1t = 7;
|
||||
}
|
||||
int re0 = (sfb_acc[r0t] < bv_end) ? sfb_acc[r0t] : bv_end;
|
||||
int sfb1 = r0t + r1t + 1;
|
||||
if (sfb1 > 21) {
|
||||
sfb1 = 21;
|
||||
}
|
||||
int re1 = (sfb_acc[sfb1] < bv_end) ? sfb_acc[sfb1] : bv_end;
|
||||
|
||||
int t0 = mp3enc_choose_table(ix, 0, re0 / 2);
|
||||
int t1 = mp3enc_choose_table(ix, re0, (re1 - re0) / 2);
|
||||
int t2 = mp3enc_choose_table(ix, re1, (bv_end - re1) / 2);
|
||||
int rbits = 0;
|
||||
for (int i = 0; i < re0; i += 2) {
|
||||
rbits += mp3enc_pair_bits(t0, ix[i], ix[i + 1]);
|
||||
}
|
||||
for (int i = re0; i < re1; i += 2) {
|
||||
rbits += mp3enc_pair_bits(t1, ix[i], ix[i + 1]);
|
||||
}
|
||||
for (int i = re1; i < bv_end; i += 2) {
|
||||
rbits += mp3enc_pair_bits(t2, ix[i], ix[i + 1]);
|
||||
}
|
||||
if (rbits < best_rbits) {
|
||||
best_rbits = rbits;
|
||||
best_r0 = r0t;
|
||||
best_r1 = r1t;
|
||||
}
|
||||
}
|
||||
gi.region0_count = best_r0;
|
||||
gi.region1_count = best_r1;
|
||||
|
||||
// Compute region end positions
|
||||
{
|
||||
int acc = 0;
|
||||
for (int sfb = 0; sfb <= gi.region0_count; sfb++) {
|
||||
acc += sfb_table[sfb];
|
||||
}
|
||||
region_end[0] = (acc < bv_end) ? acc : bv_end;
|
||||
}
|
||||
{
|
||||
int acc = 0;
|
||||
for (int sfb = 0; sfb <= gi.region0_count + gi.region1_count + 1; sfb++) {
|
||||
acc += sfb_table[sfb];
|
||||
}
|
||||
region_end[1] = (acc < bv_end) ? acc : bv_end;
|
||||
}
|
||||
region_end[2] = bv_end;
|
||||
}
|
||||
|
||||
// Choose Huffman tables for each region (3 regions for long blocks)
|
||||
int n_regions = 3;
|
||||
int total_bits = 0;
|
||||
int prev_end = 0;
|
||||
|
||||
for (int r = 0; r < n_regions; r++) {
|
||||
int pairs = (region_end[r] - prev_end) / 2;
|
||||
gi.table_select[r] = mp3enc_choose_table(ix, prev_end, pairs);
|
||||
for (int p = 0; p < pairs; p++) {
|
||||
int i = prev_end + p * 2;
|
||||
total_bits += mp3enc_pair_bits(gi.table_select[r], ix[i], ix[i + 1]);
|
||||
}
|
||||
prev_end = region_end[r];
|
||||
}
|
||||
|
||||
// Count1 region: try both tables, pick the smaller
|
||||
int c1_bits_a = 0, c1_bits_b = 0;
|
||||
for (int q = 0; q < c1_count; q++) {
|
||||
int i = c1_start + q * 4;
|
||||
int v = abs(ix[i]), w = abs(ix[i + 1]), x = abs(ix[i + 2]), y = abs(ix[i + 3]);
|
||||
int idx = v * 8 + w * 4 + x * 2 + y;
|
||||
int signs = (v > 0) + (w > 0) + (x > 0) + (y > 0);
|
||||
c1_bits_a += mp3enc_count1a_len[idx] + signs;
|
||||
c1_bits_b += mp3enc_count1b_len[idx] + signs;
|
||||
}
|
||||
|
||||
if (c1_bits_a <= c1_bits_b) {
|
||||
gi.count1table_select = 0;
|
||||
total_bits += c1_bits_a;
|
||||
} else {
|
||||
gi.count1table_select = 1;
|
||||
total_bits += c1_bits_b;
|
||||
}
|
||||
|
||||
return total_bits;
|
||||
}
|
||||
|
||||
// Compute part2_length: number of bits for scalefactors.
|
||||
// Depends on scalefac_compress and which bands are transmitted.
|
||||
static int mp3enc_part2_length(const mp3enc_granule_info & gi, int gr, const int scfsi[4]) {
|
||||
int slen1 = mp3enc_slen[0][gi.scalefac_compress];
|
||||
int slen2 = mp3enc_slen[1][gi.scalefac_compress];
|
||||
int bits = 0;
|
||||
|
||||
// Long blocks: 4 scfsi groups
|
||||
static const int band_start[4] = { 0, 6, 11, 16 };
|
||||
static const int band_end[4] = { 6, 11, 16, 21 };
|
||||
|
||||
for (int b = 0; b < 4; b++) {
|
||||
if (gr == 0 || scfsi[b] == 0) {
|
||||
int slen = (b < 2) ? slen1 : slen2;
|
||||
int count = band_end[b] - band_start[b];
|
||||
bits += count * slen;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Find the best scalefac_compress for the current scalefactors.
|
||||
// Returns the compress index (0..15) that can represent all scalefactors
|
||||
// with the fewest total bits.
|
||||
static int mp3enc_best_scalefac_compress(const int * scalefac_l) {
|
||||
// Find max scalefactor in each group
|
||||
int max1 = 0; // bands 0..10 (slen1)
|
||||
int max2 = 0; // bands 11..20 (slen2)
|
||||
for (int sfb = 0; sfb < 11; sfb++) {
|
||||
if (scalefac_l[sfb] > max1) {
|
||||
max1 = scalefac_l[sfb];
|
||||
}
|
||||
}
|
||||
for (int sfb = 11; sfb < 21; sfb++) {
|
||||
if (scalefac_l[sfb] > max2) {
|
||||
max2 = scalefac_l[sfb];
|
||||
}
|
||||
}
|
||||
|
||||
// Try all 16 compress values, pick the one with fewest bits
|
||||
// that can represent the max values
|
||||
int best_compress = 0;
|
||||
int best_bits = 999;
|
||||
|
||||
for (int c = 0; c < 16; c++) {
|
||||
int s1 = mp3enc_slen[0][c];
|
||||
int s2 = mp3enc_slen[1][c];
|
||||
int max_val1 = (s1 > 0) ? ((1 << s1) - 1) : 0;
|
||||
int max_val2 = (s2 > 0) ? ((1 << s2) - 1) : 0;
|
||||
|
||||
// Can this compress value represent our scalefactors?
|
||||
if (max1 > max_val1 || max2 > max_val2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Total bits for scalefactors (granule 0, no scfsi)
|
||||
int bits = 11 * s1 + 10 * s2;
|
||||
if (bits < best_bits) {
|
||||
best_bits = bits;
|
||||
best_compress = c;
|
||||
}
|
||||
}
|
||||
return best_compress;
|
||||
}
|
||||
|
||||
// Inner loop: find minimum global_gain where Huffman bits fit the budget.
|
||||
// Bit count is monotonically decreasing with global_gain (higher gain = coarser
|
||||
// quantization = fewer bits). We want the smallest gain where bits <= budget.
|
||||
//
|
||||
// When hint_gain >= 0 (from a previous inner_loop call in the same outer loop),
|
||||
// the optimal gain is typically within a few steps. We scan linearly from the
|
||||
// hint instead of doing a full binary search on [0, 255]. This cuts the typical
|
||||
// iteration count from 8 to 3-4.
|
||||
//
|
||||
// scalefac: per-band scalefactors (NULL for initial call before outer loop).
|
||||
// hint_gain: previous global_gain from last inner_loop call, or -1 for full search.
|
||||
static int mp3enc_inner_loop(const float * xr,
|
||||
int * ix,
|
||||
mp3enc_granule_info & gi,
|
||||
int available_bits,
|
||||
const uint8_t * sfb_table,
|
||||
int sr_index,
|
||||
const int * scalefac = nullptr,
|
||||
int hint_gain = -1) {
|
||||
// quantize + count_bits helper (avoids repeating the branch 5 times)
|
||||
auto try_gain = [&](int g) -> int {
|
||||
if (!scalefac || gi.scalefac_compress == 0) {
|
||||
mp3enc_quantize(xr, ix, g);
|
||||
} else {
|
||||
mp3enc_quantize_sfb(xr, ix, g, scalefac, gi.scalefac_scale, gi.preflag, sfb_table);
|
||||
}
|
||||
for (int i = 0; i < 576; i++) {
|
||||
if (abs(ix[i]) >= 8191) {
|
||||
return available_bits + 1; // saturated
|
||||
}
|
||||
}
|
||||
return mp3enc_count_bits(ix, gi, sfb_table, sr_index);
|
||||
};
|
||||
|
||||
int best_gain = 210;
|
||||
int best_bits = available_bits + 1;
|
||||
|
||||
if (hint_gain >= 0) {
|
||||
// Linear scan from hint. Typical cost: 3-4 try_gain calls.
|
||||
int bits = try_gain(hint_gain);
|
||||
|
||||
if (bits <= available_bits) {
|
||||
// Hint fits. Scan downward to find the minimum valid gain.
|
||||
best_gain = hint_gain;
|
||||
best_bits = bits;
|
||||
for (int g = hint_gain - 1; g >= 0 && g >= hint_gain - 10; g--) {
|
||||
bits = try_gain(g);
|
||||
if (bits > available_bits) {
|
||||
break;
|
||||
}
|
||||
best_gain = g;
|
||||
best_bits = bits;
|
||||
}
|
||||
} else {
|
||||
// Hint doesn't fit. Scan upward to find the first valid gain.
|
||||
bool found = false;
|
||||
for (int g = hint_gain + 1; g <= 255 && g <= hint_gain + 20; g++) {
|
||||
bits = try_gain(g);
|
||||
if (bits <= available_bits) {
|
||||
best_gain = g;
|
||||
best_bits = bits;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Fallback: if scan didn't find it (rare, e.g. scalefac_scale toggle),
|
||||
// binary search on the remaining range.
|
||||
if (!found) {
|
||||
int lo = hint_gain + 21;
|
||||
int hi = 255;
|
||||
while (lo <= hi) {
|
||||
int mid = (lo + hi) / 2;
|
||||
bits = try_gain(mid);
|
||||
if (bits <= available_bits) {
|
||||
best_gain = mid;
|
||||
best_bits = bits;
|
||||
hi = mid - 1;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No hint: full binary search on [0, 255].
|
||||
int lo = 0, hi = 255;
|
||||
while (lo <= hi) {
|
||||
int mid = (lo + hi) / 2;
|
||||
int bits = try_gain(mid);
|
||||
if (bits <= available_bits) {
|
||||
best_gain = mid;
|
||||
best_bits = bits;
|
||||
hi = mid - 1;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Final quantization with the best gain
|
||||
gi.global_gain = best_gain;
|
||||
if (!scalefac || gi.scalefac_compress == 0) {
|
||||
mp3enc_quantize(xr, ix, best_gain);
|
||||
} else {
|
||||
mp3enc_quantize_sfb(xr, ix, best_gain, scalefac, gi.scalefac_scale, gi.preflag, sfb_table);
|
||||
}
|
||||
best_bits = mp3enc_count_bits(ix, gi, sfb_table, sr_index);
|
||||
return best_bits;
|
||||
}
|
||||
|
||||
// Outer loop: iteratively adjust scalefactors to push quantization noise
|
||||
// below the masking thresholds computed by the psy model.
|
||||
//
|
||||
// Algorithm:
|
||||
// 1. Start with all scalefactors = 0, run inner loop
|
||||
// 2. Compute noise per SFB
|
||||
// 3. For each SFB where noise > xmin, bump its scalefactor
|
||||
// 4. Update scalefac_compress, recompute bit budget, re-run inner loop
|
||||
// 5. Repeat until noise is under control or we run out of iterations/bits
|
||||
//
|
||||
// xr: 576 MDCT coefficients
|
||||
// ix: 576 quantized output
|
||||
// gi: granule info (filled on return)
|
||||
// xmin: masking thresholds per SFB from psy model
|
||||
// available_bits: total bits for part2_3 (scalefactors + Huffman)
|
||||
// sfb_table: SFB widths
|
||||
// sr_index: sample rate index
|
||||
// gr: granule number (0 or 1)
|
||||
// scfsi: scfsi flags (for part2_length calculation)
|
||||
// Returns part2_3_length (scalefactor bits + Huffman bits).
|
||||
static int mp3enc_outer_loop(const float * xr,
|
||||
int * ix,
|
||||
mp3enc_granule_info & gi,
|
||||
const float * xmin,
|
||||
int available_bits,
|
||||
const uint8_t * sfb_table,
|
||||
int sr_index,
|
||||
int gr,
|
||||
const int scfsi[4]) {
|
||||
// Initialize: no scalefactors
|
||||
memset(&gi, 0, sizeof(gi));
|
||||
gi.block_type = 0;
|
||||
|
||||
// Initial inner loop with flat quantization
|
||||
int huff_bits = mp3enc_inner_loop(xr, ix, gi, available_bits, sfb_table, sr_index);
|
||||
gi.part2_3_length = huff_bits;
|
||||
|
||||
// If no psy thresholds (all zero), skip outer loop
|
||||
bool have_psy = false;
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
if (xmin[sfb] > 0.0f) {
|
||||
have_psy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!have_psy) {
|
||||
return gi.part2_3_length;
|
||||
}
|
||||
|
||||
// Outer iteration loop (ISO 11172-3 Annex C.1.5.4.3).
|
||||
// For each iteration:
|
||||
// - compute distortion per SFB
|
||||
// - bump scalefactor for EVERY band where noise > xmin
|
||||
// - re-run inner loop with updated scalefactors
|
||||
// - stop when all bands are under threshold or no bits left
|
||||
//
|
||||
// Max 25 passes: enough for convergence at all bitrates.
|
||||
float noise[22]; // 22 SFB bands before table terminator
|
||||
int best_ix[576];
|
||||
mp3enc_granule_info best_gi = gi;
|
||||
int best_total = gi.part2_3_length;
|
||||
int best_over = 21; // start pessimistic
|
||||
float best_max_db = 999.0f; // worst-band noise in dB over threshold
|
||||
float best_tot_db = 999.0f; // total over-threshold noise in dB
|
||||
memcpy(best_ix, ix, sizeof(best_ix));
|
||||
|
||||
for (int iter = 0; iter < 25; iter++) {
|
||||
// Compute noise per SFB with current quantization
|
||||
mp3enc_calc_noise(xr, ix, gi.global_gain, gi.scalefac_l, gi.scalefac_scale, gi.preflag, sfb_table, noise);
|
||||
|
||||
// Compute noise metrics for 3-axis comparison (GPSYCHO approach).
|
||||
// Instead of just counting bands over threshold, track:
|
||||
// - max_over_db: worst violation in dB (peak distortion)
|
||||
// - tot_over_db: sum of violations in dB (for average)
|
||||
// - over_count: number of distorted bands
|
||||
// This prefers solutions that minimize peak distortion and spread
|
||||
// remaining noise evenly, rather than concentrating it in one band.
|
||||
int over_count = 0;
|
||||
float max_over_db = 0.0f;
|
||||
float tot_over_db = 0.0f;
|
||||
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
if (xmin[sfb] > 0.0f && noise[sfb] > xmin[sfb]) {
|
||||
over_count++;
|
||||
float over_db = 10.0f * log10f(noise[sfb] / xmin[sfb]);
|
||||
tot_over_db += over_db;
|
||||
if (over_db > max_over_db) {
|
||||
max_over_db = over_db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3-axis quant_compare (inspired by LAME GPSYCHO outer_loop):
|
||||
// 1. Clean (over=0) always beats dirty (over>0)
|
||||
// 2. Among clean solutions: prefer fewer bits
|
||||
// 3. Among dirty solutions: minimize peak, then average, then count
|
||||
bool is_better = false;
|
||||
if (over_count == 0 && best_over > 0) {
|
||||
is_better = true;
|
||||
} else if (over_count == 0 && best_over == 0) {
|
||||
is_better = (gi.part2_3_length < best_total);
|
||||
} else if (over_count > 0 && best_over > 0) {
|
||||
// both dirty: compare peak distortion first
|
||||
if (max_over_db < best_max_db - 0.5f) {
|
||||
// significantly lower peak -> better
|
||||
is_better = true;
|
||||
} else if (max_over_db < best_max_db + 0.5f) {
|
||||
// similar peak: compare average violation
|
||||
float avg = tot_over_db / (float) over_count;
|
||||
float best_avg = (best_over > 0) ? best_tot_db / (float) best_over : 0.0f;
|
||||
if (avg < best_avg - 0.3f) {
|
||||
is_better = true;
|
||||
} else if (avg < best_avg + 0.3f) {
|
||||
// similar average: prefer fewer violated bands
|
||||
is_better = (over_count < best_over);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_better) {
|
||||
best_gi = gi;
|
||||
best_total = gi.part2_3_length;
|
||||
best_over = over_count;
|
||||
best_max_db = max_over_db;
|
||||
best_tot_db = tot_over_db;
|
||||
memcpy(best_ix, ix, sizeof(best_ix));
|
||||
}
|
||||
|
||||
// If all bands are under threshold, we are done
|
||||
if (over_count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Bump scalefactor for EVERY band where noise > threshold.
|
||||
// ISO outer loop: amplify all distorted bands by 1 step per iteration.
|
||||
bool any_changed = false;
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
if (xmin[sfb] > 0.0f && noise[sfb] > xmin[sfb]) {
|
||||
gi.scalefac_l[sfb]++;
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
if (!any_changed) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Preflag: if HF bands need large scalefactors, enable preflag
|
||||
// to get free amplification from the pretab table (ISO Table B.6).
|
||||
// This saves bits: pretab adds 0-3 to HF scalefactors for free
|
||||
// (encoded in a single bit rather than per-band bits).
|
||||
if (!gi.preflag) {
|
||||
int hf_need = 0;
|
||||
for (int sfb = 11; sfb < 21; sfb++) {
|
||||
if (gi.scalefac_l[sfb] >= 2 && mp3enc_pretab[sfb] > 0) {
|
||||
hf_need++;
|
||||
}
|
||||
}
|
||||
// Enable if at least 3 HF bands need boosting
|
||||
if (hf_need >= 3) {
|
||||
gi.preflag = 1;
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
gi.scalefac_l[sfb] -= mp3enc_pretab[sfb];
|
||||
if (gi.scalefac_l[sfb] < 0) {
|
||||
gi.scalefac_l[sfb] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scalefac_scale: if any scalefactor exceeds 15 (4 bit max),
|
||||
// double the step size. This halves all scalefactors but each
|
||||
// step now represents sqrt(2) instead of 2^(1/4).
|
||||
int max_sf = 0;
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
if (gi.scalefac_l[sfb] > max_sf) {
|
||||
max_sf = gi.scalefac_l[sfb];
|
||||
}
|
||||
}
|
||||
if (max_sf > 15 && !gi.scalefac_scale) {
|
||||
gi.scalefac_scale = 1;
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
gi.scalefac_l[sfb] = (gi.scalefac_l[sfb] + 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Clamp to 15
|
||||
for (int sfb = 0; sfb < 21; sfb++) {
|
||||
if (gi.scalefac_l[sfb] > 15) {
|
||||
gi.scalefac_l[sfb] = 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Update scalefac_compress and compute part2 bits
|
||||
gi.scalefac_compress = mp3enc_best_scalefac_compress(gi.scalefac_l);
|
||||
int part2 = mp3enc_part2_length(gi, gr, scfsi);
|
||||
int huff_budget = available_bits - part2;
|
||||
if (huff_budget < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-run inner loop
|
||||
huff_bits = mp3enc_inner_loop(xr, ix, gi, huff_budget, sfb_table, sr_index, gi.scalefac_l, gi.global_gain);
|
||||
int total = part2 + huff_bits;
|
||||
|
||||
if (total <= available_bits) {
|
||||
gi.part2_3_length = total;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore best result
|
||||
gi = best_gi;
|
||||
memcpy(ix, best_ix, sizeof(best_ix));
|
||||
gi.part2_3_length = best_total;
|
||||
|
||||
return gi.part2_3_length;
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
#pragma once
|
||||
// mp3enc-tables.h
|
||||
// Numerical constants for the MP3 encoder.
|
||||
// Extracted from minimp3 (CC0, github.com/lieff/minimp3).
|
||||
// Values match ISO 11172-3 Annex B+C.
|
||||
// MIT license.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Layer III bitrates in kbps, indexed by bitrate_index 0..14
|
||||
// Index 0 = free format, index 15 = forbidden
|
||||
static const int mp3enc_bitrate_kbps[15] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
|
||||
|
||||
// MPEG1 sample rates, indexed by sampling_frequency field (2 bits)
|
||||
static const int mp3enc_samplerate[3] = { 44100, 48000, 32000 };
|
||||
|
||||
// slen1 and slen2 from scalefac_compress (0..15)
|
||||
// slen1 = mp3enc_slen[0][i], slen2 = mp3enc_slen[1][i]
|
||||
static const uint8_t mp3enc_slen[2][16] = {
|
||||
{ 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 },
|
||||
{ 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }
|
||||
};
|
||||
|
||||
// Pretab values added to scalefactors when preflag=1 (ISO Table B.6)
|
||||
static const uint8_t mp3enc_pretab[22] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 };
|
||||
|
||||
// SFB boundaries: long blocks (ISO Table B.8, from minimp3 CC0)
|
||||
// MPEG1 only: [0]=44100Hz, [1]=48000Hz, [2]=32000Hz
|
||||
// These correspond to minimp3 g_scf_long[5..7].
|
||||
static const uint8_t mp3enc_sfb_long[3][23] = {
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26, 0 }
|
||||
};
|
||||
|
||||
// SFB boundaries: short blocks (ISO Table B.8, from minimp3 CC0)
|
||||
// [sr_index][band_width]
|
||||
// SFB boundaries: short blocks (ISO Table B.8, from minimp3 CC0)
|
||||
// MPEG1 only: [0]=44100Hz, [1]=48000Hz, [2]=32000Hz
|
||||
static const uint8_t mp3enc_sfb_short[3][40] = {
|
||||
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10,
|
||||
10, 12, 12, 12, 14, 14, 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 10, 10,
|
||||
10, 12, 12, 12, 14, 14, 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 12, 12,
|
||||
12, 16, 16, 16, 20, 20, 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12, 0 }
|
||||
};
|
||||
|
||||
// SFB boundaries: mixed blocks (ISO Table B.8, from minimp3 CC0)
|
||||
// [sr_index][band_width]
|
||||
static const uint8_t mp3enc_sfb_mixed[8][40] = {
|
||||
{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14,
|
||||
14, 14, 18, 18, 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18, 0 },
|
||||
{ 12, 12, 12, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24,
|
||||
24, 28, 28, 28, 36, 36, 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26, 0 },
|
||||
{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 14,
|
||||
14, 14, 18, 18, 18, 26, 26, 26, 32, 32, 32, 42, 42, 42, 18, 18, 18, 0 },
|
||||
{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14,
|
||||
14, 14, 18, 18, 18, 24, 24, 24, 32, 32, 32, 44, 44, 44, 12, 12, 12, 0 },
|
||||
{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14,
|
||||
14, 14, 18, 18, 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 10,
|
||||
12, 12, 12, 14, 14, 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 4, 4, 4, 6, 6, 6, 6, 6, 6, 10, 10, 10,
|
||||
12, 12, 12, 14, 14, 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66, 0 },
|
||||
{ 4, 4, 4, 4, 4, 4, 6, 6, 4, 4, 4, 6, 6, 6, 8, 8, 8, 12, 12, 12,
|
||||
16, 16, 16, 20, 20, 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12, 0 }
|
||||
};
|
||||
|
||||
// Alias reduction butterfly coefficients (ISO Table B.9, from minimp3 CC0)
|
||||
// cs[i] = 1/sqrt(1 + ci^2), ca[i] = ci/sqrt(1 + ci^2)
|
||||
static const float mp3enc_cs[8] = { 0.85749293f, 0.88174200f, 0.94962865f, 0.98331459f,
|
||||
0.99551782f, 0.99916056f, 0.99989920f, 0.99999316f };
|
||||
static const float mp3enc_ca[8] = { 0.51449576f, 0.47173197f, 0.31337745f, 0.18191320f,
|
||||
0.09457419f, 0.04096558f, 0.01419856f, 0.00369997f };
|
||||
|
||||
// MDCT window shapes for overlap add (from minimp3 CC0)
|
||||
// [0] = normal/start, [1] = stop block
|
||||
// First 9 values: sin(pi/36 * (i + 0.5)) for i=0..8
|
||||
// Last 9 values: sin(pi/36 * (i + 18.5)) for i=0..8
|
||||
static const float mp3enc_mdct_win[2][18] = {
|
||||
{ 0.99904822f, 0.99144486f, 0.97629601f, 0.95371695f, 0.92387953f, 0.88701083f, 0.84339145f, 0.79335334f,
|
||||
0.73727734f, 0.04361938f, 0.13052619f, 0.21643961f, 0.30070580f, 0.38268343f, 0.46174861f, 0.53729961f,
|
||||
0.60876143f, 0.67559021f },
|
||||
{ 1, 1, 1, 1, 1, 1, 0.99144486f, 0.92387953f, 0.79335334f, 0, 0, 0, 0, 0, 0, 0.13052619f, 0.38268343f, 0.60876143f }
|
||||
};
|
||||
|
||||
// MDCT twiddle factors for 18 point and 6 point transforms (from minimp3 CC0)
|
||||
static const float mp3enc_twid9[18] = { 0.73727734f, 0.79335334f, 0.84339145f, 0.88701083f, 0.92387953f, 0.95371695f,
|
||||
0.97629601f, 0.99144486f, 0.99904822f, 0.67559021f, 0.60876143f, 0.53729961f,
|
||||
0.46174861f, 0.38268343f, 0.30070580f, 0.21643961f, 0.13052619f, 0.04361938f };
|
||||
static const float mp3enc_twid3[6] = { 0.79335334f, 0.92387953f, 0.99144486f, 0.60876143f, 0.38268343f, 0.13052619f };
|
||||
|
||||
// Analysis filterbank window, 512 coefficients.
|
||||
// Ci coefficients for the polyphase analysis filter (ISO 11172-3 Table C.1).
|
||||
// Extracted from minimp3 (CC0).
|
||||
static const float mp3enc_enwindow[512] = {
|
||||
0.000000e+00f, -0.000000e+00f, -0.000000e+00f, -0.000000e+00f, -0.000000e+00f, -0.000000e+00f, -0.000000e+00f,
|
||||
-1.000000e-06f, -1.000000e-06f, -1.000000e-06f, -1.000000e-06f, -1.000000e-06f, -1.000000e-06f, -2.000000e-06f,
|
||||
-2.000000e-06f, -2.000000e-06f, -2.000000e-06f, -3.000000e-06f, -3.000000e-06f, -3.000000e-06f, -4.000000e-06f,
|
||||
-4.000000e-06f, -5.000000e-06f, -5.000000e-06f, -6.000000e-06f, -7.000000e-06f, -8.000000e-06f, -8.000000e-06f,
|
||||
-9.000000e-06f, -1.000000e-05f, -1.100000e-05f, -1.200000e-05f, -1.400000e-05f, -1.500000e-05f, -1.700000e-05f,
|
||||
-1.800000e-05f, -2.000000e-05f, -2.100000e-05f, -2.300000e-05f, -2.500000e-05f, -2.800000e-05f, -3.000000e-05f,
|
||||
-3.200000e-05f, -3.500000e-05f, -3.800000e-05f, -4.100000e-05f, -4.300000e-05f, -4.600000e-05f, -5.000000e-05f,
|
||||
-5.300000e-05f, -5.600000e-05f, -6.000000e-05f, -6.300000e-05f, -6.600000e-05f, -7.000000e-05f, -7.300000e-05f,
|
||||
-7.700000e-05f, -8.100000e-05f, -8.400000e-05f, -8.700000e-05f, -9.100000e-05f, -9.300000e-05f, -9.600000e-05f,
|
||||
-9.900000e-05f, 1.020000e-04f, 1.040000e-04f, 1.060000e-04f, 1.070000e-04f, 1.080000e-04f, 1.090000e-04f,
|
||||
1.090000e-04f, 1.080000e-04f, 1.070000e-04f, 1.050000e-04f, 1.030000e-04f, 9.900000e-05f, 9.500000e-05f,
|
||||
9.000000e-05f, 8.400000e-05f, 7.800000e-05f, 7.000000e-05f, 6.100000e-05f, 5.100000e-05f, 4.000000e-05f,
|
||||
2.700000e-05f, 1.400000e-05f, -1.000000e-06f, -1.700000e-05f, -3.400000e-05f, -5.300000e-05f, -7.300000e-05f,
|
||||
-9.400000e-05f, -1.160000e-04f, -1.400000e-04f, -1.650000e-04f, -1.910000e-04f, -2.190000e-04f, -2.470000e-04f,
|
||||
-2.770000e-04f, -3.080000e-04f, -3.390000e-04f, -3.710000e-04f, -4.040000e-04f, -4.380000e-04f, -4.730000e-04f,
|
||||
-5.070000e-04f, -5.420000e-04f, -5.770000e-04f, -6.120000e-04f, -6.470000e-04f, -6.810000e-04f, -7.140000e-04f,
|
||||
-7.470000e-04f, -7.790000e-04f, -8.100000e-04f, -8.390000e-04f, -8.660000e-04f, -8.920000e-04f, -9.150000e-04f,
|
||||
-9.360000e-04f, -9.540000e-04f, -9.690000e-04f, -9.810000e-04f, -9.890000e-04f, -9.940000e-04f, -9.950000e-04f,
|
||||
-9.920000e-04f, -9.840000e-04f, 9.710000e-04f, 9.540000e-04f, 9.310000e-04f, 9.030000e-04f, 8.690000e-04f,
|
||||
8.290000e-04f, 7.840000e-04f, 7.320000e-04f, 6.740000e-04f, 6.100000e-04f, 5.390000e-04f, 4.630000e-04f,
|
||||
3.790000e-04f, 2.880000e-04f, 1.920000e-04f, 8.800000e-05f, -2.100000e-05f, -1.370000e-04f, -2.600000e-04f,
|
||||
-3.880000e-04f, -5.220000e-04f, -6.620000e-04f, -8.070000e-04f, -9.570000e-04f, -1.111000e-03f, -1.270000e-03f,
|
||||
-1.432000e-03f, -1.598000e-03f, -1.767000e-03f, -1.937000e-03f, -2.110000e-03f, -2.283000e-03f, -2.457000e-03f,
|
||||
-2.631000e-03f, -2.803000e-03f, -2.974000e-03f, -3.142000e-03f, -3.307000e-03f, -3.467000e-03f, -3.623000e-03f,
|
||||
-3.772000e-03f, -3.914000e-03f, -4.049000e-03f, -4.175000e-03f, -4.291000e-03f, -4.396000e-03f, -4.490000e-03f,
|
||||
-4.570000e-03f, -4.638000e-03f, -4.691000e-03f, -4.728000e-03f, -4.749000e-03f, -4.752000e-03f, -4.737000e-03f,
|
||||
-4.703000e-03f, -4.649000e-03f, -4.574000e-03f, -4.477000e-03f, -4.358000e-03f, -4.215000e-03f, -4.049000e-03f,
|
||||
-3.859000e-03f, -3.643000e-03f, -3.402000e-03f, 3.135000e-03f, 2.841000e-03f, 2.522000e-03f, 2.175000e-03f,
|
||||
1.801000e-03f, 1.400000e-03f, 9.710000e-04f, 5.160000e-04f, 3.300000e-05f, -4.760000e-04f, -1.012000e-03f,
|
||||
-1.574000e-03f, -2.162000e-03f, -2.774000e-03f, -3.411000e-03f, -4.072000e-03f, -4.756000e-03f, -5.462000e-03f,
|
||||
-6.189000e-03f, -6.937000e-03f, -7.703000e-03f, -8.487000e-03f, -9.288000e-03f, -1.010400e-02f, -1.093300e-02f,
|
||||
-1.177500e-02f, -1.262800e-02f, -1.348900e-02f, -1.435900e-02f, -1.523400e-02f, -1.611300e-02f, -1.699400e-02f,
|
||||
-1.787600e-02f, -1.875700e-02f, -1.963400e-02f, -2.050700e-02f, -2.137200e-02f, -2.222900e-02f, -2.307400e-02f,
|
||||
-2.390700e-02f, -2.472500e-02f, -2.552700e-02f, -2.631100e-02f, -2.707400e-02f, -2.781500e-02f, -2.853300e-02f,
|
||||
-2.922500e-02f, -2.989000e-02f, -3.052700e-02f, -3.113300e-02f, -3.170700e-02f, -3.224800e-02f, -3.275500e-02f,
|
||||
-3.322600e-02f, -3.366000e-02f, -3.405600e-02f, -3.441300e-02f, -3.473000e-02f, -3.500700e-02f, -3.524200e-02f,
|
||||
-3.543500e-02f, -3.558600e-02f, -3.569400e-02f, -3.575900e-02f, 3.578100e-02f, 3.575900e-02f, 3.569400e-02f,
|
||||
3.558600e-02f, 3.543500e-02f, 3.524200e-02f, 3.500700e-02f, 3.473000e-02f, 3.441300e-02f, 3.405600e-02f,
|
||||
3.366000e-02f, 3.322600e-02f, 3.275500e-02f, 3.224800e-02f, 3.170700e-02f, 3.113300e-02f, 3.052700e-02f,
|
||||
2.989000e-02f, 2.922500e-02f, 2.853300e-02f, 2.781500e-02f, 2.707400e-02f, 2.631100e-02f, 2.552700e-02f,
|
||||
2.472500e-02f, 2.390700e-02f, 2.307400e-02f, 2.222900e-02f, 2.137200e-02f, 2.050700e-02f, 1.963400e-02f,
|
||||
1.875700e-02f, 1.787600e-02f, 1.699400e-02f, 1.611300e-02f, 1.523400e-02f, 1.435900e-02f, 1.348900e-02f,
|
||||
1.262800e-02f, 1.177500e-02f, 1.093300e-02f, 1.010400e-02f, 9.288000e-03f, 8.487000e-03f, 7.703000e-03f,
|
||||
6.937000e-03f, 6.189000e-03f, 5.462000e-03f, 4.756000e-03f, 4.072000e-03f, 3.411000e-03f, 2.774000e-03f,
|
||||
2.162000e-03f, 1.574000e-03f, 1.012000e-03f, 4.760000e-04f, -3.300000e-05f, -5.160000e-04f, -9.710000e-04f,
|
||||
-1.400000e-03f, -1.801000e-03f, -2.175000e-03f, -2.522000e-03f, -2.841000e-03f, 3.135000e-03f, 3.402000e-03f,
|
||||
3.643000e-03f, 3.859000e-03f, 4.049000e-03f, 4.215000e-03f, 4.358000e-03f, 4.477000e-03f, 4.574000e-03f,
|
||||
4.649000e-03f, 4.703000e-03f, 4.737000e-03f, 4.752000e-03f, 4.749000e-03f, 4.728000e-03f, 4.691000e-03f,
|
||||
4.638000e-03f, 4.570000e-03f, 4.490000e-03f, 4.396000e-03f, 4.291000e-03f, 4.175000e-03f, 4.049000e-03f,
|
||||
3.914000e-03f, 3.772000e-03f, 3.623000e-03f, 3.467000e-03f, 3.307000e-03f, 3.142000e-03f, 2.974000e-03f,
|
||||
2.803000e-03f, 2.631000e-03f, 2.457000e-03f, 2.283000e-03f, 2.110000e-03f, 1.937000e-03f, 1.767000e-03f,
|
||||
1.598000e-03f, 1.432000e-03f, 1.270000e-03f, 1.111000e-03f, 9.570000e-04f, 8.070000e-04f, 6.620000e-04f,
|
||||
5.220000e-04f, 3.880000e-04f, 2.600000e-04f, 1.370000e-04f, 2.100000e-05f, -8.800000e-05f, -1.920000e-04f,
|
||||
-2.880000e-04f, -3.790000e-04f, -4.630000e-04f, -5.390000e-04f, -6.100000e-04f, -6.740000e-04f, -7.320000e-04f,
|
||||
-7.840000e-04f, -8.290000e-04f, -8.690000e-04f, -9.030000e-04f, -9.310000e-04f, -9.540000e-04f, 9.710000e-04f,
|
||||
9.840000e-04f, 9.920000e-04f, 9.950000e-04f, 9.940000e-04f, 9.890000e-04f, 9.810000e-04f, 9.690000e-04f,
|
||||
9.540000e-04f, 9.360000e-04f, 9.150000e-04f, 8.920000e-04f, 8.660000e-04f, 8.390000e-04f, 8.100000e-04f,
|
||||
7.790000e-04f, 7.470000e-04f, 7.140000e-04f, 6.810000e-04f, 6.470000e-04f, 6.120000e-04f, 5.770000e-04f,
|
||||
5.420000e-04f, 5.070000e-04f, 4.730000e-04f, 4.380000e-04f, 4.040000e-04f, 3.710000e-04f, 3.390000e-04f,
|
||||
3.080000e-04f, 2.770000e-04f, 2.470000e-04f, 2.190000e-04f, 1.910000e-04f, 1.650000e-04f, 1.400000e-04f,
|
||||
1.160000e-04f, 9.400000e-05f, 7.300000e-05f, 5.300000e-05f, 3.400000e-05f, 1.700000e-05f, 1.000000e-06f,
|
||||
-1.400000e-05f, -2.700000e-05f, -4.000000e-05f, -5.100000e-05f, -6.100000e-05f, -7.000000e-05f, -7.800000e-05f,
|
||||
-8.400000e-05f, -9.000000e-05f, -9.500000e-05f, -9.900000e-05f, -1.030000e-04f, -1.050000e-04f, -1.070000e-04f,
|
||||
-1.080000e-04f, -1.090000e-04f, -1.090000e-04f, -1.080000e-04f, -1.070000e-04f, -1.060000e-04f, -1.040000e-04f,
|
||||
1.020000e-04f, 9.900000e-05f, 9.600000e-05f, 9.300000e-05f, 9.100000e-05f, 8.700000e-05f, 8.400000e-05f,
|
||||
8.100000e-05f, 7.700000e-05f, 7.300000e-05f, 7.000000e-05f, 6.600000e-05f, 6.300000e-05f, 6.000000e-05f,
|
||||
5.600000e-05f, 5.300000e-05f, 5.000000e-05f, 4.600000e-05f, 4.300000e-05f, 4.100000e-05f, 3.800000e-05f,
|
||||
3.500000e-05f, 3.200000e-05f, 3.000000e-05f, 2.800000e-05f, 2.500000e-05f, 2.300000e-05f, 2.100000e-05f,
|
||||
2.000000e-05f, 1.800000e-05f, 1.700000e-05f, 1.500000e-05f, 1.400000e-05f, 1.200000e-05f, 1.100000e-05f,
|
||||
1.000000e-05f, 9.000000e-06f, 8.000000e-06f, 8.000000e-06f, 7.000000e-06f, 6.000000e-06f, 5.000000e-06f,
|
||||
5.000000e-06f, 4.000000e-06f, 4.000000e-06f, 3.000000e-06f, 3.000000e-06f, 3.000000e-06f, 2.000000e-06f,
|
||||
2.000000e-06f, 2.000000e-06f, 2.000000e-06f, 1.000000e-06f, 1.000000e-06f, 1.000000e-06f, 1.000000e-06f,
|
||||
1.000000e-06f, 1.000000e-06f, 0.000000e+00f, 0.000000e+00f, 0.000000e+00f, 0.000000e+00f, 0.000000e+00f,
|
||||
0.000000e+00f
|
||||
};
|
||||
|
||||
// Huffman encoder tables (generated from minimp3 CC0 decoder trees)
|
||||
// See gen_huff_enc.c for the generator source.
|
||||
static const uint8_t mp3enc_linbits[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13 };
|
||||
static const uint16_t mp3enc_hcode_1[2][2] = {
|
||||
{ 0x1, 0x1 },
|
||||
{ 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_1[2][2] = {
|
||||
{ 1, 2 },
|
||||
{ 3, 3 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_2[3][3] = {
|
||||
{ 0x1, 0x3, 0x3 },
|
||||
{ 0x2, 0x1, 0x2 },
|
||||
{ 0x1, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_2[3][3] = {
|
||||
{ 1, 3, 5 },
|
||||
{ 3, 3, 5 },
|
||||
{ 6, 5, 6 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_3[3][3] = {
|
||||
{ 0x3, 0x1, 0x3 },
|
||||
{ 0x2, 0x1, 0x2 },
|
||||
{ 0x1, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_3[3][3] = {
|
||||
{ 2, 3, 5 },
|
||||
{ 2, 2, 5 },
|
||||
{ 6, 5, 6 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_5[4][4] = {
|
||||
{ 0x1, 0x3, 0x7, 0x6 },
|
||||
{ 0x2, 0x1, 0x5, 0x1 },
|
||||
{ 0x6, 0x4, 0x7, 0x1 },
|
||||
{ 0x5, 0x4, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_5[4][4] = {
|
||||
{ 1, 3, 6, 7 },
|
||||
{ 3, 3, 6, 6 },
|
||||
{ 6, 6, 7, 7 },
|
||||
{ 7, 7, 8, 8 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_6[4][4] = {
|
||||
{ 0x7, 0x6, 0x5, 0x3 },
|
||||
{ 0x3, 0x2, 0x4, 0x3 },
|
||||
{ 0x5, 0x3, 0x4, 0x2 },
|
||||
{ 0x1, 0x2, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_6[4][4] = {
|
||||
{ 3, 3, 4, 6 },
|
||||
{ 3, 2, 4, 5 },
|
||||
{ 5, 4, 5, 6 },
|
||||
{ 7, 5, 6, 7 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_7[6][6] = {
|
||||
{ 0x1, 0x3, 0xb, 0xc, 0x7, 0x6 },
|
||||
{ 0x2, 0x3, 0x4, 0xb, 0x6, 0x4 },
|
||||
{ 0xa, 0x7, 0xd, 0x12, 0x9, 0x5 },
|
||||
{ 0x13, 0xa, 0x11, 0xf, 0xe, 0x3 },
|
||||
{ 0x10, 0x5, 0x8, 0xb, 0x3, 0x2 },
|
||||
{ 0xa, 0x3, 0x4, 0x2, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_7[6][6] = {
|
||||
{ 1, 3, 6, 7, 7, 8 },
|
||||
{ 3, 4, 5, 7, 7, 8 },
|
||||
{ 6, 6, 7, 8, 8, 9 },
|
||||
{ 8, 7, 8, 9, 9, 10 },
|
||||
{ 8, 7, 8, 9, 9, 10 },
|
||||
{ 9, 8, 9, 9, 10, 10 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_8[6][6] = {
|
||||
{ 0x3, 0x5, 0x7, 0x13, 0xd, 0xc },
|
||||
{ 0x4, 0x1, 0x3, 0x11, 0x5, 0x4 },
|
||||
{ 0x6, 0x2, 0x5, 0xf, 0x8, 0x4 },
|
||||
{ 0x12, 0x10, 0xe, 0xd, 0xb, 0x1 },
|
||||
{ 0xc, 0x9, 0x7, 0xa, 0x5, 0x1 },
|
||||
{ 0x5, 0x3, 0x3, 0x4, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_8[6][6] = {
|
||||
{ 2, 3, 6, 8, 8, 9 },
|
||||
{ 3, 2, 4, 8, 7, 8 },
|
||||
{ 6, 4, 6, 8, 8, 9 },
|
||||
{ 8, 8, 8, 9, 9, 9 },
|
||||
{ 8, 8, 8, 9, 10, 11 },
|
||||
{ 9, 8, 9, 10, 10, 11 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_9[6][6] = {
|
||||
{ 0x7, 0x6, 0x7, 0xf, 0xb, 0xe },
|
||||
{ 0x5, 0x4, 0x6, 0x6, 0x7, 0x4 },
|
||||
{ 0x9, 0x5, 0x8, 0x9, 0x9, 0x6 },
|
||||
{ 0xe, 0x5, 0x8, 0xa, 0x6, 0x2 },
|
||||
{ 0xf, 0x6, 0x8, 0x5, 0x4, 0x6 },
|
||||
{ 0x7, 0x7, 0x5, 0x1, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_9[6][6] = {
|
||||
{ 3, 3, 4, 6, 7, 8 },
|
||||
{ 3, 3, 4, 5, 6, 7 },
|
||||
{ 5, 4, 5, 6, 7, 8 },
|
||||
{ 6, 5, 6, 7, 7, 8 },
|
||||
{ 8, 6, 7, 7, 8, 9 },
|
||||
{ 9, 8, 8, 8, 9, 9 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_10[8][8] = {
|
||||
{ 0x1, 0x3, 0xb, 0xe, 0x14, 0x1f, 0xe, 0x9 },
|
||||
{ 0x2, 0x3, 0x9, 0xd, 0x13, 0x16, 0xd, 0x8 },
|
||||
{ 0xa, 0x8, 0xf, 0x16, 0x21, 0x29, 0xa, 0x7 },
|
||||
{ 0x17, 0xc, 0x15, 0x22, 0x2f, 0x1a, 0xb, 0x8 },
|
||||
{ 0x23, 0x12, 0x20, 0x2e, 0x1b, 0x15, 0x10, 0x4 },
|
||||
{ 0x1e, 0x15, 0x28, 0x17, 0x16, 0x14, 0x6, 0x4 },
|
||||
{ 0xc, 0xc, 0x13, 0x12, 0x9, 0x5, 0x5, 0x2 },
|
||||
{ 0x11, 0x7, 0x6, 0x7, 0x3, 0x3, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_10[8][8] = {
|
||||
{ 1, 3, 6, 7, 8, 9, 8, 9 },
|
||||
{ 3, 4, 6, 7, 8, 9, 8, 8 },
|
||||
{ 6, 6, 7, 8, 9, 10, 9, 9 },
|
||||
{ 8, 7, 8, 9, 10, 10, 10, 10 },
|
||||
{ 9, 8, 9, 10, 10, 11, 10, 10 },
|
||||
{ 9, 9, 10, 10, 10, 11, 10, 11 },
|
||||
{ 9, 8, 9, 9, 10, 10, 11, 11 },
|
||||
{ 10, 8, 9, 10, 10, 11, 11, 11 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_11[8][8] = {
|
||||
{ 0x3, 0x5, 0xb, 0x19, 0x23, 0x1c, 0xe, 0xb },
|
||||
{ 0x4, 0x3, 0x7, 0xb, 0x21, 0x1a, 0xc, 0x4 },
|
||||
{ 0xa, 0x4, 0xd, 0x13, 0x1f, 0x20, 0x9, 0x6 },
|
||||
{ 0x18, 0xa, 0x12, 0x3b, 0x3a, 0x13, 0xd, 0x6 },
|
||||
{ 0x22, 0x20, 0x1e, 0x1b, 0x1e, 0x11, 0xe, 0x6 },
|
||||
{ 0x21, 0x11, 0x1f, 0x12, 0x10, 0xf, 0x9, 0x3 },
|
||||
{ 0x15, 0xb, 0x14, 0xc, 0x7, 0x8, 0x4, 0x2 },
|
||||
{ 0xf, 0xa, 0x5, 0x5, 0x5, 0xe, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_11[8][8] = {
|
||||
{ 2, 3, 5, 7, 8, 8, 8, 8 },
|
||||
{ 3, 3, 5, 6, 8, 8, 7, 7 },
|
||||
{ 5, 4, 6, 7, 8, 9, 7, 8 },
|
||||
{ 7, 6, 7, 9, 9, 10, 8, 9 },
|
||||
{ 8, 8, 8, 8, 9, 10, 9, 10 },
|
||||
{ 9, 8, 9, 10, 10, 11, 10, 10 },
|
||||
{ 8, 7, 8, 8, 9, 10, 10, 10 },
|
||||
{ 9, 8, 8, 9, 10, 11, 10, 10 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_12[8][8] = {
|
||||
{ 0x9, 0x7, 0x11, 0x11, 0x20, 0x28, 0x1b, 0x1b },
|
||||
{ 0x6, 0x5, 0x7, 0xa, 0xd, 0x11, 0xc, 0xc },
|
||||
{ 0x10, 0x6, 0xb, 0xf, 0x16, 0x1f, 0xb, 0x8 },
|
||||
{ 0x21, 0x9, 0xe, 0xc, 0x13, 0x1d, 0xf, 0xc },
|
||||
{ 0x29, 0x17, 0x15, 0x12, 0x12, 0x11, 0xa, 0x6 },
|
||||
{ 0x27, 0x10, 0x1e, 0x1c, 0x10, 0xd, 0x7, 0x3 },
|
||||
{ 0x26, 0x1a, 0xa, 0xe, 0x9, 0x4, 0x4, 0x1 },
|
||||
{ 0x1a, 0xb, 0x7, 0x5, 0x5, 0x2, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_12[8][8] = {
|
||||
{ 4, 3, 5, 6, 7, 8, 8, 9 },
|
||||
{ 3, 3, 4, 5, 6, 7, 7, 8 },
|
||||
{ 5, 4, 5, 6, 7, 8, 7, 8 },
|
||||
{ 7, 5, 6, 6, 7, 8, 8, 9 },
|
||||
{ 8, 7, 7, 7, 8, 8, 8, 9 },
|
||||
{ 9, 7, 8, 8, 8, 9, 9, 9 },
|
||||
{ 9, 8, 7, 8, 8, 8, 9, 9 },
|
||||
{ 9, 8, 8, 8, 9, 9, 10, 10 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_13[16][16] = {
|
||||
{ 0x1, 0x3, 0xf, 0x16, 0x23, 0x3a, 0x2f, 0x48, 0x2b, 0x35, 0x23, 0x35, 0x22, 0x2d, 0x30, 0x10 },
|
||||
{ 0x5, 0x4, 0xd, 0x14, 0x10, 0x1b, 0x2d, 0x22, 0x14, 0x19, 0x21, 0x19, 0x20, 0x15, 0x17, 0xf },
|
||||
{ 0xe, 0xc, 0x17, 0x25, 0x3c, 0x32, 0x4e, 0x38, 0x1e, 0x29, 0x1f, 0x17, 0x1c, 0x22, 0x14, 0x11 },
|
||||
{ 0x15, 0x13, 0x24, 0x3d, 0x39, 0x60, 0x4a, 0x5f, 0x2c, 0x25, 0x39, 0x26, 0x27, 0x40, 0x27, 0x1b },
|
||||
{ 0x22, 0x1f, 0x3b, 0x38, 0x61, 0x4c, 0x73, 0x5c, 0x37, 0x2c, 0x2a, 0x46, 0x31, 0x38, 0x24, 0x19 },
|
||||
{ 0x33, 0x1a, 0x31, 0x4f, 0x4b, 0x46, 0x5e, 0x55, 0x4e, 0x3b, 0x52, 0x3c, 0x4b, 0x32, 0x23, 0x14 },
|
||||
{ 0x2e, 0x2c, 0x4d, 0x49, 0x72, 0x5d, 0x5a, 0x5b, 0x48, 0x36, 0x48, 0x33, 0x1e, 0x31, 0x35, 0x1d },
|
||||
{ 0x47, 0x21, 0x41, 0x40, 0x5b, 0x54, 0x4f, 0x5a, 0x57, 0x51, 0x50, 0x24, 0x34, 0x2d, 0x15, 0xb },
|
||||
{ 0x2a, 0x1f, 0x1d, 0x2b, 0x36, 0x4d, 0x45, 0x56, 0x4e, 0x42, 0x2f, 0x37, 0x30, 0x1f, 0x10, 0x11 },
|
||||
{ 0x34, 0x18, 0x28, 0x4c, 0x49, 0x3a, 0x53, 0x49, 0x3d, 0x4c, 0x3a, 0x1a, 0x28, 0x13, 0x17, 0xc },
|
||||
{ 0x44, 0x20, 0x1e, 0x38, 0x37, 0x4f, 0x47, 0x4d, 0x2e, 0x39, 0x37, 0x22, 0x34, 0xc, 0xd, 0x10 },
|
||||
{ 0x34, 0x18, 0x28, 0x25, 0x29, 0x1d, 0x32, 0x41, 0x36, 0x36, 0x15, 0x17, 0x1c, 0xf, 0xa, 0x8 },
|
||||
{ 0x43, 0x1f, 0x1b, 0x1a, 0x30, 0x4a, 0x3b, 0x33, 0x25, 0x25, 0x16, 0x1b, 0x12, 0xa, 0x6, 0x1 },
|
||||
{ 0x2c, 0x23, 0x21, 0x1f, 0x35, 0x31, 0x26, 0x2c, 0x1e, 0x12, 0x1a, 0xe, 0x11, 0x7, 0x1, 0x1 },
|
||||
{ 0x2b, 0x16, 0x2a, 0x19, 0x17, 0x29, 0x24, 0x2b, 0x14, 0x27, 0x26, 0x9, 0x9, 0x6, 0x4, 0x0 },
|
||||
{ 0x13, 0xe, 0x10, 0xe, 0x18, 0x11, 0xf, 0x2a, 0x10, 0xb, 0x16, 0x7, 0x5, 0x3, 0x2, 0x1 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_13[16][16] = {
|
||||
{ 1, 3, 6, 7, 8, 9, 9, 10, 9, 10, 10, 11, 11, 12, 13, 12 },
|
||||
{ 4, 4, 6, 7, 7, 8, 9, 9, 8, 9, 10, 10, 11, 11, 12, 12 },
|
||||
{ 6, 6, 7, 8, 9, 9, 10, 10, 9, 10, 10, 10, 11, 12, 12, 13 },
|
||||
{ 7, 7, 8, 9, 9, 10, 10, 11, 10, 10, 11, 11, 12, 13, 13, 14 },
|
||||
{ 8, 8, 9, 9, 10, 10, 11, 11, 10, 11, 11, 12, 12, 13, 13, 14 },
|
||||
{ 9, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14 },
|
||||
{ 9, 9, 10, 10, 11, 11, 11, 12, 11, 11, 12, 12, 12, 14, 15, 15 },
|
||||
{ 10, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 12, 13, 14, 14, 14 },
|
||||
{ 9, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15 },
|
||||
{ 10, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 17, 15 },
|
||||
{ 11, 10, 10, 11, 11, 12, 12, 13, 12, 13, 14, 13, 15, 14, 15, 16 },
|
||||
{ 11, 10, 11, 11, 12, 11, 12, 13, 13, 14, 13, 14, 15, 15, 15, 16 },
|
||||
{ 12, 11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 15, 15, 16, 15, 19 },
|
||||
{ 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 15, 17, 18 },
|
||||
{ 13, 12, 13, 13, 13, 14, 14, 16, 15, 16, 16, 15, 16, 16, 16, 19 },
|
||||
{ 13, 12, 13, 13, 14, 14, 14, 16, 15, 15, 17, 16, 16, 16, 16, 16 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_15[16][16] = {
|
||||
{ 0x7, 0xd, 0x13, 0x1d, 0x34, 0x4d, 0x7d, 0x6d, 0x5a, 0x47, 0x6d, 0x56, 0x76, 0x5b, 0x7b, 0x47 },
|
||||
{ 0xc, 0x5, 0x11, 0x1c, 0x16, 0x25, 0x20, 0x35, 0x2b, 0x22, 0x35, 0x2a, 0x44, 0x2c, 0x3c, 0x25 },
|
||||
{ 0x12, 0x10, 0xf, 0x19, 0x2a, 0x23, 0x3c, 0x31, 0x29, 0x43, 0x33, 0x28, 0x1e, 0x27, 0x3a, 0x22 },
|
||||
{ 0x35, 0x1b, 0x18, 0x2b, 0x28, 0x42, 0x38, 0x5e, 0x4d, 0x3c, 0x2f, 0x25, 0x37, 0x26, 0x35, 0x1e },
|
||||
{ 0x2f, 0x2e, 0x29, 0x27, 0x43, 0x3a, 0x32, 0x58, 0x49, 0x3a, 0x5a, 0x46, 0x32, 0x22, 0x2f, 0x1c },
|
||||
{ 0x4c, 0x24, 0x22, 0x3f, 0x39, 0x34, 0x5c, 0x4b, 0x3f, 0x31, 0x52, 0x40, 0x2e, 0x3f, 0x2b, 0x14 },
|
||||
{ 0x7c, 0x3d, 0x3b, 0x37, 0x5f, 0x5b, 0x4e, 0x42, 0x38, 0x58, 0x3a, 0x34, 0x4a, 0x34, 0x20, 0x11 },
|
||||
{ 0x6c, 0x33, 0x30, 0x5d, 0x4f, 0x4a, 0x41, 0x7a, 0x5c, 0x4c, 0x39, 0x2b, 0x41, 0x2d, 0x16, 0x1a },
|
||||
{ 0x59, 0x2a, 0x28, 0x4c, 0x48, 0x3e, 0x37, 0x5b, 0x4d, 0x43, 0x30, 0x46, 0x31, 0x1f, 0x25, 0x15 },
|
||||
{ 0x7b, 0x46, 0x40, 0x3b, 0x39, 0x30, 0x57, 0x49, 0x42, 0x6a, 0x48, 0x37, 0x27, 0x34, 0x18, 0x10 },
|
||||
{ 0x6c, 0x34, 0x32, 0x5d, 0x59, 0x4f, 0x47, 0x38, 0x2f, 0x47, 0x39, 0x2a, 0x18, 0x1c, 0x11, 0xa },
|
||||
{ 0x77, 0x53, 0x4e, 0x48, 0x45, 0x3f, 0x33, 0x2a, 0x43, 0x36, 0x29, 0x19, 0x10, 0x13, 0xc, 0x6 },
|
||||
{ 0x6b, 0x41, 0x3e, 0x36, 0x31, 0x5a, 0x49, 0x40, 0x30, 0x26, 0x17, 0x1d, 0x16, 0xe, 0xf, 0x8 },
|
||||
{ 0x51, 0x29, 0x50, 0x4b, 0x42, 0x3e, 0x33, 0x2c, 0x35, 0x27, 0x1b, 0x12, 0xd, 0x8, 0xa, 0x6 },
|
||||
{ 0x7a, 0x3b, 0x38, 0x32, 0x2e, 0x28, 0x46, 0x15, 0x24, 0x17, 0x3e, 0xb, 0xe, 0x9, 0x2, 0x2 },
|
||||
{ 0x3f, 0x24, 0x21, 0x1d, 0x1b, 0x26, 0x1e, 0x19, 0x14, 0xf, 0x9, 0xb, 0x7, 0x3, 0x1, 0x0 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_15[16][16] = {
|
||||
{ 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 10, 11, 11, 12, 12 },
|
||||
{ 4, 3, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11 },
|
||||
{ 5, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 11, 11 },
|
||||
{ 7, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 10, 10, 11, 11 },
|
||||
{ 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11 },
|
||||
{ 8, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11 },
|
||||
{ 9, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11 },
|
||||
{ 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12 },
|
||||
{ 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12 },
|
||||
{ 10, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12 },
|
||||
{ 10, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12 },
|
||||
{ 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12 },
|
||||
{ 11, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 13, 13 },
|
||||
{ 11, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13 },
|
||||
{ 12, 11, 11, 11, 11, 11, 12, 11, 12, 12, 13, 12, 13, 13, 12, 13 },
|
||||
{ 13, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_16[16][16] = {
|
||||
{ 0x1, 0x3, 0xf, 0x2d, 0x4b, 0x42, 0x6f, 0x62, 0x55, 0x9a, 0x8b, 0xf3, 0xca, 0x2eb, 0x179, 0xc },
|
||||
{ 0x5, 0x4, 0xd, 0x15, 0x24, 0x1e, 0x36, 0x30, 0x54, 0x4c, 0x81, 0x78, 0xe0, 0xd3, 0x171, 0xa },
|
||||
{ 0xe, 0xc, 0x17, 0x27, 0x44, 0x3b, 0x34, 0x5b, 0x51, 0x49, 0x43, 0x76, 0xde, 0xd2, 0x66, 0x7 },
|
||||
{ 0x2c, 0x14, 0x26, 0x45, 0x41, 0x38, 0x64, 0x58, 0x9f, 0x8d, 0x7d, 0x73, 0xda, 0xd0, 0xbb, 0xb },
|
||||
{ 0x4a, 0x23, 0x43, 0x40, 0x73, 0x66, 0xb8, 0xa5, 0x9c, 0x83, 0xf7, 0xe3, 0xd8, 0x172, 0x2d6, 0xa },
|
||||
{ 0x3f, 0x3e, 0x3a, 0x72, 0x65, 0xb9, 0xb2, 0x9d, 0x8f, 0x100, 0xe9, 0xdf, 0x185, 0x17b, 0x2d2, 0x11 },
|
||||
{ 0x6e, 0x35, 0x67, 0x63, 0xb3, 0xad, 0xa0, 0x94, 0x104, 0xf5, 0xe5, 0x18c, 0x182, 0x2de, 0x166, 0xb },
|
||||
{ 0x5d, 0x2f, 0x5a, 0x57, 0xa4, 0x109, 0x85, 0x105, 0xf9, 0x1aa, 0xdb, 0x2ea, 0x17d, 0x2d3, 0x2c7, 0x9 },
|
||||
{ 0xac, 0x53, 0xa1, 0x9e, 0x9b, 0x8e, 0x101, 0xf8, 0x1ab, 0x196, 0x189, 0x2e6, 0x16c, 0x2ca, 0x2c5, 0xd },
|
||||
{ 0x95, 0x4b, 0x48, 0x8c, 0x108, 0xfd, 0xf4, 0x197, 0x191, 0x18a, 0x2e7, 0x2e0, 0x378, 0x6c7, 0x362, 0xc },
|
||||
{ 0x8a, 0x44, 0x7f, 0xfc, 0xf6, 0xe8, 0xe4, 0x18d, 0x188, 0x180, 0x2e1, 0x2d1, 0x1bb, 0x373, 0x6c6, 0xa },
|
||||
{ 0xf2, 0x77, 0x75, 0xd4, 0xe2, 0x190, 0xd9, 0x174, 0x17f, 0x2df, 0x2d0, 0x2c8, 0x2c3, 0x36d, 0x367, 0x7 },
|
||||
{ 0xe1, 0xc9, 0x6e, 0xc7, 0x18b, 0x184, 0x181, 0x17c, 0x2d7, 0x167, 0x375, 0x2c2, 0x1b8, 0x36c, 0xd82, 0x5 },
|
||||
{ 0xc3, 0x6b, 0xd1, 0x183, 0x17e, 0x17a, 0x16e, 0x379, 0x2c9, 0x2c6, 0x372, 0xdf, 0x1b5, 0xd83, 0x366, 0x3 },
|
||||
{ 0x178, 0xcf, 0xce, 0x16d, 0x16a, 0x1bd, 0x2cb, 0x374, 0x2c4, 0x160, 0x1b7, 0x1b4, 0x6c0, 0x361, 0x1b2, 0x1 },
|
||||
{ 0x11, 0x9, 0x10, 0x1a, 0x9, 0x10, 0xa, 0x8, 0x7, 0xb, 0x4, 0x6, 0x4, 0x2, 0x0, 0x3 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_16[16][16] = {
|
||||
{ 1, 3, 6, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 14, 13, 9 },
|
||||
{ 4, 4, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 8 },
|
||||
{ 6, 6, 7, 8, 9, 9, 9, 10, 10, 10, 10, 11, 12, 12, 11, 8 },
|
||||
{ 8, 7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 9 },
|
||||
{ 9, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 14, 9 },
|
||||
{ 9, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 10 },
|
||||
{ 10, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 13, 10 },
|
||||
{ 10, 9, 10, 10, 11, 12, 11, 12, 12, 13, 12, 14, 13, 14, 14, 10 },
|
||||
{ 11, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, 13, 14, 14, 11 },
|
||||
{ 11, 10, 10, 11, 12, 12, 12, 13, 13, 13, 14, 14, 15, 16, 15, 11 },
|
||||
{ 11, 10, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 16, 11 },
|
||||
{ 12, 11, 11, 12, 12, 13, 12, 13, 13, 14, 14, 14, 14, 15, 15, 11 },
|
||||
{ 12, 12, 11, 12, 13, 13, 13, 13, 14, 13, 15, 14, 14, 15, 17, 11 },
|
||||
{ 12, 11, 12, 13, 13, 13, 13, 15, 14, 14, 15, 13, 14, 17, 15, 11 },
|
||||
{ 13, 12, 12, 13, 13, 14, 14, 15, 14, 13, 14, 14, 16, 15, 14, 11 },
|
||||
{ 9, 8, 9, 10, 9, 10, 10, 10, 10, 11, 10, 11, 11, 11, 11, 8 }
|
||||
};
|
||||
static const uint16_t mp3enc_hcode_24[16][16] = {
|
||||
{ 0xf, 0xe, 0x2f, 0x51, 0x93, 0x107, 0xf9, 0x1b3, 0x1ab, 0x14f, 0x29c, 0x28c, 0x288, 0x26c, 0x409, 0x2b },
|
||||
{ 0xd, 0xc, 0x16, 0x27, 0x48, 0x42, 0x7b, 0x73, 0xd4, 0xc7, 0xb8, 0x15a, 0x142, 0x12c, 0x118, 0x14 },
|
||||
{ 0x2e, 0x15, 0x29, 0x4b, 0x45, 0x81, 0x79, 0x6f, 0xd0, 0xc5, 0xb7, 0xab, 0x13c, 0x128, 0x116, 0x13 },
|
||||
{ 0x50, 0x26, 0x4a, 0x46, 0x87, 0x7e, 0x75, 0x6d, 0xcd, 0xbf, 0xb3, 0xa8, 0x138, 0x126, 0x112, 0x11 },
|
||||
{ 0x92, 0x47, 0x44, 0x86, 0x7f, 0x77, 0x71, 0xd3, 0xc9, 0xbd, 0xaf, 0xa4, 0x133, 0x120, 0x10b, 0xf },
|
||||
{ 0x106, 0x82, 0x80, 0x7d, 0x76, 0x72, 0xd7, 0xcb, 0xc1, 0xb5, 0x158, 0x13e, 0x12e, 0x11a, 0x108, 0xd },
|
||||
{ 0xf8, 0x7a, 0x78, 0x74, 0x70, 0xd6, 0xce, 0xc4, 0xba, 0xae, 0x14b, 0x135, 0x124, 0x111, 0x103, 0xb },
|
||||
{ 0x1b2, 0xd8, 0xdd, 0xdc, 0xd2, 0xca, 0xc3, 0xbb, 0xb1, 0x14d, 0x13a, 0x12b, 0x11c, 0x10a, 0x17e, 0x9 },
|
||||
{ 0x1aa, 0xd1, 0xcf, 0xcc, 0xc8, 0xc0, 0xb9, 0x161, 0xa9, 0x141, 0x130, 0x11f, 0x10d, 0x203, 0x17a, 0x7 },
|
||||
{ 0x29d, 0xc6, 0xc2, 0xbe, 0xbc, 0xb4, 0x15b, 0x14c, 0x140, 0x131, 0x122, 0x114, 0x105, 0x17c, 0x174, 0x6 },
|
||||
{ 0x28d, 0x147, 0xb6, 0xb2, 0x160, 0x155, 0x14a, 0x139, 0x12f, 0x121, 0x115, 0x107, 0x200, 0x176, 0x16f, 0x4 },
|
||||
{ 0x289, 0x159, 0x154, 0x145, 0x143, 0x13d, 0x134, 0x12a, 0x11e, 0x113, 0x212, 0x201, 0x178, 0x171, 0x16b, 0x7 },
|
||||
{ 0x26d, 0x13f, 0x13b, 0x137, 0x132, 0x12d, 0x123, 0x11b, 0x10c, 0x209, 0x17f, 0x177, 0x172, 0x16d, 0x168, 0x5 },
|
||||
{ 0x205, 0x129, 0x127, 0x125, 0x11d, 0x119, 0x110, 0x213, 0x202, 0x17b, 0x175, 0x170, 0x16c, 0x169, 0x166, 0x3 },
|
||||
{ 0x408, 0x117, 0x21d, 0x10f, 0x21c, 0x106, 0x208, 0x17d, 0x179, 0x173, 0x16e, 0x16a, 0x167, 0x165, 0x164, 0x1 },
|
||||
{ 0x58, 0x2a, 0x12, 0x10, 0xe, 0xc, 0xa, 0x11, 0x10, 0xb, 0xa, 0x6, 0x4, 0x2, 0x0, 0x3 }
|
||||
};
|
||||
static const uint8_t mp3enc_hlen_24[16][16] = {
|
||||
{ 4, 4, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 8 },
|
||||
{ 4, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 7 },
|
||||
{ 6, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 7 },
|
||||
{ 7, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 7 },
|
||||
{ 8, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 7 },
|
||||
{ 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 7 },
|
||||
{ 9, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 7 },
|
||||
{ 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 7 },
|
||||
{ 10, 9, 9, 9, 9, 9, 9, 10, 9, 10, 10, 10, 10, 11, 11, 7 },
|
||||
{ 11, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 7 },
|
||||
{ 11, 10, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 7 },
|
||||
{ 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8 },
|
||||
{ 11, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 8 },
|
||||
{ 11, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 8 },
|
||||
{ 12, 10, 11, 10, 11, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8 },
|
||||
{ 9, 8, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 4 }
|
||||
};
|
||||
static const uint8_t mp3enc_count1a_code[16] = { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 };
|
||||
static const uint8_t mp3enc_count1a_len[16] = { 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6 };
|
||||
static const uint8_t mp3enc_count1b_code[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
static const uint8_t mp3enc_count1b_len[16] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
@@ -0,0 +1,591 @@
|
||||
#pragma once
|
||||
// mp3enc.h
|
||||
// MPEG1 Layer III MP3 encoder, CBR, 32/44.1/48 kHz, mono/stereo.
|
||||
// MIT license.
|
||||
//
|
||||
// Usage:
|
||||
// mp3enc_t * enc = mp3enc_init(44100, 2, 128);
|
||||
// while (have_audio) {
|
||||
// const uint8_t * mp3 = mp3enc_encode(enc, pcm, samples, &size);
|
||||
// fwrite(mp3, 1, size, fp);
|
||||
// }
|
||||
// const uint8_t * mp3 = mp3enc_flush(enc, &size);
|
||||
// fwrite(mp3, 1, size, fp);
|
||||
// mp3enc_free(enc);
|
||||
//
|
||||
// PCM input: planar float [ch0: N samples] [ch1: N samples]
|
||||
// Output: raw MP3 frames (no ID3 tags)
|
||||
//
|
||||
// MIT license.
|
||||
|
||||
// clang-format off
|
||||
// Order matters: tables.h defines constants used by all other headers.
|
||||
#include "mp3enc-tables.h"
|
||||
#include "mp3enc-bits.h"
|
||||
#include "mp3enc-filter.h"
|
||||
#include "mp3enc-huff.h"
|
||||
#include "mp3enc-mdct.h"
|
||||
#include "mp3enc-psy.h"
|
||||
#include "mp3enc-quant.h"
|
||||
// clang-format on
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
// Encoder state.
|
||||
struct mp3enc_t {
|
||||
// Config
|
||||
int sample_rate;
|
||||
int channels;
|
||||
int bitrate_kbps;
|
||||
int sr_index; // 0=44100, 1=48000, 2=32000
|
||||
|
||||
// Frame geometry
|
||||
int frame_samples; // always 1152 for MPEG1 Layer III
|
||||
int slots_per_frame; // frame size in bytes (varies with padding)
|
||||
|
||||
// Per channel state
|
||||
mp3enc_filter filter[2]; // analysis filterbank
|
||||
float sb_prev[2][32][18]; // subband overlap memory
|
||||
float sb_cur[2][32][18]; // current granule subbands
|
||||
mp3enc_psy psy; // psychoacoustic model
|
||||
|
||||
// Bit reservoir (ISO 11172-3, clause 2.4.2.7).
|
||||
// Tracks unused bits from previous frames that can be borrowed.
|
||||
int resv_size; // current reservoir size in bits
|
||||
int resv_max; // max: 511 bytes * 8 = 4088 bits
|
||||
|
||||
// Adaptive lowpass: MDCT line index above which coefficients are zeroed.
|
||||
// Saves bits at low bitrates by not encoding inaudible HF content.
|
||||
int lowpass_line;
|
||||
|
||||
// PCM input buffer (accumulates until we have 1152 samples)
|
||||
float * pcm_buf; // interleaved buffer: [ch0_1152][ch1_1152]
|
||||
int pcm_fill; // samples accumulated per channel
|
||||
|
||||
// Output buffer (holds accumulated MP3 frames for one encode call)
|
||||
uint8_t * out_buf;
|
||||
int out_capacity;
|
||||
int out_written;
|
||||
|
||||
// Scratch buffer for one frame (max ~1441 bytes at 320kbps/32kHz)
|
||||
uint8_t frame_buf[2048];
|
||||
|
||||
// Main data scratch: written separately from header+sideinfo for reservoir
|
||||
uint8_t md_scratch[2048];
|
||||
|
||||
// Pending frame: we delay output by one frame so we can write the next
|
||||
// frame's main_data overflow into the current frame's unused tail.
|
||||
// This is how the bit reservoir works (ISO 11172-3 clause 2.4.2.7).
|
||||
uint8_t pending_frame[2048];
|
||||
int pending_bytes; // size of pending frame (0 = no pending frame)
|
||||
int pending_md_end; // byte offset where main_data ends in pending_frame
|
||||
|
||||
// Padding state (for 44100 Hz which needs alternating padding)
|
||||
int pad_remainder;
|
||||
};
|
||||
|
||||
// Initialize encoder.
|
||||
static mp3enc_t * mp3enc_init(int sample_rate, int channels, int bitrate_kbps) {
|
||||
mp3enc_t * enc = (mp3enc_t *) calloc(1, sizeof(mp3enc_t));
|
||||
if (!enc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enc->sample_rate = sample_rate;
|
||||
enc->channels = channels;
|
||||
enc->bitrate_kbps = bitrate_kbps;
|
||||
enc->frame_samples = 1152;
|
||||
|
||||
// Determine sample rate index
|
||||
if (sample_rate == 44100) {
|
||||
enc->sr_index = 0;
|
||||
} else if (sample_rate == 48000) {
|
||||
enc->sr_index = 1;
|
||||
} else if (sample_rate == 32000) {
|
||||
enc->sr_index = 2;
|
||||
} else {
|
||||
free(enc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Init subsystems
|
||||
for (int ch = 0; ch < channels; ch++) {
|
||||
enc->filter[ch].init();
|
||||
}
|
||||
memset(enc->sb_prev, 0, sizeof(enc->sb_prev));
|
||||
enc->psy.init();
|
||||
enc->psy.init_ath(enc->sr_index, mp3enc_sfb_long[enc->sr_index], sample_rate);
|
||||
|
||||
// Bit reservoir: max 511 bytes (9 bit field main_data_begin)
|
||||
enc->resv_size = 0;
|
||||
enc->resv_max = 511 * 8;
|
||||
|
||||
// Adaptive lowpass: cut HF that wastes bits at low bitrates.
|
||||
// Cutoff per total bitrate in Hz. Higher bitrates preserve more bandwidth.
|
||||
{
|
||||
static const struct {
|
||||
int kbps;
|
||||
int hz;
|
||||
} lp_table[] = {
|
||||
{ 8, 2000 },
|
||||
{ 16, 3700 },
|
||||
{ 24, 3900 },
|
||||
{ 32, 5500 },
|
||||
{ 40, 7000 },
|
||||
{ 48, 7500 },
|
||||
{ 56, 10000 },
|
||||
{ 64, 11000 },
|
||||
{ 80, 13500 },
|
||||
{ 96, 15100 },
|
||||
{ 112, 15600 },
|
||||
{ 128, 17000 },
|
||||
{ 160, 17500 },
|
||||
{ 192, 18600 },
|
||||
{ 224, 19400 },
|
||||
{ 256, 19700 },
|
||||
{ 320, 20500 }
|
||||
};
|
||||
|
||||
static const int lp_count = (int) (sizeof(lp_table) / sizeof(lp_table[0]));
|
||||
|
||||
// Find nearest bitrate in table
|
||||
int best = 0;
|
||||
int best_dist = 999;
|
||||
for (int i = 0; i < lp_count; i++) {
|
||||
int dist = abs(bitrate_kbps - lp_table[i].kbps);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
float cutoff_hz = (float) lp_table[best].hz;
|
||||
|
||||
// MDCT line corresponding to cutoff: 576 lines cover 0..samplerate/2
|
||||
float freq_per_line = (float) sample_rate / (2.0f * 576.0f);
|
||||
enc->lowpass_line = (int) (cutoff_hz / freq_per_line);
|
||||
if (enc->lowpass_line > 576) {
|
||||
enc->lowpass_line = 576;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate buffers
|
||||
enc->pcm_buf = (float *) calloc(1152 * channels, sizeof(float));
|
||||
enc->pcm_fill = 0;
|
||||
|
||||
enc->out_capacity = 2048;
|
||||
enc->out_buf = (uint8_t *) malloc(enc->out_capacity);
|
||||
enc->out_written = 0;
|
||||
|
||||
enc->pad_remainder = 0;
|
||||
|
||||
// No pending frame at start
|
||||
enc->pending_bytes = 0;
|
||||
enc->pending_md_end = 0;
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
// Free encoder.
|
||||
static void mp3enc_free(mp3enc_t * enc) {
|
||||
if (!enc) {
|
||||
return;
|
||||
}
|
||||
free(enc->pcm_buf);
|
||||
free(enc->out_buf);
|
||||
free(enc);
|
||||
}
|
||||
|
||||
// Compute padding for this frame (needed at 44100 Hz).
|
||||
static int mp3enc_get_padding(mp3enc_t * enc) {
|
||||
int dif = (144 * enc->bitrate_kbps * 1000) % enc->sample_rate;
|
||||
enc->pad_remainder -= dif;
|
||||
if (enc->pad_remainder < 0) {
|
||||
enc->pad_remainder += enc->sample_rate;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Encode one complete frame (1152 samples per channel).
|
||||
// pcm: planar float [ch0: 1152 samples][ch1: 1152 samples]
|
||||
// Returns number of bytes written to enc->frame_buf.
|
||||
static int mp3enc_encode_frame(mp3enc_t * enc, const float * pcm) {
|
||||
int nch = enc->channels;
|
||||
int padding = mp3enc_get_padding(enc);
|
||||
|
||||
// MS stereo decision is deferred until after MDCT energy analysis.
|
||||
// mode=1 (joint) allows switching M/S on or off per frame.
|
||||
// mode=0 (stereo) would force L/R always. mode=3 (mono).
|
||||
int mode = (nch == 1) ? 3 : 1;
|
||||
int mode_ext = 0; // set after MDCT energy analysis
|
||||
|
||||
// Setup header
|
||||
mp3enc_header hdr;
|
||||
hdr.bitrate_kbps = enc->bitrate_kbps;
|
||||
hdr.samplerate = enc->sample_rate;
|
||||
hdr.mode = mode;
|
||||
hdr.mode_ext = mode_ext;
|
||||
hdr.padding = padding;
|
||||
|
||||
int frame_bytes = hdr.frame_bytes();
|
||||
int side_info_bytes = (nch == 1) ? 17 : 32;
|
||||
int main_data_bytes = frame_bytes - 4 - side_info_bytes;
|
||||
int main_data_bits = main_data_bytes * 8;
|
||||
|
||||
// SFB tables for this sample rate
|
||||
const uint8_t * sfb_long = mp3enc_sfb_long[enc->sr_index];
|
||||
|
||||
// Process 2 granules (each is 576 samples = 18 subband slots of 32 samples)
|
||||
mp3enc_side_info si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
|
||||
// Cross-frame bit reservoir (ISO 11172-3 clause 2.4.2.7).
|
||||
// Unused bytes at the end of the previous frame can be borrowed by this frame.
|
||||
// The pending_frame holds the previous frame; its unused tail is the reservoir.
|
||||
int resv_bytes = 0;
|
||||
if (enc->pending_bytes > 0) {
|
||||
resv_bytes = enc->pending_bytes - enc->pending_md_end;
|
||||
if (resv_bytes < 0) {
|
||||
resv_bytes = 0;
|
||||
}
|
||||
if (resv_bytes > 511) {
|
||||
resv_bytes = 511;
|
||||
}
|
||||
}
|
||||
si.main_data_begin = resv_bytes;
|
||||
|
||||
// Total main_data bits: this frame's area + reservoir from previous frame
|
||||
int total_md_bits = main_data_bits + resv_bytes * 8;
|
||||
|
||||
// Phase 1: compute MDCT + psy for ALL granules before bit allocation.
|
||||
// We need PE from both granules to weight the bit budget.
|
||||
float mdct_all[2][2][576]; // [granule][channel][576 MDCT lines]
|
||||
float saved_xmin[2][2][MP3ENC_PSY_SFB_MAX];
|
||||
float saved_pe[2] = { 0.0f, 0.0f };
|
||||
|
||||
// Accumulators for MS stereo decision
|
||||
float energy_mid = 0.0f;
|
||||
float energy_side = 0.0f;
|
||||
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
int pcm_offset = gr * 576;
|
||||
|
||||
// filterbank + MDCT for all channels
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
const float * ch_pcm = pcm + ch * 1152 + pcm_offset;
|
||||
float sb_out[32];
|
||||
for (int slot = 0; slot < 18; slot++) {
|
||||
enc->filter[ch].process(ch_pcm + slot * 32, sb_out);
|
||||
for (int sb = 0; sb < 32; sb++) {
|
||||
enc->sb_cur[ch][sb][slot] = sb_out[sb];
|
||||
}
|
||||
// frequency inversion: negate odd subbands at odd time slots
|
||||
if (slot & 1) {
|
||||
for (int sb = 1; sb < 32; sb += 2) {
|
||||
enc->sb_cur[ch][sb][slot] = -enc->sb_cur[ch][sb][slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
mp3enc_mdct_granule(enc->sb_prev[ch], enc->sb_cur[ch], mdct_all[gr][ch]);
|
||||
memcpy(enc->sb_prev[ch], enc->sb_cur[ch], sizeof(enc->sb_cur[ch]));
|
||||
}
|
||||
|
||||
// MS stereo energy analysis (before transform, on L/R data).
|
||||
// Accumulate mid and side energy across both granules to decide
|
||||
// whether M/S coding is beneficial for this frame.
|
||||
// M/S wins when L and R are correlated (side energy is small).
|
||||
if (nch == 2) {
|
||||
for (int i = 0; i < enc->lowpass_line && i < 576; i++) {
|
||||
float l = mdct_all[gr][0][i];
|
||||
float r = mdct_all[gr][1][i];
|
||||
float m = l + r;
|
||||
float s = l - r;
|
||||
energy_mid += m * m;
|
||||
energy_side += s * s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MS stereo decision: use M/S when channels are correlated enough
|
||||
// that the side channel is cheap to encode. FhG "almost always uses
|
||||
// ms_stereo" (GPSYCHO docs). We use it unless side energy dominates,
|
||||
// which means the channels are very different (rare for music).
|
||||
bool use_ms = false;
|
||||
if (nch == 2) {
|
||||
// Use M/S unless side channel has more energy than mid.
|
||||
// This is generous -- almost always enables M/S (like FhG).
|
||||
use_ms = (energy_side < energy_mid * 1.2f) || (energy_mid < 1e-20f);
|
||||
mode_ext = use_ms ? 2 : 0;
|
||||
hdr.mode_ext = mode_ext;
|
||||
}
|
||||
|
||||
// Now apply M/S transform + lowpass + psy for both granules
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
// MS stereo transform
|
||||
if (use_ms) {
|
||||
static const float ms_scale = 0.7071067811865476f; // 1/sqrt(2)
|
||||
for (int i = 0; i < 576; i++) {
|
||||
float l = mdct_all[gr][0][i];
|
||||
float r = mdct_all[gr][1][i];
|
||||
mdct_all[gr][0][i] = (l + r) * ms_scale;
|
||||
mdct_all[gr][1][i] = (l - r) * ms_scale;
|
||||
}
|
||||
}
|
||||
|
||||
// adaptive lowpass
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
for (int i = enc->lowpass_line; i < 576; i++) {
|
||||
mdct_all[gr][ch][i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// psy: compute masking thresholds and perceptual entropy
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
enc->psy.compute(mdct_all[gr][ch], sfb_long, enc->sr_index, ch);
|
||||
memcpy(saved_xmin[gr][ch], enc->psy.xmin, sizeof(enc->psy.xmin));
|
||||
saved_pe[gr] += enc->psy.pe;
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: PE-weighted bit allocation + quantization.
|
||||
// Give more bits to granules with higher perceptual entropy (more complex
|
||||
// signal). ISO 11172-3 computes PE but then ignores it for allocation;
|
||||
// LAME uses it to drive the bit reservoir. We weight the per-granule
|
||||
// budget proportionally to PE, clamped to avoid starving either granule.
|
||||
int gr_budget[2];
|
||||
float pe_sum = saved_pe[0] + saved_pe[1];
|
||||
if (pe_sum > 1e-6f) {
|
||||
float frac0 = saved_pe[0] / pe_sum;
|
||||
gr_budget[0] = (int) ((float) total_md_bits * frac0);
|
||||
gr_budget[1] = total_md_bits - gr_budget[0];
|
||||
// clamp: neither granule gets less than 20% or more than 80%
|
||||
int lo = total_md_bits / 5;
|
||||
int hi = total_md_bits * 4 / 5;
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
if (gr_budget[gr] < lo) {
|
||||
gr_budget[gr] = lo;
|
||||
}
|
||||
if (gr_budget[gr] > hi) {
|
||||
gr_budget[gr] = hi;
|
||||
}
|
||||
}
|
||||
// re-normalize after clamp
|
||||
int clamped_sum = gr_budget[0] + gr_budget[1];
|
||||
int bits_to_spread = total_md_bits - clamped_sum;
|
||||
gr_budget[0] += bits_to_spread / 2;
|
||||
gr_budget[1] += bits_to_spread - bits_to_spread / 2;
|
||||
} else {
|
||||
gr_budget[0] = total_md_bits / 2;
|
||||
gr_budget[1] = total_md_bits - gr_budget[0];
|
||||
}
|
||||
|
||||
int ix[2][2][576];
|
||||
int total_bits_used = 0;
|
||||
int intra_resv = 0;
|
||||
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
int max_bits = gr_budget[gr] + intra_resv;
|
||||
|
||||
// don't exceed remaining budget
|
||||
int remaining_bits = total_md_bits - total_bits_used;
|
||||
if (max_bits > remaining_bits) {
|
||||
max_bits = remaining_bits;
|
||||
}
|
||||
if (max_bits > 4095 * nch) {
|
||||
max_bits = 4095 * nch;
|
||||
}
|
||||
|
||||
int bits_per_ch = max_bits / nch;
|
||||
|
||||
// quantize each channel with psy thresholds
|
||||
int gr_bits_used = 0;
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
int bits = mp3enc_outer_loop(mdct_all[gr][ch], ix[gr][ch], si.gr[gr][ch], saved_xmin[gr][ch], bits_per_ch,
|
||||
sfb_long, enc->sr_index, gr, si.scfsi[ch]);
|
||||
gr_bits_used += bits;
|
||||
}
|
||||
|
||||
// intra-frame savings: unused bits carry to next granule
|
||||
intra_resv += gr_budget[gr] - gr_bits_used;
|
||||
if (intra_resv < 0) {
|
||||
intra_resv = 0;
|
||||
}
|
||||
total_bits_used += gr_bits_used;
|
||||
}
|
||||
|
||||
// Write header + side_info to frame_buf
|
||||
mp3enc_bs hdr_bs;
|
||||
hdr_bs.init(enc->frame_buf, sizeof(enc->frame_buf));
|
||||
hdr.write(hdr_bs);
|
||||
si.write(hdr_bs, nch);
|
||||
int hdr_si_bytes = (hdr_bs.total_bits() + 7) / 8;
|
||||
|
||||
// Write main_data to md_scratch (separate buffer for reservoir assembly)
|
||||
mp3enc_bs md_bs;
|
||||
md_bs.init(enc->md_scratch, sizeof(enc->md_scratch));
|
||||
|
||||
for (int gr = 0; gr < 2; gr++) {
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
const mp3enc_granule_info & gi = si.gr[gr][ch];
|
||||
|
||||
// Scalefactors
|
||||
mp3enc_write_scalefactors(md_bs, gi, gr, nch, si.scfsi[ch]);
|
||||
|
||||
// Huffman data: big_values region (3 regions for long blocks)
|
||||
int prev_end = 0;
|
||||
for (int r = 0; r < 3; r++) {
|
||||
int reg_end;
|
||||
if (r == 0) {
|
||||
int acc = 0;
|
||||
for (int s = 0; s <= gi.region0_count; s++) {
|
||||
acc += sfb_long[s];
|
||||
}
|
||||
reg_end = (acc < gi.big_values * 2) ? acc : gi.big_values * 2;
|
||||
} else if (r == 1) {
|
||||
int acc = 0;
|
||||
for (int s = 0; s <= gi.region0_count + gi.region1_count + 1; s++) {
|
||||
acc += sfb_long[s];
|
||||
}
|
||||
reg_end = (acc < gi.big_values * 2) ? acc : gi.big_values * 2;
|
||||
} else {
|
||||
reg_end = gi.big_values * 2;
|
||||
}
|
||||
|
||||
int pairs = (reg_end - prev_end) / 2;
|
||||
for (int p = 0; p < pairs; p++) {
|
||||
int i = prev_end + p * 2;
|
||||
mp3enc_write_pair(md_bs, gi.table_select[r], ix[gr][ch][i], ix[gr][ch][i + 1]);
|
||||
}
|
||||
prev_end = reg_end;
|
||||
}
|
||||
|
||||
// Count1 region
|
||||
int c1_start = gi.big_values * 2;
|
||||
int nz_end = 576 - mp3enc_count_rzero(ix[gr][ch], 576) * 2;
|
||||
int c1_count = (nz_end - c1_start) / 4;
|
||||
mp3enc_write_count1(md_bs, ix[gr][ch], c1_start, c1_count, gi.count1table_select);
|
||||
}
|
||||
}
|
||||
int md_bytes = (md_bs.total_bits() + 7) / 8;
|
||||
|
||||
// Assemble output: write overflow to pending frame, output it, save current as pending.
|
||||
//
|
||||
// The first resv_bytes of main_data go into the previous frame's unused tail.
|
||||
// The rest goes into the current frame's main data area.
|
||||
// This is how the decoder's main_data_begin backpointer works.
|
||||
int output_bytes = 0;
|
||||
|
||||
if (enc->pending_bytes > 0) {
|
||||
// Write main_data overflow into pending frame's unused tail
|
||||
int overflow = (md_bytes < resv_bytes) ? md_bytes : resv_bytes;
|
||||
if (overflow > 0) {
|
||||
memcpy(enc->pending_frame + enc->pending_md_end, enc->md_scratch, overflow);
|
||||
}
|
||||
|
||||
// Grow out_buf if needed
|
||||
int need = enc->out_written + enc->pending_bytes + frame_bytes;
|
||||
if (need > enc->out_capacity) {
|
||||
enc->out_capacity = need * 2;
|
||||
enc->out_buf = (uint8_t *) realloc(enc->out_buf, enc->out_capacity);
|
||||
}
|
||||
|
||||
// Output the pending frame (now complete with overflow data)
|
||||
memcpy(enc->out_buf + enc->out_written, enc->pending_frame, enc->pending_bytes);
|
||||
enc->out_written += enc->pending_bytes;
|
||||
output_bytes = enc->pending_bytes;
|
||||
}
|
||||
|
||||
// Build current frame: header+sideinfo already in frame_buf, add main_data + padding
|
||||
int md_in_frame = md_bytes - resv_bytes;
|
||||
if (md_in_frame < 0) {
|
||||
md_in_frame = 0;
|
||||
}
|
||||
int md_area = frame_bytes - hdr_si_bytes;
|
||||
|
||||
// Copy the portion of main_data that goes in this frame
|
||||
if (md_in_frame > 0) {
|
||||
memcpy(enc->frame_buf + hdr_si_bytes, enc->md_scratch + resv_bytes, md_in_frame);
|
||||
}
|
||||
// Zero-pad the unused tail (this becomes reservoir for the next frame)
|
||||
if (md_in_frame < md_area) {
|
||||
memset(enc->frame_buf + hdr_si_bytes + md_in_frame, 0, md_area - md_in_frame);
|
||||
}
|
||||
|
||||
// Save current frame as pending (will be output when next frame is encoded)
|
||||
memcpy(enc->pending_frame, enc->frame_buf, frame_bytes);
|
||||
enc->pending_bytes = frame_bytes;
|
||||
enc->pending_md_end = hdr_si_bytes + md_in_frame;
|
||||
|
||||
return output_bytes;
|
||||
}
|
||||
|
||||
// Public API: encode PCM samples.
|
||||
// audio: planar float [ch0: n_samples][ch1: n_samples]
|
||||
// n_samples: number of samples per channel
|
||||
// out_size: receives the total MP3 bytes produced
|
||||
// Returns pointer to MP3 data (internal buffer, valid until next call).
|
||||
static const uint8_t * mp3enc_encode(mp3enc_t * enc, const float * audio, int n_samples, int * out_size) {
|
||||
*out_size = 0;
|
||||
int nch = enc->channels;
|
||||
int consumed = 0;
|
||||
|
||||
// Reset output write position
|
||||
enc->out_written = 0;
|
||||
|
||||
while (consumed < n_samples) {
|
||||
// Fill PCM buffer up to 1152 samples per channel
|
||||
int space = 1152 - enc->pcm_fill;
|
||||
int avail = n_samples - consumed;
|
||||
int copy = (avail < space) ? avail : space;
|
||||
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
memcpy(enc->pcm_buf + ch * 1152 + enc->pcm_fill, audio + ch * n_samples + consumed, copy * sizeof(float));
|
||||
}
|
||||
enc->pcm_fill += copy;
|
||||
consumed += copy;
|
||||
|
||||
// When we have 1152 samples, encode a frame.
|
||||
// encode_frame handles writing to out_buf (including pending frame output).
|
||||
if (enc->pcm_fill == 1152) {
|
||||
mp3enc_encode_frame(enc, enc->pcm_buf);
|
||||
enc->pcm_fill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*out_size = enc->out_written;
|
||||
return enc->out_buf;
|
||||
}
|
||||
|
||||
// Flush remaining samples (zero pad to 1152, encode last frame).
|
||||
// Also outputs the final pending frame from the bit reservoir delay.
|
||||
static const uint8_t * mp3enc_flush(mp3enc_t * enc, int * out_size) {
|
||||
*out_size = 0;
|
||||
enc->out_written = 0;
|
||||
|
||||
if (enc->pcm_fill > 0) {
|
||||
// Zero pad to 1152
|
||||
int nch = enc->channels;
|
||||
for (int ch = 0; ch < nch; ch++) {
|
||||
memset(enc->pcm_buf + ch * 1152 + enc->pcm_fill, 0, (1152 - enc->pcm_fill) * sizeof(float));
|
||||
}
|
||||
enc->pcm_fill = 1152;
|
||||
mp3enc_encode_frame(enc, enc->pcm_buf);
|
||||
enc->pcm_fill = 0;
|
||||
}
|
||||
|
||||
// Output the final pending frame (delayed by one frame for reservoir)
|
||||
if (enc->pending_bytes > 0) {
|
||||
int need = enc->out_written + enc->pending_bytes;
|
||||
if (need > enc->out_capacity) {
|
||||
enc->out_capacity = need * 2;
|
||||
enc->out_buf = (uint8_t *) realloc(enc->out_buf, enc->out_capacity);
|
||||
}
|
||||
memcpy(enc->out_buf + enc->out_written, enc->pending_frame, enc->pending_bytes);
|
||||
enc->out_written += enc->pending_bytes;
|
||||
enc->pending_bytes = 0;
|
||||
}
|
||||
|
||||
*out_size = enc->out_written;
|
||||
return enc->out_buf;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Extracted from minimp3.h (CC0, github.com/lieff/minimp3)
|
||||
// ISO 11172-3 Annex B, Table B.7 Huffman trees
|
||||
|
||||
static const int16_t tabs[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
785, 785, 785, 785, 784, 784, 784, 784, 513, 513, 513, 513, 513, 513, 513, 513,
|
||||
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
||||
-255, 1313, 1298, 1282, 785, 785, 785, 785, 784, 784, 784, 784, 769, 769, 769, 769,
|
||||
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
||||
290, 288, -255, 1313, 1298, 1282, 769, 769, 769, 769, 529, 529, 529, 529, 529, 529,
|
||||
529, 529, 528, 528, 528, 528, 528, 528, 528, 528, 512, 512, 512, 512, 512, 512,
|
||||
512, 512, 290, 288, -253, -318, -351, -367, 785, 785, 785, 785, 784, 784, 784, 784,
|
||||
769, 769, 769, 769, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
||||
256, 256, 256, 256, 819, 818, 547, 547, 275, 275, 275, 275, 561, 560, 515, 546,
|
||||
289, 274, 288, 258, -254, -287, 1329, 1299, 1314, 1312, 1057, 1057, 1042, 1042, 1026, 1026,
|
||||
784, 784, 784, 784, 529, 529, 529, 529, 529, 529, 529, 529, 769, 769, 769, 769,
|
||||
768, 768, 768, 768, 563, 560, 306, 306, 291, 259, -252, -413, -477, -542, 1298, -575,
|
||||
1041, 1041, 784, 784, 784, 784, 769, 769, 769, 769, 256, 256, 256, 256, 256, 256,
|
||||
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, -383, -399, 1107, 1092, 1106, 1061,
|
||||
849, 849, 789, 789, 1104, 1091, 773, 773, 1076, 1075, 341, 340, 325, 309, 834, 804,
|
||||
577, 577, 532, 532, 516, 516, 832, 818, 803, 816, 561, 561, 531, 531, 515, 546,
|
||||
289, 289, 288, 258, -252, -429, -493, -559, 1057, 1057, 1042, 1042, 529, 529, 529, 529,
|
||||
529, 529, 529, 529, 784, 784, 784, 784, 769, 769, 769, 769, 512, 512, 512, 512,
|
||||
512, 512, 512, 512, -382, 1077, -415, 1106, 1061, 1104, 849, 849, 789, 789, 1091, 1076,
|
||||
1029, 1075, 834, 834, 597, 581, 340, 340, 339, 324, 804, 833, 532, 532, 832, 772,
|
||||
818, 803, 817, 787, 816, 771, 290, 290, 290, 290, 288, 258, -253, -349, -414, -447,
|
||||
-463, 1329, 1299, -479, 1314, 1312, 1057, 1057, 1042, 1042, 1026, 1026, 785, 785, 785, 785,
|
||||
784, 784, 784, 784, 769, 769, 769, 769, 768, 768, 768, 768, -319, 851, 821, -335,
|
||||
836, 850, 805, 849, 341, 340, 325, 336, 533, 533, 579, 579, 564, 564, 773, 832,
|
||||
578, 548, 563, 516, 321, 276, 306, 291, 304, 259, -251, -572, -733, -830, -863, -879,
|
||||
1041, 1041, 784, 784, 784, 784, 769, 769, 769, 769, 256, 256, 256, 256, 256, 256,
|
||||
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, -511, -527, -543, 1396, 1351, 1381,
|
||||
1366, 1395, 1335, 1380, -559, 1334, 1138, 1138, 1063, 1063, 1350, 1392, 1031, 1031, 1062, 1062,
|
||||
1364, 1363, 1120, 1120, 1333, 1348, 881, 881, 881, 881, 375, 374, 359, 373, 343, 358,
|
||||
341, 325, 791, 791, 1123, 1122, -703, 1105, 1045, -719, 865, 865, 790, 790, 774, 774,
|
||||
1104, 1029, 338, 293, 323, 308, -799, -815, 833, 788, 772, 818, 803, 816, 322, 292,
|
||||
307, 320, 561, 531, 515, 546, 289, 274, 288, 258, -251, -525, -605, -685, -765, -831,
|
||||
-846, 1298, 1057, 1057, 1312, 1282, 785, 785, 785, 785, 784, 784, 784, 784, 769, 769,
|
||||
769, 769, 512, 512, 512, 512, 512, 512, 512, 512, 1399, 1398, 1383, 1367, 1382, 1396,
|
||||
1351, -511, 1381, 1366, 1139, 1139, 1079, 1079, 1124, 1124, 1364, 1349, 1363, 1333, 882, 882,
|
||||
882, 882, 807, 807, 807, 807, 1094, 1094, 1136, 1136, 373, 341, 535, 535, 881, 775,
|
||||
867, 822, 774, -591, 324, 338, -671, 849, 550, 550, 866, 864, 609, 609, 293, 336,
|
||||
534, 534, 789, 835, 773, -751, 834, 804, 308, 307, 833, 788, 832, 772, 562, 562,
|
||||
547, 547, 305, 275, 560, 515, 290, 290, -252, -397, -477, -557, -622, -653, -719, -735,
|
||||
-750, 1329, 1299, 1314, 1057, 1057, 1042, 1042, 1312, 1282, 1024, 1024, 785, 785, 785, 785,
|
||||
784, 784, 784, 784, 769, 769, 769, 769, -383, 1127, 1141, 1111, 1126, 1140, 1095, 1110,
|
||||
869, 869, 883, 883, 1079, 1109, 882, 882, 375, 374, 807, 868, 838, 881, 791, -463,
|
||||
867, 822, 368, 263, 852, 837, 836, -543, 610, 610, 550, 550, 352, 336, 534, 534,
|
||||
865, 774, 851, 821, 850, 805, 593, 533, 579, 564, 773, 832, 578, 578, 548, 548,
|
||||
577, 577, 307, 276, 306, 291, 516, 560, 259, 259, -250, -2107, -2507, -2764, -2909, -2974,
|
||||
-3007, -3023, 1041, 1041, 1040, 1040, 769, 769, 769, 769, 256, 256, 256, 256, 256, 256,
|
||||
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, -767, -1052, -1213, -1277, -1358, -1405,
|
||||
-1469, -1535, -1550, -1582, -1614, -1647, -1662, -1694, -1726, -1759, -1774, -1807, -1822, -1854, -1886, 1565,
|
||||
-1919, -1935, -1951, -1967, 1731, 1730, 1580, 1717, -1983, 1729, 1564, -1999, 1548, -2015, -2031, 1715,
|
||||
1595, -2047, 1714, -2063, 1610, -2079, 1609, -2095, 1323, 1323, 1457, 1457, 1307, 1307, 1712, 1547,
|
||||
1641, 1700, 1699, 1594, 1685, 1625, 1442, 1442, 1322, 1322, -780, -973, -910, 1279, 1278, 1277,
|
||||
1262, 1276, 1261, 1275, 1215, 1260, 1229, -959, 974, 974, 989, 989, -943, 735, 478, 478,
|
||||
495, 463, 506, 414, -1039, 1003, 958, 1017, 927, 942, 987, 957, 431, 476, 1272, 1167,
|
||||
1228, -1183, 1256, -1199, 895, 895, 941, 941, 1242, 1227, 1212, 1135, 1014, 1014, 490, 489,
|
||||
503, 487, 910, 1013, 985, 925, 863, 894, 970, 955, 1012, 847, -1343, 831, 755, 755,
|
||||
984, 909, 428, 366, 754, 559, -1391, 752, 486, 457, 924, 997, 698, 698, 983, 893,
|
||||
740, 740, 908, 877, 739, 739, 667, 667, 953, 938, 497, 287, 271, 271, 683, 606,
|
||||
590, 712, 726, 574, 302, 302, 738, 736, 481, 286, 526, 725, 605, 711, 636, 724,
|
||||
696, 651, 589, 681, 666, 710, 364, 467, 573, 695, 466, 466, 301, 465, 379, 379,
|
||||
709, 604, 665, 679, 316, 316, 634, 633, 436, 436, 464, 269, 424, 394, 452, 332,
|
||||
438, 363, 347, 408, 393, 448, 331, 422, 362, 407, 392, 421, 346, 406, 391, 376,
|
||||
375, 359, 1441, 1306, -2367, 1290, -2383, 1337, -2399, -2415, 1426, 1321, -2431, 1411, 1336, -2447,
|
||||
-2463, -2479, 1169, 1169, 1049, 1049, 1424, 1289, 1412, 1352, 1319, -2495, 1154, 1154, 1064, 1064,
|
||||
1153, 1153, 416, 390, 360, 404, 403, 389, 344, 374, 373, 343, 358, 372, 327, 357,
|
||||
342, 311, 356, 326, 1395, 1394, 1137, 1137, 1047, 1047, 1365, 1392, 1287, 1379, 1334, 1364,
|
||||
1349, 1378, 1318, 1363, 792, 792, 792, 792, 1152, 1152, 1032, 1032, 1121, 1121, 1046, 1046,
|
||||
1120, 1120, 1030, 1030, -2895, 1106, 1061, 1104, 849, 849, 789, 789, 1091, 1076, 1029, 1090,
|
||||
1060, 1075, 833, 833, 309, 324, 532, 532, 832, 772, 818, 803, 561, 561, 531, 560,
|
||||
515, 546, 289, 274, 288, 258, -250, -1179, -1579, -1836, -1996, -2124, -2253, -2333, -2413, -2477,
|
||||
-2542, -2574, -2607, -2622, -2655, 1314, 1313, 1298, 1312, 1282, 785, 785, 785, 785, 1040, 1040,
|
||||
1025, 1025, 768, 768, 768, 768, -766, -798, -830, -862, -895, -911, -927, -943, -959, -975,
|
||||
-991, -1007, -1023, -1039, -1055, -1070, 1724, 1647, -1103, -1119, 1631, 1767, 1662, 1738, 1708, 1723,
|
||||
-1135, 1780, 1615, 1779, 1599, 1677, 1646, 1778, 1583, -1151, 1777, 1567, 1737, 1692, 1765, 1722,
|
||||
1707, 1630, 1751, 1661, 1764, 1614, 1736, 1676, 1763, 1750, 1645, 1598, 1721, 1691, 1762, 1706,
|
||||
1582, 1761, 1566, -1167, 1749, 1629, 767, 766, 751, 765, 494, 494, 735, 764, 719, 749,
|
||||
734, 763, 447, 447, 748, 718, 477, 506, 431, 491, 446, 476, 461, 505, 415, 430,
|
||||
475, 445, 504, 399, 460, 489, 414, 503, 383, 474, 429, 459, 502, 502, 746, 752,
|
||||
488, 398, 501, 473, 413, 472, 486, 271, 480, 270, -1439, -1455, 1357, -1471, -1487, -1503,
|
||||
1341, 1325, -1519, 1489, 1463, 1403, 1309, -1535, 1372, 1448, 1418, 1476, 1356, 1462, 1387, -1551,
|
||||
1475, 1340, 1447, 1402, 1386, -1567, 1068, 1068, 1474, 1461, 455, 380, 468, 440, 395, 425,
|
||||
410, 454, 364, 467, 466, 464, 453, 269, 409, 448, 268, 432, 1371, 1473, 1432, 1417,
|
||||
1308, 1460, 1355, 1446, 1459, 1431, 1083, 1083, 1401, 1416, 1458, 1445, 1067, 1067, 1370, 1457,
|
||||
1051, 1051, 1291, 1430, 1385, 1444, 1354, 1415, 1400, 1443, 1082, 1082, 1173, 1113, 1186, 1066,
|
||||
1185, 1050, -1967, 1158, 1128, 1172, 1097, 1171, 1081, -1983, 1157, 1112, 416, 266, 375, 400,
|
||||
1170, 1142, 1127, 1065, 793, 793, 1169, 1033, 1156, 1096, 1141, 1111, 1155, 1080, 1126, 1140,
|
||||
898, 898, 808, 808, 897, 897, 792, 792, 1095, 1152, 1032, 1125, 1110, 1139, 1079, 1124,
|
||||
882, 807, 838, 881, 853, 791, -2319, 867, 368, 263, 822, 852, 837, 866, 806, 865,
|
||||
-2399, 851, 352, 262, 534, 534, 821, 836, 594, 594, 549, 549, 593, 593, 533, 533,
|
||||
848, 773, 579, 579, 564, 578, 548, 563, 276, 276, 577, 576, 306, 291, 516, 560,
|
||||
305, 305, 275, 259, -251, -892, -2058, -2620, -2828, -2957, -3023, -3039, 1041, 1041, 1040, 1040,
|
||||
769, 769, 769, 769, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
|
||||
256, 256, 256, 256, -511, -527, -543, -559, 1530, -575, -591, 1528, 1527, 1407, 1526, 1391,
|
||||
1023, 1023, 1023, 1023, 1525, 1375, 1268, 1268, 1103, 1103, 1087, 1087, 1039, 1039, 1523, -604,
|
||||
815, 815, 815, 815, 510, 495, 509, 479, 508, 463, 507, 447, 431, 505, 415, 399,
|
||||
-734, -782, 1262, -815, 1259, 1244, -831, 1258, 1228, -847, -863, 1196, -879, 1253, 987, 987,
|
||||
748, -767, 493, 493, 462, 477, 414, 414, 686, 669, 478, 446, 461, 445, 474, 429,
|
||||
487, 458, 412, 471, 1266, 1264, 1009, 1009, 799, 799, -1019, -1276, -1452, -1581, -1677, -1757,
|
||||
-1821, -1886, -1933, -1997, 1257, 1257, 1483, 1468, 1512, 1422, 1497, 1406, 1467, 1496, 1421, 1510,
|
||||
1134, 1134, 1225, 1225, 1466, 1451, 1374, 1405, 1252, 1252, 1358, 1480, 1164, 1164, 1251, 1251,
|
||||
1238, 1238, 1389, 1465, -1407, 1054, 1101, -1423, 1207, -1439, 830, 830, 1248, 1038, 1237, 1117,
|
||||
1223, 1148, 1236, 1208, 411, 426, 395, 410, 379, 269, 1193, 1222, 1132, 1235, 1221, 1116,
|
||||
976, 976, 1192, 1162, 1177, 1220, 1131, 1191, 963, 963, -1647, 961, 780, -1663, 558, 558,
|
||||
994, 993, 437, 408, 393, 407, 829, 978, 813, 797, 947, -1743, 721, 721, 377, 392,
|
||||
844, 950, 828, 890, 706, 706, 812, 859, 796, 960, 948, 843, 934, 874, 571, 571,
|
||||
-1919, 690, 555, 689, 421, 346, 539, 539, 944, 779, 918, 873, 932, 842, 903, 888,
|
||||
570, 570, 931, 917, 674, 674, -2575, 1562, -2591, 1609, -2607, 1654, 1322, 1322, 1441, 1441,
|
||||
1696, 1546, 1683, 1593, 1669, 1624, 1426, 1426, 1321, 1321, 1639, 1680, 1425, 1425, 1305, 1305,
|
||||
1545, 1668, 1608, 1623, 1667, 1592, 1638, 1666, 1320, 1320, 1652, 1607, 1409, 1409, 1304, 1304,
|
||||
1288, 1288, 1664, 1637, 1395, 1395, 1335, 1335, 1622, 1636, 1394, 1394, 1319, 1319, 1606, 1621,
|
||||
1392, 1392, 1137, 1137, 1137, 1137, 345, 390, 360, 375, 404, 373, 1047, -2751, -2767, -2783,
|
||||
1062, 1121, 1046, -2799, 1077, -2815, 1106, 1061, 789, 789, 1105, 1104, 263, 355, 310, 340,
|
||||
325, 354, 352, 262, 339, 324, 1091, 1076, 1029, 1090, 1060, 1075, 833, 833, 788, 788,
|
||||
1088, 1028, 818, 818, 803, 803, 561, 561, 531, 531, 816, 771, 546, 546, 289, 274,
|
||||
288, 258, -253, -317, -381, -446, -478, -509, 1279, 1279, -811, -1179, -1451, -1756, -1900, -2028,
|
||||
-2189, -2253, -2333, -2414, -2445, -2511, -2526, 1313, 1298, -2559, 1041, 1041, 1040, 1040, 1025, 1025,
|
||||
1024, 1024, 1022, 1007, 1021, 991, 1020, 975, 1019, 959, 687, 687, 1018, 1017, 671, 671,
|
||||
655, 655, 1016, 1015, 639, 639, 758, 758, 623, 623, 757, 607, 756, 591, 755, 575,
|
||||
754, 559, 543, 543, 1009, 783, -575, -621, -685, -749, 496, -590, 750, 749, 734, 748,
|
||||
974, 989, 1003, 958, 988, 973, 1002, 942, 987, 957, 972, 1001, 926, 986, 941, 971,
|
||||
956, 1000, 910, 985, 925, 999, 894, 970, -1071, -1087, -1102, 1390, -1135, 1436, 1509, 1451,
|
||||
1374, -1151, 1405, 1358, 1480, 1420, -1167, 1507, 1494, 1389, 1342, 1465, 1435, 1450, 1326, 1505,
|
||||
1310, 1493, 1373, 1479, 1404, 1492, 1464, 1419, 428, 443, 472, 397, 736, 526, 464, 464,
|
||||
486, 457, 442, 471, 484, 482, 1357, 1449, 1434, 1478, 1388, 1491, 1341, 1490, 1325, 1489,
|
||||
1463, 1403, 1309, 1477, 1372, 1448, 1418, 1433, 1476, 1356, 1462, 1387, -1439, 1475, 1340, 1447,
|
||||
1402, 1474, 1324, 1461, 1371, 1473, 269, 448, 1432, 1417, 1308, 1460, -1711, 1459, -1727, 1441,
|
||||
1099, 1099, 1446, 1386, 1431, 1401, -1743, 1289, 1083, 1083, 1160, 1160, 1458, 1445, 1067, 1067,
|
||||
1370, 1457, 1307, 1430, 1129, 1129, 1098, 1098, 268, 432, 267, 416, 266, 400, -1887, 1144,
|
||||
1187, 1082, 1173, 1113, 1186, 1066, 1050, 1158, 1128, 1143, 1172, 1097, 1171, 1081, 420, 391,
|
||||
1157, 1112, 1170, 1142, 1127, 1065, 1169, 1049, 1156, 1096, 1141, 1111, 1155, 1080, 1126, 1154,
|
||||
1064, 1153, 1140, 1095, 1048, -2159, 1125, 1110, 1137, -2175, 823, 823, 1139, 1138, 807, 807,
|
||||
384, 264, 368, 263, 868, 838, 853, 791, 867, 822, 852, 837, 866, 806, 865, 790,
|
||||
-2319, 851, 821, 836, 352, 262, 850, 805, 849, -2399, 533, 533, 835, 820, 336, 261,
|
||||
578, 548, 563, 577, 532, 532, 832, 772, 562, 562, 547, 547, 305, 275, 560, 515,
|
||||
290, 290, 288, 258
|
||||
};
|
||||
|
||||
static const uint8_t tab32[] = { 130, 162, 193, 209, 44, 28, 76, 140, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 190, 254, 222, 238, 126, 94, 157, 157, 109, 61, 173, 205 };
|
||||
static const uint8_t tab33[] = { 252, 236, 220, 204, 188, 172, 156, 140, 124, 108, 92, 76, 60, 44, 28, 12 };
|
||||
static const int16_t tabindex[2 * 16] = { 0, 32, 64, 98, 0, 132, 180, 218, 292, 364, 426,
|
||||
538, 648, 746, 0, 1126, 1460, 1460, 1460, 1460, 1460, 1460,
|
||||
1460, 1460, 1842, 1842, 1842, 1842, 1842, 1842, 1842, 1842 };
|
||||
static const uint8_t g_linbits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13 };
|
||||
Reference in New Issue
Block a user