欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MPEG音频编码实验

程序员文章站 2022-07-14 22:04:44
...

MPEG音频编码原理

感知音频编码的设计思想

MPEG音频编码实验
  • 两条线

    通过子带编码可以降低可以减小量化范围,降低比特率;通过心理声学模型可以利用人耳的掩蔽效应去除冗余的数据。

    子带分解模块需要向心理声学模型传输子带样值从而确定比例因子;心理声学模型通过对1024点的计算结合用于数据的码率从而确定每个子带的量化比特数。

    通过这两条线实现声音的压缩算法。

  • 时-频域分析的矛盾

    为了使编码的时间信号具有足够高的质量,需要具有足够高的时间分辨率,这就要求每次的采样样本尽可能少;但为了在频域上的心理声学模型模型计算有足够高的分辨率,需要一次的样本长度尽可能长。为了解决这个矛盾,最终采用每个样本12点采样提高时间分辨率,通过子带拼接来提高心理声学分析的频率分辨率。对于时域上的移位频率分析上很难区分,通过从高时间分辨率的子带块提取比例因子在一定程度上弥补了这个缺点。

心理声学模型

临界频带

  • 临界频带是指当某个纯音被以它为中心频率、且具有一定带 宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等 于这一频带内的噪声功率,这个带宽为临界频带宽度。 如下图所示:

    MPEG音频编码实验
    频域掩蔽域随声压级变化曲线
  • 人类听觉系统大致等效于一个信号通过一组并联的不同中 频率的带通滤波器,如下图所示:

    MPEG音频编码实验

掩蔽值和码率分配计算

信号掩蔽比:SMR = 信号能量 / 掩蔽阈值

算法:使整帧和每个子带的总噪声—掩蔽比最小;循环,直到没有比特可用:

噪声-掩蔽比:NMR = SMR– SNR (dB)

◼ 对最高NMR的子带分配比特,使获益最大的子带的量化级别增加一级

◼ 重新计算分配了更多比特子带的NMR

MPEG音频编码实验MPEG音频编码实验

MPEG音频编码的实现

程序设计的整体框架

结构体frame_infoframe_header定义了音频帧的结构,结构体bit_stream_struc定义了上一层次音频流的结构:从中可以得到声道数、子带数、比特分配和采样率等成员信息。根据这些可以迅速找到所需的信息:

/*****************************************m2aenc.c*************************************/
```
  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];// 3 组/帧 x 12个样本/子带 x 32个子带/帧 = 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;c
  unsigned long num_samples;
  int lg_frame;
  int i;
```
  //音频流逐帧处理
  while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
	```
    adb = available_bits (&header, &glopts);	// 计算比特预算
```

输出音频的采样率和目标码率

/*****************************************m2aenc.c*************************************/
```
#if TRACE
  printf( "---------------------------------------------------------------------\n");
  printf( "输入文件:%s\t", original_file_name);
  printf( "输出文件:%s\n\n", encoded_file_name);
  printf( "输出音频的采样率和目标码率:\n");
  printf( "采样率:%f kHz\n", s_freq[header.version][header.sampling_frequency]);
  printf( "目标码率:%d kbps\n", bitrate[header.version][header.bitrate_index]);
#endif

  //音频流逐帧处理
  while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
```

输出某个帧所分配的比特数 、比例因子 、比特分配结果

/*****************************************m2aenc.c*************************************/
```
  //音频流逐帧处理
  while (get_audio (musicin, buffer, num_samples, nch, &header) > 0) {
	```
#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

#if TRACE
	if (frameNum == 2) 
	{
		printf("\n选择的音频帧:%d\n", frameNum);
		printf("该帧所分配的比特数 :%d bits\n", adb);
		printf("\n该帧的比例因子:\n");
		for (ch = 0; ch < nch; ch++)
		{
			printf("\n%d声道:\n", ch+1);
			for (sb = 0; sb < frame.sblimit; sb++)
			{
				printf( "子带[%d]:\t", sb + 1);
				for (sbb = 0; sbb < 3; sbb++) 
					printf( "%d\t", scalar[ch][sbb][sb]);
				printf( "\n");
			}
		}
		printf( "\n该帧的比特分配结果:\n");  
		for (ch = 0; ch < nch; ch++) 
		{
			printf("\n%d声道:\n", ch+1);
			for (sb = 0; sb < frame.sblimit; sb++) 
				printf( "子带[%d]:\t%d\n", sb + 1, bit_alloc[ch][sb]);
		}
	}
#endif
    ```
  }
```

实验结果

均采用默认参数

---------------------------------------------------------------------
输入文件:.\my_test\music.wav   输出文件:.\my_test\music_2.wav

输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps

选择的音频帧:2
该帧所分配的比特数 :5016 bits

该帧的比例因子:

1声道:
子带[1]:        9       11      10
子带[2]:        14      14      14
子带[3]:        19      17      19
子带[4]:        25      23      24
子带[5]:        29      28      28
子带[6]:        23      25      23
子带[7]:        22      22      24
子带[8]:        22      22      21
子带[9]:        29      27      27
子带[10]:       30      30      32
子带[11]:       30      29      28
子带[12]:       27      28      28
子带[13]:       25      24      28
子带[14]:       26      27      23
子带[15]:       23      23      21
子带[16]:       26      23      25
子带[17]:       28      31      30
子带[18]:       30      33      31
子带[19]:       30      30      29
子带[20]:       28      29      29
子带[21]:       29      31      28
子带[22]:       32      30      30
子带[23]:       40      39      41
子带[24]:       54      50      50
子带[25]:       53      52      55
子带[26]:       55      53      54
子带[27]:       51      53      55
子带[28]:       53      53      52
子带[29]:       53      53      54
子带[30]:       53      52      52

