实验原理
MPEG-1 Audio LayerII编码器原理图
心理声学模型:
1.将样本变换到频域
32个等分的子带信号并不能精确地反映人耳的听觉特性,引入FFT补偿频率分辨率不足的问题。
2.确定声压级别
3.考虑安静时阈值
也即绝对阈值。在标准中有根据输入PCM信号的采样率编制的“频率、临街频带率和绝对阈值”表。
4.将音频信号分解成“乐音”和“非乐音/噪声”部分,因为两种信号的掩蔽能力不同。
5.音调和非音调掩蔽成分的消除
利用标准中给出的绝对阈值消除被掩蔽成分;考虑在每个临界频带内,小于0.5Bark的距离总只保留最高功率的成分
6.单个掩蔽阈值的计算
音调成分和非音调成分单个掩蔽阈值根据标准中给出的算法求得
7.全局掩蔽阈值的计算
8.每个子带的掩蔽阈值
选出本子带中最小的阈值作为子带阈值
9.计算每个子带信号掩蔽比
SMR=信号能量/掩蔽阈值
并将SMR传递给编码单元
实验要求
1.输出音频的采样率和目标码率
2.选择某个数据帧,输出该帧所分配的比特数、比例因子、比特分配结果
代码分析
记录该帧所分配的总比特数
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];//声道1
win_buf[1] = &buffer[1][0];//声道2
adb = available_bits (&header, &glopts);
选择第二帧输出
#else
////////////////////增加////////////////////
if(frameNum==2)
{
fprintf(outinfo,"采样率:%.1fkhz\n",s_freq[header.version][header.sampling_frequency]);
fprintf(outinfo,"目标码率:%dMbps\n",bitrate[header.version][header.bitrate_index]);
fprintf(outinfo,"第二帧比特数:%d\n",adb);
}
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);
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);
////////////////////增加////////////////////
if(frameNum==2)
{
fprintf(outinfo,"比例因子\n");
for ( cha = 0; cha < nch; cha++ )
{
fprintf(outinfo,"声道%d\n",cha);
fprintf(outinfo,"子带\tGroup1\tGroup2\tGroup3\t\n");
for ( sbd = 0; sbd < frame.sblimit; sbd++ )
{
fprintf(outinfo,"%4d\t",sbd);
for( gro = 0; gro < 3; gro++ )
{
fprintf(outinfo,"%3d\t",scalar[cha][gro][sbd]);
}
fprintf(outinfo,"\n");
}
}
fprintf(outinfo,"帧比特分配:\n");
for ( cha = 0; cha < nch; cha++ )
{
fprintf(outinfo,"声道%d\n",cha);
for ( sbd = 0; sbd < frame.sblimit; sbd++ )
{
fprintf(outinfo,"子带%2d:\t",sbd);
fprintf(outinfo,"%2d\n",bit_alloc[cha][sbd]);
}
}
if(outinfo)
fclose(outinfo);
}
#endif
实验结果