【数据压缩11】Lab6 MPEG音频编码实验

【数据压缩11】Lab6 MPEG音频编码实验

一、实验目的

  1. 理解程序设计的整体框架
  2. 理解感知音频编码的设计思想
    • 两条线
    • 时-频分析的矛盾!
  3. 理解心理声学模型的实现过程
    • 临界频带的概念
    • 掩蔽值计算的思路
  4. 理解码率分配的实现思路

二、实验原理

1. 感知音频编码设计思想

MPEG-1 Audio LayerII编码器原理如下

  • 输入PCM码流,采样率为32,44.1或48kHz;
  • 输出为32kbps到384kbps。
    在这里插入图片描述
(1)基本思想

基于人的生理和心理感知特性(心理声学模型),分析信号,对不被感知的部分不编码。声音压缩算法可以确立这种特性的模型来取消更多的冗余数据。

(2)上下两条线

在这里插入图片描述

  • 上支线:子带分解考虑时域。子带分析滤波器组使信号具有高的时间分辨率,确保在短暂冲击信号情况下,编码的声音信号具有足够高的质量。
  • 下支线:FFT和心理声学模型考虑频域。信号通过FFT运算具有高的频率分辨率,因为掩蔽阈值是从功率谱密度推出来的。
  • 上支线为下支线的心理声学模型提供比例因子;下支线为上支线的量化器提供比特分配
(3)时频矛盾

由于傅里叶变换的缺陷,变换结果只表示了信号中存在哪些频率,并不能表示某个频率出现的时间,如果时域上不同时刻出现尖峰,在频域上看两者是一样的。

(4)模块组成
- 多相滤波器组(Polyphase Filter Bank)

将 PCM样本变换到32个子带的频域信号。

如果输入的采样频率为48kHz,那么子带的频率宽度为48/(2*32)=0.75Hz

  • 等带宽的滤波器组与人类听觉系统的临界频带不对应 ;
  • 滤波器组与其逆过程不是无失真的;
  • 子带间频率有混叠 ,混叠:一个单频正弦信号输入可能在两个子带中产生非零信号
- 心理声学模型(Psychoacoustic Model)

计算信号中不可听觉感知的部分 (计算噪声遮蔽效应)

- 比特分配器(Bit Allocator)

根据心理声学模型的计算结果,为每个子带信号分配比特数。

- 装帧(Frame Creation)

2. 心理声学模型实现过程

(1)将样本变换到频域

32个等分的子带信号并不能精确地反映人耳的听觉特性。 引入FFT补偿频率分辨率不足的问题。

(2)确定声压级别
(3)考虑安静时阈值

即绝对阈值。在标准中有根据输入PCM信号的采样率编制的“频率、临界频带率和绝对阈值”表。此表为多位科学家经多次心理声学实验所得。

(4)音频信号分解

将音频信号分解成“乐音(tones)” 和“非乐音/噪声”部分:因为两种信号的掩蔽能力不同。

临界频带(Critical Band):
  • 指当某个纯音被以它为中心频率、且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽为临界频带宽度。通常认为从20Hz到16kHz有25个临界频带,单位为bark

    1 Bark = 一个临界频带的宽度

  • 研究窄带噪声对纯音掩蔽量的规律时被发现的

    • 使噪声的中心频率等于信号频率,只改变噪声的带宽同时保持噪声的功率谱密度不变,测试纯音听阈随掩蔽噪声带宽变化的特性。
    • 纯音的听阈随掩蔽噪声带宽的增大而增大,在带宽增大到某一特定值之后听阈保持恒定不变。
      在这里插入图片描述
(5)音调和非音调掩蔽成分的消除

利用标准中给出的绝对阈值消除被掩蔽成分;考虑在每个临界频带内,小于0.5Bark的距离中只保留最高功率的成分。

(6)单个掩蔽阈值的计算

音调成分和非音调成分单个掩蔽阈值根据标准中给出的算法求得。

隐蔽值计算:

Lutfi 对多个掩蔽音同时存在时的综合掩蔽效果进行了研究:每个掩蔽音的掩蔽效果先独立变换然后再线性相加
在这里插入图片描述
在这里插入图片描述

(7)全局掩蔽阈值的计算
(8)每个子带的掩蔽阈值

选择出本子带中最小的阈值作为子带阈值

(9)计算每个子带信号掩蔽比(signal-to-mask ratio, SMR)

SMR = 信号能量 / 掩蔽阈值(SMR传递给编码单元)

3. 码率分配

算法:使整帧和每个子带的总噪声—掩蔽比MNR最小

(1)在调整到固定的码率之前

先确定可用于样值编码的有效比特数。这个数值取决于比例因子、比例因子选择信息、比特分配信息以及辅助数据所需比特数。

(2)比特分配的过程
  1. 对每个子带计算噪声-掩蔽比MNR,是信掩比SMR之差信噪比SNR,其中SNR 由MPEG-I标准给定 (为量化水平的函数) ,噪声掩蔽比NMR表示波形误差与感知测量之间的误差;

N M R = S M R – S N R ( d B ) NMR = SMR– SNR (dB) NMR=SMRSNR(dB)

  1. 对最高NMR的子带分配比特,使获益最大的子带的量化级别增加一级,每提升1比特,信噪比就可以提升6dB
  2. 重新计算分配了更多比特子带的NMR

三、实验内容

  1. 输出音频的采样率和目标码率
  2. 选择三个不同特性的音频文件
    • 噪声(持续噪声、突发噪声)
    • 音乐
    • 混合
  3. 某个数据帧,输出
    • 该帧所分配的比特数
    • 该帧的比例因子
    • 该帧的比特分配结果

四、实验结果

1. 输出某一数据帧的各种信息

采样率: 44.1 kHz

目标码率:bitrate = 192.000 kbps

在这里插入图片描述

(1)m2eanc.h头文件中打开FRAME_TRACE
# define FRAME_TRACE 1

m2eanc.c的print_config函数中加入FRAME_TRACE

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

#if FRAME_TRACE
  FILE* output;
  output = fopen("output.txt", "a");
  fprintf(output, "========== 基本信息 ==========\n");
  fprintf(output, "输入文件:%s\n", inPath);
  fprintf(output, "输出文件:%s\n", outPath);
  fprintf(output, "采样频率:%.1f kHz\n", s_freq[header->version][header->sampling_frequency]);
  fprintf(output, "目标码率:%d kbps\n", bitrate[header->version][header->bitrate_index]);//输出文件码率
  fclose(output);
#endif // FRAME_TRACE
(2)m2eanc.c的main函数中加入FRAME_TRACE

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

#if FRAME_TRACE
	FILE* output;
	output = fopen("output.txt", "a");
	if (frameNum == 2) {
		fprintf(output, "声道数:%d\n", nch);
		fprintf(output, "目前观测第 %d 帧\n", frameNum);
		fprintf(output, "本帧比特预算:%d bits\n", adb);
		fprintf(output, "\n");
        

		fprintf(output, "========== 比例因子 ==========\n");
		for (ch = 0; ch < nch; ch++)	// 每个声道单独输出
		{
			fprintf(output, "------ 声道%2d ------\n", ch + 1);
			for (sb = 0; sb < frame.sblimit; sb++)	// 每个子带
			{
				fprintf(output, "子带[%2d]:\t", sb + 1);
				for (int gr = 0; gr < 3; gr++) {
					fprintf(output, "%2d\t", scalar[ch][gr][sb]);
				}
				fprintf(output, "\n");
			}
		}
		fprintf(output, "\n");


		fprintf(output, "========== 比特分配表 ==========\n");  //输出比特分配结果
		for (ch = 0; ch < nch; ch++) {
			fprintf(output, "------ 声道%2d ------\n", ch + 1); //按声道分配
			for (sb = 0; sb < frame.sblimit; sb++) {
				fprintf(output, "子带[%2d]:\t%2d\n", sb + 1, bit_alloc[ch][sb]);
			}
			fprintf(output, "\n");
		}
	}

	fclose(output);
#endif // FRAME_TRACE

2. 三个不同特性的音频文件

(1)音乐

test.wav

在这里插入图片描述

========== 基本信息 ==========
输入文件:test.wav
输出文件:test.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:1
目前观测第 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
(2)噪声

生成高斯白噪声noise_yyx.wav

Number = 100000;
noise_guass= 1*randn(1,Number);
audiowrite('noise_yyx.wav',noise_guass,44100);

在这里插入图片描述

========== 基本信息 ==========
输入文件:noise_yyx.wav
输出文件:noise_yyx.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:1
目前观测第 2 帧
本帧比特预算:5016 bits

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

========== 比特分配表 ==========
------ 声道 1 ------
子带[ 1]:	 5
子带[ 2]:	 5
子带[ 3]:	 4
子带[ 4]:	 5
子带[ 5]:	 5
子带[ 6]:	 5
子带[ 7]:	 5
子带[ 8]:	 4
子带[ 9]:	 4
子带[10]:	 5
子带[11]:	 4
子带[12]:	 5
子带[13]:	 3
子带[14]:	 3
子带[15]:	 4
子带[16]:	 3
子带[17]:	 4
子带[18]:	 4
子带[19]:	 3
子带[20]:	 3
子带[21]:	 2
子带[22]:	 3
子带[23]:	 3
子带[24]:	 3
子带[25]:	 2
子带[26]:	 1
子带[27]:	 2
子带[28]:	 3
子带[29]:	 2
子带[30]:	 2
(3)音乐+噪声
[y,~]=audioread('test.wav');
[noise_guass,fs]=audioread('test.wav');
mix=y + noise_guass;
audiowrite('mix_yyx.wav',mix,fs);

在这里插入图片描述

========== 基本信息 ==========
输入文件:mix_yyx.wav
输出文件:mix_yyx.mp2
采样频率:44.1 kHz
目标码率:192 kbps
声道数:1
目前观测第 2 帧
本帧比特预算:5016 bits

========== 比例因子 ==========
------ 声道 1 ------
子带[ 1]:	 6	 8	 7	
子带[ 2]:	11	11	11	
子带[ 3]:	16	14	16	
子带[ 4]:	22	20	21	
子带[ 5]:	26	25	25	
子带[ 6]:	20	22	20	
子带[ 7]:	19	19	21	
子带[ 8]:	19	19	18	
子带[ 9]:	26	24	24	
子带[10]:	27	27	29	
子带[11]:	27	26	25	
子带[12]:	24	25	25	
子带[13]:	22	21	25	
子带[14]:	23	24	20	
子带[15]:	20	20	18	
子带[16]:	23	20	22	
子带[17]:	25	28	27	
子带[18]:	27	30	28	
子带[19]:	27	27	26	
子带[20]:	25	26	26	
子带[21]:	26	28	25	
子带[22]:	29	27	27	
子带[23]:	37	36	38	
子带[24]:	51	47	47	
子带[25]:	50	49	52	
子带[26]:	52	50	51	
子带[27]:	48	50	52	
子带[28]:	50	50	49	
子带[29]:	50	50	51	
子带[30]:	50	49	49	

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

4. 结论

  • 噪声:各子带都分配到的比特数相对比较均匀,这说明了这种信源分布比较均匀,对于每种频率上的音频都超过掩蔽曲线不少;
  • 音乐:比特数集中在前面几个子带,后面的子带分配到的比特数较少,这主要是因为人发声范围有限,高频分量较少。基于感知编码,声音信号在时域上非均匀分布,小幅度的样值比大幅度的样值出现的概率高;在频域上功率谱密度非均匀,低频能量高、高频能量低。

DEBUG

img
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值