⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac3_parser.cpp

📁 ac3的解码程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#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 + -