📄 ac3_parser.cpp
字号:
#include <stdio.h>
#include <string.h>
#include "../../crc.h"
#include "ac3_header.h"
#include "ac3_parser.h"
#include "ac3_bitalloc.h"
#include "ac3_dither.h"
#include "ac3_tables.h"
// todo:
// * crc check (start_decode)
// * verify bit allocation conditions:
// do we need to make _all_ bit allocation if deltbaie = 1?
// * grouped mantissas verification
#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
///////////////////////////////////////////////////////////////////////////////
// Quanitizier class
// Decode mantissas
///////////////////////////////////////////////////////////////////////////////
class Quantizer
{
protected:
int q3_cnt, q5_cnt, q11_cnt;
sample_t q3[2];
sample_t q5[2];
sample_t q11;
public:
Quantizer(): q3_cnt(0), q5_cnt(0), q11_cnt(0) {};
void get_coeff(ReadBS &bs, sample_t *s, int8_t *bap, int8_t *exp, int n, bool dither);
};
///////////////////////////////////////////////////////////////////////////////
// AC3Parser
///////////////////////////////////////////////////////////////////////////////
AC3Parser::AC3Parser()
{
frames = 0;
errors = 0;
do_crc = true;
do_dither = true;
do_imdct = true;
// allocate buffers
samples.allocate(AC3_NCHANNELS, AC3_FRAME_SAMPLES);
delay.allocate(AC3_NCHANNELS, AC3_BLOCK_SAMPLES);
reset();
}
AC3Parser::~AC3Parser()
{}
///////////////////////////////////////////////////////////////////////////////
// FrameParser overrides
const HeaderParser *
AC3Parser::header_parser() const
{
return &ac3_header;
}
void
AC3Parser::reset()
{
memset((AC3Info*)this, 0, sizeof(AC3Info));
memset((AC3FrameState*)this, 0, sizeof(AC3FrameState));
spk = spk_unknown;
frame = 0;
frame_size = 0;
bs_type = 0;
block = 0;
samples.zero();
delay.zero();
}
bool
AC3Parser::parse_frame(uint8_t *frame, size_t size)
{
if (!start_parse(frame, size))
{
errors++;
return false;
}
if (!parse_header())
{
errors++;
return false;
}
while (block < AC3_NBLOCKS)
if (!decode_block())
{
errors++;
return false;
}
frames++;
return true;
}
size_t
AC3Parser::stream_info(char *buf, size_t size) const
{
char info[1024];
int max_freq = (cplinu? MAX(endmant[0], cplendmant): endmant[0]) * spk.sample_rate / 512000;
int cpl_freq = cplinu? cplstrtmant * spk.sample_rate / 512000: max_freq;
size_t len = sprintf(info,
"AC3\n"
"speakers: %s\n"
"sample rate: %iHz\n"
"bitrate: %ikbps\n"
"stream: %s\n"
"frame size: %i bytes\n"
"nsamples: %i\n"
"bsid: %i\n"
"clev: %.1fdB (%.4f)\n"
"slev: %.1fdB (%.4f)\n"
"dialnorm: -%idB\n"
"bandwidth: %ikHz/%ikHz\n\0",
spk.mode_text(),
spk.sample_rate,
bitrate,
(bs_type == BITSTREAM_8? "8 bit": "16bit low endian"),
frame_size,
AC3_FRAME_SAMPLES,
bsid,
value2db(clev), clev,
value2db(slev), slev,
dialnorm,
cpl_freq, max_freq);
if (len + 1 > size) len = size - 1;
memcpy(buf, info, len + 1);
buf[len] = 0;
return len;
}
size_t
AC3Parser::frame_info(char *buf, size_t size) const
{
if (buf && size) buf[0] = 0;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// AC3 parse
bool
AC3Parser::start_parse(uint8_t *_frame, size_t _size)
{
HeaderInfo hinfo;
if (!ac3_header.parse_header(_frame, &hinfo))
return false;
if (hinfo.frame_size > _size)
return false;
spk = hinfo.spk;
spk.format = FORMAT_LINEAR;
frame = _frame;
frame_size = hinfo.frame_size;
bs_type = hinfo.bs_type;
if (do_crc)
if (!crc_check())
return false;
bs.set_ptr(frame, bs_type);
return true;
}
bool
AC3Parser::crc_check()
{
// Note: AC3 uses standard CRC16 polinomial
uint32_t crc;
/////////////////////////////////////////////////////////
// Check first 5/8 of frame
// CRC is initialized by 0 and test result must be also 0.
// Syncword (first 2 bytes) is not imcluded to crc calc
// but it is included to 5/8 of frame size. So we must
// check 5/8*frame_size - 2 bytes.
size_t frame_size1 = ((frame_size >> 2) + (frame_size >> 4)) << 1;
crc = crc16.calc(0, frame + 2, frame_size1 - 2, bs_type);
if (crc)
return false;
/////////////////////////////////////////////////////////
// Check the rest of frame
// CRC is initialized by 0 (from previous point) and test
// result must be also 0.
crc = crc16.calc(0, frame + frame_size1, frame_size - frame_size1, bs_type);
if (crc)
return false;
return true;
}
bool
AC3Parser::parse_header()
// Fill AC3Info structure
{
/////////////////////////////////////////////////////////////
// Skip syncword
bs.get(32);
/////////////////////////////////////////////////////////////
// Parse bit stream information (BSI)
fscod = bs.get(2); // 'fscod' - sample rate code
frmsizecod = bs.get(6); // 'frmsizecod' - frame size code
bsid = bs.get(5); // 'bsid' - bitstream identification
bsmod = bs.get(3); // 'bsmod' - bitstreeam mode
acmod = bs.get(3); // 'acmod' - audio coding mode
halfrate = halfrate_tbl[bsid];
bitrate = bitrate_tbl[frmsizecod >> 1];
if ((acmod & 1) && (acmod != 1))
clev = clev_tbl[bs.get(2)]; // 'clev' - center mix level
else
clev = 1.0;
if (acmod & 4)
slev = slev_tbl[bs.get(2)]; // 'slev' - surround mix level
else
slev = 1.0;
if (acmod == AC3_MODE_STEREO)
dsurmod = bs.get(2); // 'dsurmod' - Dolby Surround mode
else
dsurmod = 0;
lfeon = bs.get_bool(); // 'lfeon' - flag shows if it is LFE channel in stream
dialnorm = bs.get(5); // 'dialnorm' - dialog normalization
compre = bs.get_bool(); // 'compre' - compression gain word
if (compre)
compr = bs.get(8); // 'compr' - compression gain word
else
compr = 0;
langcode = bs.get_bool(); // 'langcode' - language code exists
if (langcode)
langcod = bs.get(8); // 'langcod' - language code
else
langcod = 0;
audprodie = bs.get_bool(); // 'audprodie' - audio production information exists
if (audprodie)
{
mixlevel = bs.get(5) + 80; // 'mixlevel' - mixing level in SPL
roomtyp = bs.get(2); // 'roomtyp' - room type
}
else
{
mixlevel = 0;
roomtyp = 0;
}
if (acmod == AC3_MODE_DUAL)
{
dialnorm2 = bs.get(5); // 'dialnorm2' - dialog normalization
compr2e = bs.get_bool(); // 'compr2e' - compression gain word
if (compr2e)
compr2 = bs.get(8); // 'compr2' - compression gain word
else
compr2 = 0;
langcod2e = bs.get_bool(); // 'langcod2e' - language code exists
if (langcod2e)
langcod = bs.get(8); // 'langcod2' - language code
else
langcod = 0;
audprodi2e = bs.get_bool(); // 'audprodi2e' - audio production information exists
if (audprodi2e)
{
mixlevel2 = bs.get(5) + 80; // 'mixlevel2' - mixing level in SPL
roomtyp2 = bs.get(2); // 'roomtyp2' - room type
}
else
{
mixlevel2 = 0;
roomtyp2 = 0;
}
}
else
{
dialnorm2 = 0;
compr2e = false;
compr2 = 0;
langcod2e = false;
langcod = 0;
audprodi2e = false;
mixlevel2 = 0;
roomtyp2 = 0;
}
copyrightb = bs.get_bool(); // 'copyrightb' - copyright bit
origbs = bs.get_bool(); // 'origbs' - original bitstream
if (bs.get_bool()) // 'timecod1e' - timecode first half exists
{
timecode.hours = bs.get(5);
timecode.mins = bs.get(6);
timecode.secs = bs.get(3) << 4;
}
if (bs.get_bool()) // 'timecod2e' - timecode second half exists
{
timecode.secs += bs.get(3);
timecode.frames = bs.get(5);
timecode.fracs = bs.get(6);
}
if (bs.get_bool()) // 'addbsie' - additional bitstream information exists
{
int addbsil = bs.get(6); // 'addbsil' - additioanl bitstream information length
while (addbsil--)
bs.get(8); // 'addbsi' - additional bitstream information
}
/////////////////////////////////////////////////////////////
// Init variables to for first block decoding
block = 0;
dynrng = 1.0;
dynrng2 = 1.0;
cpldeltbae = DELTA_BIT_NONE;
deltbae[0] = DELTA_BIT_NONE;
deltbae[1] = DELTA_BIT_NONE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -