📄 ac3_enc.cpp
字号:
#include <stdlib.h>
#include <string.h>
#include "../../crc.h"
#include "ac3_bitalloc.h"
#include "ac3_enc.h"
#define EXP_REUSE 0
#define EXP_D15 1
#define EXP_D25 2
#define EXP_D45 3
#define DELTA_BIT_REUSE 0
#define DELTA_BIT_NEW 1
#define DELTA_BIT_NONE 2
#define DELTA_BIT_RESERVED 3
// exponent variation threshold
// exponent set will be reused if variation between blocks is less
#define EXP_DIFF_THRESHOLD 5000
#define CRC16_POLY ((1 << 0) | (1 << 2) | (1 << 15) | (1 << 16))
#define min(a, b) ((a) < (b)? (a): (b))
#define max(a, b) ((a) > (b)? (a): (b))
inline int bits_left(int32_t v);
inline unsigned int mul_poly(unsigned int a, unsigned int b, unsigned int poly);
inline unsigned int pow_poly(unsigned int a, unsigned int n, unsigned int poly);
// freq_tbl[halfratecod][fscod]
// freq_tbl[halfratecod][fscod] = freq_tbl[0][fscod] >> halfratecod;
const int freq_tbl[9] =
{ 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
const int bitrate_tbl[19] =
{
32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000,
160000, 192000, 224000, 256000, 320000, 384000, 448000, 512000, 576000, 640000
};
const sample_t ac3_window[256] =
{
0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443,
0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061,
0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121,
0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770,
0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153,
0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389,
0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563,
0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699,
0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757,
0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626,
0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126,
0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019,
0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031,
0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873,
0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269,
0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981,
0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831,
0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716,
0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610,
0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560,
0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674,
0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099,
0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994,
0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513,
0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788,
0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919,
0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974,
0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993,
0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999,
0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000,
1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000
};
// bit allocation tables
const uint8_t sdecay_tbl[4] = { 0x0f, 0x11, 0x13, 0x15 };
const uint8_t fdecay_tbl[4] = { 0x3f, 0x53, 0x67, 0x7b };
const uint16_t sgain_tbl[4] = { 0x0540, 0x04d8, 0x0478, 0x0410 };
const uint16_t dbknee_tbl[4] = { 0x0000, 0x0700, 0x0900, 0x0b00 };
const uint16_t floor_tbl[8] = { 0x02f0, 0x02b0, 0x0270, 0x0230, 0x01f0, 0x0170, 0x00f0, 0xf800 };
const uint16_t fgain_tbl[8] = { 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, 0x0400 };
AC3Enc::AC3Enc()
:NullFilter(0), // use own query_input()
mdct(7)
{
frames = 0;
bitrate = 640000;
frame_samples.allocate(AC3_NCHANNELS, AC3_FRAME_SAMPLES);
frame_buf.allocate(AC3_MAX_FRAME_SIZE);
window.allocate(1, AC3_BLOCK_SAMPLES);
reset();
}
int
AC3Enc::get_bitrate() const
{
return bitrate;
}
bool
AC3Enc::set_bitrate(int _bitrate)
{
// check bitrate
int i;
for (i = 0; i < sizeof(bitrate_tbl) / sizeof(bitrate_tbl[0]); i++)
if (bitrate_tbl[i] == _bitrate)
{
bitrate = _bitrate;
reset();
return true;
}
return false;
}
bool
AC3Enc::fill_buffer()
{
size_t n = AC3_FRAME_SAMPLES - sample;
if (size < n)
{
for (int ch = 0; ch < spk.nch(); ch++)
memcpy(frame_samples[ch] + sample, samples[ch], size * sizeof(sample_t));
sample += size;
time += vtime_t(size) / spk.sample_rate;
drop_samples(size);
return false;
}
else
{
for (int ch = 0; ch < spk.nch(); ch++)
memcpy(frame_samples[ch] + sample, samples[ch], n * sizeof(sample_t));
sample = 0;
time += vtime_t(n) / spk.sample_rate;
drop_samples(n);
return true;
}
}
void
AC3Enc::reset()
{
sample = 0;
memset(delay, 0, sizeof(delay));
for (int ch = 0; ch < NCHANNELS; ch++)
delay_exp[ch] = 15; // indicate that we have 0 bits in delay array
// reset bit allocation
sdcycod = 2;
fdcycod = 1;
sgaincod = 1;
dbpbcod = 2;
floorcod = 4;
fgaincod = 4;
csnroffst = 0;
fsnroffst = 0;
}
bool
AC3Enc::query_input(Speakers _spk) const
{
if (_spk.format != FORMAT_LINEAR)
return false;
// check sample rate
int i;
for (i = 0; i < sizeof(freq_tbl) / sizeof(freq_tbl[0]); i++)
if (freq_tbl[i] == _spk.sample_rate)
break;
if (i == sizeof(freq_tbl) / sizeof(freq_tbl[0]))
return false;
// check mask
switch (_spk.mask)
{
case MODE_1_0: case MODE_1_0 | CH_MASK_LFE:
case MODE_2_0: case MODE_2_0 | CH_MASK_LFE:
case MODE_3_0: case MODE_3_0 | CH_MASK_LFE:
case MODE_2_1: case MODE_2_1 | CH_MASK_LFE:
case MODE_3_1: case MODE_3_1 | CH_MASK_LFE:
case MODE_2_2: case MODE_2_2 | CH_MASK_LFE:
case MODE_3_2: case MODE_3_2 | CH_MASK_LFE:
break;
default: return false;
}
// everything is ok
return true;
}
bool
AC3Enc::set_input(Speakers _spk)
{
if (!NullFilter::set_input(_spk))
return false;
// sample rate
fscod = 0;
for (fscod = 0; fscod < sizeof(freq_tbl) / sizeof(freq_tbl[0]); fscod++)
if (freq_tbl[fscod] == _spk.sample_rate)
break;
if (fscod == sizeof(freq_tbl) / sizeof(freq_tbl[0]))
return false;
// bitrate
for (frmsizecod = 0; frmsizecod < sizeof(bitrate_tbl) / sizeof(bitrate_tbl[0]); frmsizecod++)
if (bitrate_tbl[frmsizecod] == bitrate)
break;
if (frmsizecod == sizeof(bitrate_tbl) / sizeof(bitrate_tbl[0]))
return false;
frmsizecod <<= 1;
halfratecod = fscod / 3;
fscod %= 3;
bsid = 8 + halfratecod;
spk = _spk;
sample_rate = _spk.sample_rate;
frame_size = (bitrate * AC3_BLOCK_SAMPLES * AC3_NBLOCKS) / sample_rate / 8;
switch (spk.mask)
{
case MODE_1_0: case MODE_1_0 | CH_MASK_LFE: acmod = AC3_MODE_1_0; break;
case MODE_2_0: case MODE_2_0 | CH_MASK_LFE: acmod = AC3_MODE_2_0; break;
case MODE_3_0: case MODE_3_0 | CH_MASK_LFE: acmod = AC3_MODE_3_0; break;
case MODE_2_1: case MODE_2_1 | CH_MASK_LFE: acmod = AC3_MODE_2_1; break;
case MODE_3_1: case MODE_3_1 | CH_MASK_LFE: acmod = AC3_MODE_3_1; break;
case MODE_2_2: case MODE_2_2 | CH_MASK_LFE: acmod = AC3_MODE_2_2; break;
case MODE_3_2: case MODE_3_2 | CH_MASK_LFE: acmod = AC3_MODE_3_2; break;
default: return false;
}
lfe = spk.lfe();
dolby = (spk.mask == MODE_STEREO) && ((spk.relation == RELATION_DOLBY) || (spk.relation == RELATION_DOLBY2));
nfchans = spk.lfe()? spk.nch() - 1: spk.nch();
// scale window
sample_t factor = 32768.0 / spk.level;
for (int s = 0; s < AC3_BLOCK_SAMPLES; s++)
window[0][s] = ac3_window[s] * factor;
reset();
return true;
}
bool
AC3Enc::get_chunk(Chunk *_chunk)
{
// todo: output partially filled frame on flushing
if (fill_buffer())
{
// encode frame
if (!encode_frame())
return false;
// fill chunk
_chunk->set_rawdata
(
get_output(),
frame_buf, frame_size,
sync, time,
flushing && !size
);
}
else
{
// dummy chunk
_chunk->set_dummy();
}
// reset after flushing
if (flushing && !size)
{
flushing = false;
reset();
}
return true;
}
Speakers
AC3Enc::get_output() const
{
return Speakers(FORMAT_AC3, spk.mask, spk.sample_rate, 1.0, spk.relation);
}
int
AC3Enc::encode_frame()
{
// todo: support non-standart channel ordering given with spk
// todo: support for 24/32/float input sample formats
// todo: support coupling (basic encoder)
int ch, b, s; // channel, block, sample indexes
int endmant;
int nch = spk.nch();
// frame-wide data
// channel-wide data
int exp_norm[AC3_NBLOCKS]; // normalization
// block-wide data
int16_t mdct_buf[AC3_BLOCK_SAMPLES * 2];
for (ch = 0; ch < nch; ch++)
{
if (spk.lfe() && (ch == nfchans))
// lfe channel
endmant = 7;
else
{
// fbw channels
chbwcod[ch] = 50;
endmant = ((chbwcod[ch] + 12) * 3) + 37;
}
nmant[ch] = endmant;
/////////////////////////////////////////////////////////////////
// Compute exponents and mdct coeffitients
// for all blocks from input data
//
for (b = 0; b < AC3_NBLOCKS; b++)
{
// todo: silence threshold at absolute level of 128
int exp_norm1 = 0; // normalization for this block
int exp_norm2 = 0; // normalization for next block delay
memcpy(mdct_buf, delay[ch], sizeof(delay[ch]));
///////////////////////////////////////////////////////////////
// Form input for MDCT
//
sample_t v;
sample_t *sptr = frame_samples[ch];
sptr += b * AC3_BLOCK_SAMPLES;
// * copy samples from input buffer to mdct and delay
// * apply ac3 window to both mdct and delay halves
// * compute the normalization for mdct (using
// delay normalization computed at previous block)
// and delay
// optimize: unroll cycle
for (s = 0; s < AC3_BLOCK_SAMPLES; s++)
{
v = *sptr++;
mdct_buf[s + 256] = int32_t(v * window[0][AC3_BLOCK_SAMPLES - s - 1]);
delay[ch][s] = int32_t(v * window[0][s]);
exp_norm1 |= abs(mdct_buf[s + 256]);
exp_norm2 |= abs(delay[ch][s]);
}
// compute normalization
exp_norm1 = 15 - bits_left(exp_norm1);
exp_norm2 = 15 - bits_left(exp_norm2);
exp_norm1 = min(exp_norm1, delay_exp[ch]);
exp_norm[b] = exp_norm1;
delay_exp[ch] = exp_norm2;
// normalize
for (s = 0; s < AC3_BLOCK_SAMPLES * 2; s++)
mdct_buf[s] <<= exp_norm1;
// finished with input
// now we have normalized mdct_buf[] buffer
// and noramlization exponent 'exp'
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// MDCT and exponents computation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -