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

📄 mpa_parser.cpp

📁 ac3的解码程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <string.h>
#include "../../crc.h"
#include "mpa_parser.h"
#include "mpa_header.h"
#include "mpa_tables.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


MPAParser::MPAParser()
{
  samples.allocate(2, MPA_NSAMPLES);
  synth[0] = new SynthBufferFPU();
  synth[1] = new SynthBufferFPU();

  // always useful
  reset();
}


MPAParser::~MPAParser()
{
  safe_delete(synth[0]);
  safe_delete(synth[1]);
}

///////////////////////////////////////////////////////////////////////////////
// FrameParser overrides

const HeaderParser *
MPAParser::header_parser() const
{
  return &mpa_header;
}

void 
MPAParser::reset()
{
  spk = spk_unknown;
  samples.zero();
  if (synth[0]) synth[0]->reset();
  if (synth[1]) synth[1]->reset();
}

bool
MPAParser::parse_frame(uint8_t *frame, size_t size)
{
  if (!parse_header(frame, size))
    return false;

  bs.set_ptr(frame, bsi.bs_type);
  bs.get(32); // skip header
  if (hdr.error_protection)
    bs.get(16); // skip crc

  switch (bsi.layer)
  {
    case MPA_LAYER_I:
      I_decode_frame();
      break;

    case MPA_LAYER_II:
      II_decode_frame();
      break;
  }

  return true;
}

size_t
MPAParser::stream_info(char *buf, size_t size) const 
{
  char info[1024];

  size_t len = sprintf(info, 
    "MPEG Audio\n"
    "speakers: %s\n"
    "ver: %s\n"
    "frame size: %i bytes\n"
    "stream: %s\n"
    "bitrate: %ikbps\n"
    "sample rate: %iHz\n"
    "bandwidth: %ikHz/%ikHz\n\0",
    spk.mode_text(),
    bsi.ver? "MPEG2 LSF": "MPEG1", 
    bsi.frame_size,
    (bsi.bs_type == BITSTREAM_8? "8 bit": "16bit low endian"), 
    bsi.bitrate / 1000,
    bsi.freq,
    bsi.jsbound * bsi.freq / SBLIMIT / 1000 / 2,
    bsi.sblimit * bsi.freq / SBLIMIT / 1000 / 2);

  if (len + 1 > size) len = size - 1;
  memcpy(buf, info, len + 1);
  buf[len] = 0;
  return len;
}

size_t
MPAParser::frame_info(char *buf, size_t size) const 
{
  if (buf && size) buf[0] = 0;
  return 0;
}

///////////////////////////////////////////////////////////////////////////////
// BaseParser overrides
/*
bool
MPAParser::crc_check()
{
  // Note: MPA uses standard CRC16 polinomial and 0xffff start value
  // MPA LayerII has variable number of protected bits.
  // To calculate it we must parse much of bs.
  // So we will check CRC on frame decode.
  // Maybe later.........
  return true;
}
*/
//////////////////////////////////////////////////////////////////////
// MPA parsing
//////////////////////////////////////////////////////////////////////

bool 
MPAParser::parse_header(const uint8_t *frame, size_t size)
{
  // 8 bit or 16 bit big endian stream sync
  if ((frame[0] == 0xff)         && // sync
     ((frame[1] & 0xf0) == 0xf0) && // sync
     ((frame[1] & 0x06) != 0x00) && // layer
     ((frame[2] & 0xf0) != 0xf0) && // bitrate
     ((frame[2] & 0x0c) != 0x0c))   // sample rate
  {
    uint32_t h = *(uint32_t *)frame;
    hdr = swab_u32(h);
    bsi.bs_type = BITSTREAM_8;
  }
  else
  // 16 bit low endian stream sync
  if ((frame[1] == 0xff)         && // sync
     ((frame[0] & 0xf0) == 0xf0) && // sync
     ((frame[0] & 0x06) != 0x00) && // layer
     ((frame[3] & 0xf0) != 0xf0) && // bitrate
     ((frame[3] & 0x0c) != 0x0c))   // sample rate
  {
    uint32_t h = *(uint32_t *)frame;
    hdr = (h >> 16) | (h << 16);
    bsi.bs_type = BITSTREAM_16LE;
  }
  else
    return false;

  hdr.error_protection = ~hdr.error_protection;

  // common information
  bsi.ver       = 1 - hdr.version;
  bsi.mode      = hdr.mode;
  bsi.layer     = 3 - hdr.layer;
  bsi.bitrate   = bitrate_tbl[bsi.ver][bsi.layer][hdr.bitrate_index] * 1000;
  bsi.freq      = freq_tbl[bsi.ver][hdr.sampling_frequency];

  bsi.nch       = bsi.mode == MPA_MODE_SINGLE? 1: 2;
  bsi.nsamples  = bsi.layer == MPA_LAYER_I? SCALE_BLOCK * SBLIMIT: SCALE_BLOCK * SBLIMIT * 3;

  // frame size calculation
  if (bsi.bitrate)
  {
    bsi.frame_size = bsi.bitrate * slots_tbl[bsi.layer] / bsi.freq + hdr.padding;
    if (bsi.layer == MPA_LAYER_I) 
      bsi.frame_size *= 4;

    if (bsi.frame_size > size)
      return false;
  }
  else
    bsi.frame_size = 0;

  // layerII: table select
  II_table = 0;
  if (bsi.layer == MPA_LAYER_II)
  {
    // todo: check for allowed bitrate ??? (look at sec 2.4.2.3 of ISO 11172-3)
    if (bsi.ver)
      // MPEG2 LSF
      II_table = 4; 
    else
    {
      // MPEG1
      if (bsi.mode == MPA_MODE_SINGLE)
        II_table = II_table_tbl[hdr.sampling_frequency][hdr.bitrate_index];
      else
        II_table = II_table_tbl[hdr.sampling_frequency][II_half_bitrate_tbl[hdr.bitrate_index]];
    }
  }

  // subband information
  bsi.sblimit = bsi.layer == MPA_LAYER_II?
                  II_sblimit_tbl[II_table]:
                  SBLIMIT;

  bsi.jsbound = bsi.mode == MPA_MODE_JOINT? 
                  jsbound_tbl[bsi.layer][hdr.mode_ext]: 
                  bsi.sblimit;

  spk = Speakers(FORMAT_LINEAR, (bsi.mode == MPA_MODE_SINGLE)? MODE_MONO: MODE_STEREO, bsi.freq);
  return true; 
}


