Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
+220
View File
@@ -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;
}