一、实验原理
1、感知音频编码的设计思想
- 基于人耳的听觉特性,去掉音频中人感知不到的部分,不进行量化、编码。
- 等响度曲线与频域掩蔽域随声压级变化曲线
(等响度曲线)
- 两个声音响度级相同,但强度不一定相同,声强还受到频率的影响
- 声压级越高,等响度曲线趋于平坦
- 人耳对3~4KHz的声音最敏感
(频域掩蔽域随声压级变化曲线)
- 频率低的音频容易对频率高的音频产生掩蔽
- 掩蔽声的强度越强、频率越高,其掩蔽的频率范围就越宽
2、时域与频域的矛盾
提高频率分辨率会使时间分辨率降低
3、心理声学模型的实现过程
(1)临界频带
- 定义:当某个纯音被以它为中心频率,且具有一定带宽的连续噪声所掩蔽时,如果该纯音刚好被听到时的功率等于这一频带内的噪声功率,这个带宽称为临界频带宽度。
- 通常认为从20Hz到16KHz有25个临界频带,单位为bark,1bark=一个临界频带宽度
(2)掩蔽值计算的思路
掩蔽效果加和:多个掩蔽音同时存在的综合效果等于每个掩蔽音的掩蔽效果先独立变换再线性相加。
4、码率分配
- 多相滤波器组用来分割子带
- 对各子带每12个样点进行一次比例因子计算,定出12个样点中绝对值的最大值。查比例因子表中比这个最大值大的最小值作为比例因子,用6bit表示。
- 确定可用于样值编码的有效比特数,对每个子带计算掩蔽-噪声比MNR。比特分配应使整个一帧和每个子带的总噪声-掩蔽比最小。
5、程序设计的整体框架
二、实验内容
1、选择三种不同特性的音频文件:噪声、音乐、混合,输出音频的采样率和目标码率
2、某个数据帧,输出
- 该帧所分配的比特数
- 该帧的比例因子
- 该帧比特分配的结果
三、实验过程
m2aenc.c
main函数
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;
//add sentence
FILE* outfile = NULL;
unsigned char* outtxt = NULL;
outfile = fopen("output2.txt", "w");
//add finish
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];
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