该帧的比特分配结果:

1声道:
子带[1]:        8
子带[2]:        8
子带[3]:        6
子带[4]:        8
子带[5]:        7
子带[6]:        8
子带[7]:        8
子带[8]:        6
子带[9]:        5
子带[10]:       6
子带[11]:       6
子带[12]:       7
子带[13]:       6
子带[14]:       6
子带[15]:       6
子带[16]:       5
子带[17]:       5
子带[18]:       5
子带[19]:       4
子带[20]:       6
子带[21]:       3
子带[22]:       3
子带[23]:       0
子带[24]:       0
子带[25]:       0
子带[26]:       0
子带[27]:       0
子带[28]:       0
子带[29]:       0
子带[30]:       0
---------------------------------------------------------------------
输入文件:.\my_test\noise.wav   输出文件:.\my_test\noise_2.wav

输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps

选择的音频帧:2
该帧所分配的比特数 :5016 bits

该帧的比例因子:

1声道:
子带[1]:        23      24      26
子带[2]:        23      24      23
子带[3]:        25      25      25
子带[4]:        24      26      24
子带[5]:        25      25      27
子带[6]:        23      25      23
子带[7]:        25      25      23
子带[8]:        25      24      25
子带[9]:        25      23      25
子带[10]:       22      24      23
子带[11]:       25      25      24
子带[12]:       23      24      24
子带[13]:       22      26      24
子带[14]:       23      24      25
子带[15]:       23      25      24
子带[16]:       23      22      23
子带[17]:       24      25      22
子带[18]:       24      23      24
子带[19]:       25      24      23
子带[20]:       23      24      24
子带[21]:       25      25      24
子带[22]:       25      24      24
子带[23]:       24      25      26
子带[24]:       24      25      24
子带[25]:       23      23      23
子带[26]:       24      24      22
子带[27]:       25      25      24
子带[28]:       25      24      24
子带[29]:       24      25      25
子带[30]:       22      24      25

该帧的比特分配结果:

1声道:
子带[1]:        6
子带[2]:        7
子带[3]:        6
子带[4]:        7
子带[5]:        7
子带[6]:        6
子带[7]:        6
子带[8]:        7
子带[9]:        6
子带[10]:       6
子带[11]:       6
子带[12]:       6
子带[13]:       6
子带[14]:       6
子带[15]:       6
子带[16]:       5
子带[17]:       6
子带[18]:       6
子带[19]:       5
子带[20]:       4
子带[21]:       4
子带[22]:       4
子带[23]:       4
子带[24]:       2
子带[25]:       1
子带[26]:       1
子带[27]:       1
子带[28]:       1
子带[29]:       1
子带[30]:       0
---------------------------------------------------------------------
输入文件:.\my_test\music+noise.wav     输出文件:.\my_test\music+noise_2.wav

输出音频的采样率和目标码率:
采样率:44.100000 kHz
目标码率:192 kbps

选择的音频帧:2
该帧所分配的比特数 :5016 bits

该帧的比例因子:

1声道:
子带[1]:        9       11      10
子带[2]:        14      14      14
子带[3]:        18      17      19
子带[4]:        21      22      22
子带[5]:        24      24      24
子带[6]:        22      22      22
子带[7]:        20      22      26
子带[8]:        20      21      19
子带[9]:        23      22      24
子带[10]:       24      24      25
子带[11]:       24      22      22
子带[12]:       23      25      23
子带[13]:       22      23      23
子带[14]:       22      22      23
子带[15]:       23      23      20
子带[16]:       22      22      25
子带[17]:       22      26      24
子带[18]:       25      27      24
子带[19]:       24      23      23
子带[20]:       23      26      23
子带[21]:       23      23      23
子带[22]:       26      25      25
子带[23]:       23      24      25
子带[24]:       25      26      24
子带[25]:       24      25      24
子带[26]:       25      25      25
子带[27]:       23      25      22
子带[28]:       23      24      23
子带[29]:       25      24      26
子带[30]:       26      25      24

该帧的比特分配结果:

1声道:
子带[1]:        8
子带[2]:        7
子带[3]:        6
子带[4]:        7
子带[5]:        7
子带[6]:        7
子带[7]:        7
子带[8]:        6
子带[9]:        6
子带[10]:       6
子带[11]:       6
子带[12]:       6
子带[13]:       6
子带[14]:       6
子带[15]:       6
子带[16]:       5
子带[17]:       6
子带[18]:       5
子带[19]:       5
子带[20]:       4
子带[21]:       4
子带[22]:       5
子带[23]:       4
子带[24]:       1
子带[25]:       1
子带[26]:       1
子带[27]:       1
子带[28]:       1
子带[29]:       0
子带[30]:       0

可以看到对于噪声来说尽管各个子带的缩放因子几乎相同,但根据心理声学模型,在不失真的条件下仍能够压缩到不错的程度。

相关标签: 数据压缩原理