///////////////////////////////////////////////////////////////////////////////
//  Layer II
///////////////////////////////////////////////////////////////////////////////


bool 
MPAParser::II_decode_frame()
{
  int sb, ch;
  int nch     = bsi.nch;
  int sblimit = bsi.sblimit;
  int jsbound = bsi.jsbound;
  int table   = II_table;

  int16_t  bit_alloc[MPA_NCH][SBLIMIT]; 
  sample_t scale[MPA_NCH][3][SBLIMIT];
  
  /////////////////////////////////////////////////////////
  // Load bitalloc
 
  const int16_t *ba_bits = II_ba_bits_tbl[table];

  if (nch == 1)
  {
    for (sb = 0; sb < sblimit; sb++)
    {
      int bits = ba_bits[sb];
      bit_alloc[0][sb] = II_ba_tbl[table][sb][bs.get(bits)];
    }
    
    for (sb = sblimit; sb < SBLIMIT; sb++) 
      bit_alloc[0][sb] = 0;
  }
  else
  {
    for (sb = 0; sb < jsbound; sb++) 
    {
      int bits = ba_bits[sb];
      if (bits)
      {
        bit_alloc[0][sb] = II_ba_tbl[table][sb][bs.get(bits)];
        bit_alloc[1][sb] = II_ba_tbl[table][sb][bs.get(bits)];
      }
      else
      {
        bit_alloc[0][sb] = II_ba_tbl[table][sb][0];
        bit_alloc[1][sb] = II_ba_tbl[table][sb][0];
      }
    }

    for (sb = jsbound; sb < sblimit; sb++)
    {
      int bits = ba_bits[sb];
      if (bits)
        bit_alloc[0][sb] = bit_alloc[1][sb] = II_ba_tbl[table][sb][bs.get(bits)];
      else
        bit_alloc[0][sb] = bit_alloc[1][sb] = II_ba_tbl[table][sb][0];
    }
    
    for (sb = sblimit; sb < SBLIMIT; sb++) 
      bit_alloc[0][sb] = bit_alloc[1][sb] = 0;
  }

  /////////////////////////////////////////////////////////
  // Load scalefactors bitalloc
  
  uint16_t scfsi[2][SBLIMIT];
  for (sb = 0; sb < sblimit; sb++) 
    for (ch = 0; ch < nch; ch++)    // 2 bit scfsi 
      if (bit_alloc[ch][sb]) 
        scfsi[ch][sb] = (uint16_t) bs.get(2);

  // do we need this?
  for (sb = sblimit; sb < SBLIMIT; sb++) 
    for (ch = 0; ch < nch; ch++)   
      scfsi[ch][sb] = 0;

  /////////////////////////////////////////////////////////
  // CRC check
  // Do crc check up to current point. Note that we 
  // include CRC word into processing AFTER protected 
  // data. Due to CRC properties we must get zero result
  // in case of no errors.
/*
  if (hdr.error_protection && do_crc)
  {
    uint32_t crc_bits = bs.get_pos() - 32 - 16;
    uint32_t crc = crc16.crc_init(0xffff);
    crc = crc16.calc_bits(crc, frame + 2, 0, 16,       bs_type); // header
    crc = crc16.calc_bits(crc, frame + 6, 0, crc_bits, bs_type); // frame data
    crc = crc16.calc_bits(crc, frame + 4, 0, 16,       bs_type); // crc
    if (crc)
      return false;
  }
*/
  /////////////////////////////////////////////////////////
  // Load scalefactors

  sample_t c;
  for (sb = 0; sb < sblimit; sb++) 
    for (ch = 0; ch < nch; ch ++) 
    {
      int ba = bit_alloc[ch][sb];
      if (ba)
      {
        if (ba > 0)
          c = c_tbl[ba];
        else 
          switch (ba)
          {
          case -5:  c = c_tbl[0]; break;
          case -7:  c = c_tbl[1]; break;
          case -10: c = c_tbl[2]; break;
          }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -