MPEG音频编码实验

1、MPEG-1 Audio LayerII编码相关原理

编码器原理
MPEG音频编码实验_第1张图片
多相滤波器组
MPEG音频编码实验_第2张图片
将 PCM样本变换到32个子带的频域信号 如果输入的采样频率为48kHz,那么子带的频率 宽度为48/(2*32)=0.75Hz

PCM 脉冲编码调制,即Pulse Code Modulation。脉冲编码调制是数字通信的编码方式之一。将模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值量化,用一组二进制码来表示抽样脉冲的幅值
心理声学模型的应用,计算噪声遮蔽效应
人耳听觉特性灵敏度与频率有关,存在掩蔽效应

2、程序设计的整体框架:

1.对滑动窗口内的音频信号进行32子带的滤波
2.若为立体声模式,结合左右两声道
3.计算当前帧的比例因子,并计算当前帧的比例因子选择信息
4.使用相应的心理声学模型计算心理声学掩蔽电平
5.使用步骤4中的掩蔽电平计算掩噪比,迭代分配比特
6.如有需要添加CRC纠错
7.将比特分配,比例因子和比例因子信息打包并加入比特流
8.根据比特分配信息对子带量化打包加入比特流

代码实现:

int main(int argc, char** argv)
{
 typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT];
 SBS* sb_sample;
 typedef double JSBS[3][SCALE_BLOCK][SBLIMIT];
 JSBS* j_sample;
 typedef double IN[2][HAN_SIZE];
 IN* win_que;
 typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT];
 SUB* subband;
 frame_info frame;//包含头信息等内容
 frame_header header;//头信息具体内容
 char original_file_name[MAX_NAME_SIZE];//原始文件名
 char encoded_file_name[MAX_NAME_SIZE];//编码文件名
 short** win_buf;
 static short buffer[2][1152];
 static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT];
 static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT];
 static double smr[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT];
 // FLOAT snr32[32];
 short sam[2][1344];  /* was [1056]; */
 int model, nch, error_protection;
 static unsigned int crc;
 int sb, ch, adb;
 unsigned long frameBits, sentBits = 0;
 unsigned long num_samples;
 int lg_frame;
 int i;
 /* Used to keep the SNR values for the fast/quick psy models */
 static FLOAT smrdef[2][32];//共32个子带
 static int psycount = 0;
 extern int minimum;
 time_t start_time, end_time;
 int total_time;
 sb_sample = (SBS*)mem_alloc(sizeof(SBS), "sb_sample");
 j_sample = (JSBS*)mem_alloc(sizeof(JSBS), "j_sample");
 win_que = (IN*)mem_alloc(sizeof(IN), "Win_que");
 subband = (SUB*)mem_alloc(sizeof(SUB), "subband");
 win_buf = (short**)mem_alloc(sizeof(short*) * 2, "win_buf");
 /* clear buffers */
 memset((char*)buffer, 0, sizeof(buffer));
 memset((char*)bit_alloc, 0, sizeof(bit_alloc));
 memset((char*)scalar, 0, sizeof(scalar));
 memset((char*)j_scale, 0, sizeof(j_scale));
 memset((char*)scfsi, 0, sizeof(scfsi));
 memset((char*)smr, 0, sizeof(smr));
 memset((char*)lgmin, 0, sizeof(lgmin));
 memset((char*)max_sc, 0, sizeof(max_sc));
 //memset ((char *) snr32, 0, sizeof (snr32));
 memset((char*)sam, 0, sizeof(sam));
 //初始化相关buffer
 global_init();
 //运行一次初始化函数
 header.extension = 0;
 frame.header = &header;
 frame.tab_num = -1;  /* no table loaded */
 frame.alloc = NULL;
 header.version = MPEG_AUDIO_ID; /* Default: MPEG-1 */
 total_time = 0;
 time(&start_time);//记录编码开始时间     
 programName = argv[0];//读入命令行参数
 if (argc == 1)  /* no command-line args */
  short_usage();
 else
  parse_args(argc, argv, &frame, &model, &num_samples, original_file_name,
   encoded_file_name);
 print_config(&frame, &model, original_file_name, encoded_file_name);
 /* this will load the alloc tables and do some other stuff */
 hdr_to_frps(&frame);//读文件头内相关信息
 nch = frame.nch;
 error_protection = header.error_protection;
 //获取音频信息
 while (get_audio(musicin, buffer, num_samples, nch, &header) > 0) {
  if (glopts.verbosity > 1)
   if (++frameNum % 10 == 0)
    fprintf(stderr, "[%4u]\r", frameNum);
  fflush(stderr);
  win_buf[0] = &buffer[0][0];
  win_buf[1] = &buffer[1][0];
  //比特预算
  adb = available_bits(&header, &glopts);
  lg_frame = adb / 8;
  if (header.dab_extension) {
   /* in 24 kHz we always have 4 bytes */
   if (header.sampling_frequency == 1)
    header.dab_extension = 4;
   /* You must have one frame in memory if you are in DAB mode                 */
   /* in conformity of the norme ETS 300 401 http://www.etsi.org               */
      /* see bitstream.c            */
   if (frameNum == 1)
    minimum = lg_frame + MINIMUM;
   adb -= header.dab_extension * 8 + header.dab_length * 8 + 16;
  }
  {
   int gr, bl, ch;
   /* New polyphase filter
     Combines windowing and filtering. Ricardo Feb'03 */
   for (gr = 0; gr < 3; gr++)//layer2进行三次
    for (bl = 0; bl < 12; bl++)//每个子带12个样本
     for (ch = 0; ch < nch; ch++)//32个子带
      WindowFilterSubband(&buffer[ch][gr * 12 * 32 + 32 * bl], ch,
       &(*sb_sample)[ch][gr][bl][0]);
  }//多项滤波器组
#ifdef REFERENCECODE
  {
   /* Old code. left here for reference */
   int gr, bl, ch;
   for (gr = 0; gr < 3; gr++)
    for (bl = 0; bl < SCALE_BLOCK; bl++)
     for (ch = 0; ch < nch; ch++) {
      window_subband(&win_buf[ch], &(*win_que)[ch][0], ch);
      filter_subband(&(*win_que)[ch][0], &(*sb_sample)[ch][gr][bl][0]);
     }
  }
#endif
#ifdef NEWENCODE
  scalefactor_calc_new(*sb_sample, scalar, nch, frame.sblimit);
  find_sf_max(scalar, &frame, max_sc);
  if (frame.actual_mode == MPG_MD_JOINT_STEREO) {
   /* this way we calculate more mono than we need */
   /* but it is cheap */
   combine_LR_new(*sb_sample, *j_sample, frame.sblimit);
   scalefactor_calc_new(j_sample, &j_scale, 1, frame.sblimit);
  }
#else
  scale_factor_calc(*sb_sample, scalar, nch, frame.sblimit);
  pick_scale(scalar, &frame, max_sc);//找到最大的比例因子
  if (frame.actual_mode == MPG_MD_JOINT_STEREO) {
   /* this way we calculate more mono than we need */
   /* but it is cheap */
   combine_LR(*sb_sample, *j_sample, frame.sblimit);
   scale_factor_calc(j_sample, &j_scale, 1, frame.sblimit);
  }
#endif
  //选择合适的心理声学模型计算smr
  if ((glopts.quickmode == TRUE) && (++psycount % glopts.quickcount != 0)) {
   /* We're using quick mode, so we're only calculating the model every
      'quickcount' frames. Otherwise, just copy the old ones across */
   for (ch = 0; ch < nch; ch++) {
    for (sb = 0; sb < SBLIMIT; sb++)
     smr[ch][sb] = smrdef[ch][sb];
   }
  }
  else {
   /* calculate the psymodel */
   switch (model) {
   case -1:
    psycho_n1(smr, nch);
    break;
   case 0: /* Psy Model A */
    psycho_0(smr, nch, scalar, (FLOAT)s_freq[header.version][header.sampling_frequency] * 1000);
    break;
   case 1:
    psycho_1(buffer, max_sc, smr, &frame);
    break;
   case 2:
    for (ch = 0; ch < nch; ch++) {
     psycho_2(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32,
      (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    }
    break;
   case 3:
    /* Modified psy model 1 */
    psycho_3(buffer, max_sc, smr, &frame, &glopts);
    break;
   case 4:
    /* Modified Psycho Model 2 */
    for (ch = 0; ch < nch; ch++) {
     psycho_4(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32,
      (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    }
    break;
   case 5:
    /* Model 5 comparse model 1 and 3 */
    psycho_1(buffer, max_sc, smr, &frame);
    fprintf(stdout, "1 ");
    smr_dump(smr, nch);
    psycho_3(buffer, max_sc, smr, &frame, &glopts);
    fprintf(stdout, "3 ");
    smr_dump(smr, nch);
    break;
   case 6:
    /* Model 6 compares model 2 and 4 */
    for (ch = 0; ch < nch; ch++)
     psycho_2(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32,
     (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    fprintf(stdout, "2 ");
    smr_dump(smr, nch);
    for (ch = 0; ch < nch; ch++)
     psycho_4(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32,
     (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    fprintf(stdout, "4 ");
    smr_dump(smr, nch);
    break;
   case 7:
    fprintf(stdout, "Frame: %i\n", frameNum);
    /* Dump the SMRs for all models */
    psycho_1(buffer, max_sc, smr, &frame);
    fprintf(stdout, "1");
    smr_dump(smr, nch);
    psycho_3(buffer, max_sc, smr, &frame, &glopts);
    fprintf(stdout, "3");
    smr_dump(smr, nch);
    for (ch = 0; ch < nch; ch++)
     psycho_2(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], //snr32,
     (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    fprintf(stdout, "2");
    smr_dump(smr, nch);
    for (ch = 0; ch < nch; ch++)
     psycho_4(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32,
     (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    fprintf(stdout, "4");
    smr_dump(smr, nch);
    break;
   case 8:
    /* Compare 0 and 4 */
    psycho_n1(smr, nch);
    fprintf(stdout, "0");
    smr_dump(smr, nch);
    for (ch = 0; ch < nch; ch++)
     psycho_4(&buffer[ch][0], &sam[ch][0], ch, &smr[ch][0], // snr32,
     (FLOAT)s_freq[header.version][header.sampling_frequency] *
      1000, &glopts);
    fprintf(stdout, "4");
    smr_dump(smr, nch);
    break;
   default:
    fprintf(stderr, "Invalid psy model specification: %i\n", model);
    exit(0);
   }
   if (glopts.quickmode == TRUE)
    /* copy the smr values and reuse them later */
    for (ch = 0; ch < nch; ch++) {
     for (sb = 0; sb < SBLIMIT; sb++)
      smrdef[ch][sb] = smr[ch][sb];
    }
   if (glopts.verbosity > 4)
    smr_dump(smr, nch);
  }
#ifdef NEWENCODE
  sf_transmission_pattern(scalar, scfsi, &frame);
  main_bit_allocation_new(smr, scfsi, bit_alloc, &adb, &frame, &glopts);
  //main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
  if (error_protection)
   CRC_calc(&frame, bit_alloc, scfsi, &crc);
  write_header(&frame, &bs);
  //encode_info (&frame, &bs);
  if (error_protection)
   putbits(&bs, crc, 16);
  write_bit_alloc(bit_alloc, &frame, &bs);
  //encode_bit_alloc (bit_alloc, &frame, &bs);
  write_scalefactors(bit_alloc, scfsi, scalar, &frame, &bs);
  //encode_scale (bit_alloc, scfsi, scalar, &frame, &bs);
  subband_quantization_new(scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
   *subband, &frame);
  //subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
  //   *subband, &frame);
  write_samples_new(*subband, bit_alloc, &frame, &bs);
  //sample_encoding (*subband, bit_alloc, &frame, &bs);
#else
  transmission_pattern(scalar, scfsi, &frame);
  main_bit_allocation(smr, scfsi, bit_alloc, &adb, &frame, &glopts);//比特分配
  if (error_protection)
   CRC_calc(&frame, bit_alloc, scfsi, &crc);//crc纠错
  encode_info(&frame, &bs);
  if (error_protection)
   encode_CRC(crc, &bs);
  encode_bit_alloc(bit_alloc, &frame, &bs);
  encode_scale(bit_alloc, scfsi, scalar, &frame, &bs);//编码
  subband_quantization(scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
   *subband, &frame);//对子带进行量化
  sample_encoding(*subband, bit_alloc, &frame, &bs);
#endif
  /* If not all the bits were used, write out a stack of zeros */
  for (i = 0; i < adb; i++)
   put1bit(&bs, 0);
  if (header.dab_extension) {
   /* Reserve some bytes for X-PAD in DAB mode */
   putbits(&bs, 0, header.dab_length * 8);//码流输出
   for (i = header.dab_extension - 1; i >= 0; i--) {
    CRC_calcDAB(&frame, bit_alloc, scfsi, scalar, &crc, i);
    /* this crc is for the previous frame in DAB mode  */
    if (bs.buf_byte_idx + lg_frame < bs.buf_size)
     bs.buf[bs.buf_byte_idx + lg_frame] = crc;
    /* reserved 2 bytes for F-PAD in DAB mode  */
    putbits(&bs, crc, 8);
   }
   putbits(&bs, 0, 16);
  }
  frameBits = sstell(&bs) - sentBits;
  if (frameBits % 8) { /* a program failure */
   fprintf(stderr, "Sent %ld bits = %ld slots plus %ld\n", frameBits,
    frameBits / 8, frameBits % 8);
   fprintf(stderr, "If you are reading this, the program is broken\n");
   fprintf(stderr, "email [mfc at NOTplanckenerg.com] without the NOT\n");
   fprintf(stderr, "with the command line arguments and other info\n");
   exit(0);
  }

你可能感兴趣的:(MPEG音频编码实验)