📄 encode.c
字号:
/*/************************************************************************/ void filter_subband(z,s)double z[HAN_SIZE], s[SBLIMIT];{ double y[64]; int i,j; static char init = 0; typedef double MM[SBLIMIT][64]; static MM *m; long SIZE_OF_MM; SIZE_OF_MM = SBLIMIT*64; SIZE_OF_MM *= 8; if (!init) { m = (MM *) mem_alloc(SIZE_OF_MM, "filter"); create_ana_filter(*m); init = 1; } for (i=0;i<64;i++) for (j=0, y[i] = 0;j<8;j++) y[i] += z[i+64*j]; for (i=0;i<SBLIMIT;i++) for (j=0, s[i]= 0;j<64;j++) s[i] += (*m)[i][j] * y[j];}/************************************************************************//*/* encode_info()/*/* 功能: 将同步字节和头信息放入输出比特流/*/************************************************************************/ void encode_info(fr_ps,bs)frame_params *fr_ps;Bit_stream_struc *bs;{ layer *info = fr_ps->header; putabits(bs,0xfff,12); /* syncword 12 bits */ put1bit(bs,info->version); /* ID 1 bit */ putabits(bs,4-info->lay,2); /* layer 2 bits */ put1bit(bs,!info->error_protection); /* bit set => no err prot */ putabits(bs,info->bitrate_index,4); putabits(bs,info->sampling_frequency,2); put1bit(bs,info->padding); put1bit(bs,info->extension); /* private_bit */ putabits(bs,info->mode,2); putabits(bs,info->mode_ext,2); put1bit(bs,info->copyright); put1bit(bs,info->original); putabits(bs,info->emphasis,2);} /************************************************************************//*/* mod()/*/* 功能: 返回变量的绝对值
/*/************************************************************************/ double mod(a)double a;{ return (a > 0) ? a : -a;} /************************************************************************//*/* I_combine_LR (Layer I)/* II_combine_LR (Layer II)/*/* 功能:将左右声道组合成一个单声道/*/* 结构描述: 左右子带采样的平均值放入#joint_sample#中。/*/*/************************************************************************/ void I_combine_LR(sb_sample, joint_sample)double sb_sample[2][3][SCALE_BLOCK][SBLIMIT];double joint_sample[3][SCALE_BLOCK][SBLIMIT];{ int sb, smp; for(sb = 0; sb<SBLIMIT; ++sb) for(smp = 0; smp<SCALE_BLOCK; ++smp) joint_sample[0][smp][sb] = .5 * (sb_sample[0][0][smp][sb] + sb_sample[1][0][smp][sb]);} void II_combine_LR(sb_sample, joint_sample, sblimit)double sb_sample[2][3][SCALE_BLOCK][SBLIMIT];double joint_sample[3][SCALE_BLOCK][SBLIMIT];int sblimit;{ int sb, smp, sufr; for(sb = 0; sb<sblimit; ++sb) for(smp = 0; smp<SCALE_BLOCK; ++smp) for(sufr = 0; sufr<3; ++sufr) joint_sample[sufr][smp][sb] = .5 * (sb_sample[0][sufr][smp][sb] + sb_sample[1][sufr][smp][sb]);} /************************************************************************/*/* I_scale_factor_calc (Layer I)/* II_scale_factor_calc (Layer II)/*/* 功能:算每个子带中每组12个子带采样的比例因子/*/* 结构解释: 从#multiple[]#选择比12个子带抽样值的绝对值的最大值还要大的
做为比例因子,并将比例因子信息存入#scalar#中/*/* Layer II 有3组12子带采样/*/************************************************************************/ void I_scale_factor_calc(sb_sample,scalar,stereo)double sb_sample[][3][SCALE_BLOCK][SBLIMIT];unsigned int scalar[][3][SBLIMIT];int stereo;{ int i,j, k; double s[SBLIMIT]; for (k=0;k<stereo;k++) { for (i=0;i<SBLIMIT;i++) for (j=1, s[i] = mod(sb_sample[k][0][0][i]);j<SCALE_BLOCK;j++) if (mod(sb_sample[k][0][j][i]) > s[i]) s[i] = mod(sb_sample[k][0][j][i]); for (i=0;i<SBLIMIT;i++) for (j=SCALE_RANGE-2,scalar[k][0][i]=0;j>=0;j--) /* $A 6/16/92 */ if (s[i] <= multiple[j]) { scalar[k][0][i] = j; break; } }}/******************************** Layer II ******************************/ void II_scale_factor_calc(sb_sample,scalar,stereo,sblimit)double sb_sample[][3][SCALE_BLOCK][SBLIMIT];unsigned int scalar[][3][SBLIMIT];int stereo,sblimit;{ int i,j, k,t; double s[SBLIMIT]; for (k=0;k<stereo;k++) for (t=0;t<3;t++) { for (i=0;i<sblimit;i++) for (j=1, s[i] = mod(sb_sample[k][t][0][i]);j<SCALE_BLOCK;j++) if (mod(sb_sample[k][t][j][i]) > s[i]) s[i] = mod(sb_sample[k][t][j][i]); for (i=0;i<sblimit;i++) for (j=SCALE_RANGE-2,scalar[k][t][i]=0;j>=0;j--) /* $A 6/16/92 */ if (s[i] <= multiple[j]) { scalar[k][t][i] = j; break; } for (i=sblimit;i<SBLIMIT;i++) scalar[k][t][i] = SCALE_RANGE-1; }}/************************************************************************/*/* pick_scale (Layer II)/*/* 功能: 对每个子带,将3各比例因子中最小的和一个帧放入#max_sc#. /* 这用于心理声学模型I./*/************************************************************************/ void pick_scale(scalar, fr_ps, max_sc)unsigned int scalar[2][3][SBLIMIT];frame_params *fr_ps;double max_sc[2][SBLIMIT];{ int i,j,k; unsigned int max; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; for (k=0;k<stereo;k++) for (i=0;i<sblimit;max_sc[k][i] = multiple[max],i++) for (j=1, max = scalar[k][0][i];j<3;j++) if (max > scalar[k][j][i]) max = scalar[k][j][i]; for (i=sblimit;i<SBLIMIT;i++) max_sc[0][i] = max_sc[1][i] = 1E-20;}/************************************************************************/*/* put_scale (Layer I)/*/* 功能: 将#max_sc#设置为#scalar中的比例因子索引./*/************************************************************************/ void put_scale(scalar, fr_ps, max_sc)unsigned int scalar[2][3][SBLIMIT];frame_params *fr_ps;double max_sc[2][SBLIMIT];{ int i,k; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; for (k=0;k<stereo;k++) for (i=0;i<SBLIMIT;i++) max_sc[k][i] = multiple[scalar[k][0][i]];} /************************************************************************/*/* II_transmission_pattern (Layer II only)/*/* 功能:对给定的子带传送1个或2个或全部3个比例因子并填充相应的比例因子选择
信息/*/* 结构描述: 子带和信道根据三个比例因子的变化划分。如果三个比例因子变化
不大,则仅传送1个或2个比例因子。/*/************************************************************************/ void II_transmission_pattern(scalar, scfsi, fr_ps)unsigned int scalar[2][3][SBLIMIT];unsigned int scfsi[2][SBLIMIT];frame_params *fr_ps;{ int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int dscf[2]; int sclass[2],i,j,k; static int pattern[5][5] = {0x123, 0x122, 0x122, 0x133, 0x123, 0x113, 0x111, 0x111, 0x444, 0x113, 0x111, 0x111, 0x111, 0x333, 0x113, 0x222, 0x222, 0x222, 0x333, 0x123, 0x123, 0x122, 0x122, 0x133, 0x123}; for (k=0;k<stereo;k++) for (i=0;i<sblimit;i++) { dscf[0] = (scalar[k][0][i]-scalar[k][1][i]); dscf[1] = (scalar[k][1][i]-scalar[k][2][i]); for (j=0;j<2;j++) { if (dscf[j]<=-3) sclass[j] = 0; else if (dscf[j] > -3 && dscf[j] <0) sclass[j] = 1; else if (dscf[j] == 0) sclass[j] = 2; else if (dscf[j] > 0 && dscf[j] < 3) sclass[j] = 3; else sclass[j] = 4; } switch (pattern[sclass[0]][sclass[1]]) { case 0x123 : scfsi[k][i] = 0; break; case 0x122 : scfsi[k][i] = 3; scalar[k][2][i] = scalar[k][1][i]; break; case 0x133 : scfsi[k][i] = 3; scalar[k][1][i] = scalar[k][2][i]; break; case 0x113 : scfsi[k][i] = 1; scalar[k][1][i] = scalar[k][0][i]; break; case 0x111 : scfsi[k][i] = 2; scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; break; case 0x222 : scfsi[k][i] = 2; scalar[k][0][i] = scalar[k][2][i] = scalar[k][1][i]; break; case 0x333 : scfsi[k][i] = 2; scalar[k][0][i] = scalar[k][1][i] = scalar[k][2][i]; break; case 0x444 : scfsi[k][i] = 2; if (scalar[k][0][i] > scalar[k][2][i]) scalar[k][0][i] = scalar[k][2][i]; scalar[k][1][i] = scalar[k][2][i] = scalar[k][0][i]; } }} /************************************************************************/*/* I_encode_scale (Layer I)/* II_encode_scale (Layer II)/*/* 功能: 编码后的比例因子信息放入输出队列等待传送/*/************************************************************************/ void I_encode_scale(scalar, bit_alloc, fr_ps, bs)unsigned int scalar[2][3][SBLIMIT];unsigned int bit_alloc[2][SBLIMIT];frame_params *fr_ps;Bit_stream_struc *bs;{ int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int i,j; for (i=0;i<SBLIMIT;i++) for (j=0;j<stereo;j++) if (bit_alloc[j][i]) putabits(bs,scalar[j][0][i],6);} /***************************** Layer II ********************************/ void II_encode_scale(bit_alloc, scfsi, scalar, fr_ps, bs)unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT];unsigned int scalar[2][3][SBLIMIT];frame_params *fr_ps;Bit_stream_struc *bs;{ int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; int i,j,k; for (i=0;i<sblimit;i++) for (k=0;k<stereo;k++) if (bit_alloc[k][i]) putabits(bs,scfsi[k][i],2); for (i=0;i<sblimit;i++) for (k=0;k<stereo;k++) if (bit_alloc[k][i]) switch (scfsi[k][i]) { case 0: for (j=0;j<3;j++) putabits(bs,scalar[k][j][i],6); break; case 1: case 3: putabits(bs,scalar[k][0][i],6); putabits(bs,scalar[k][2][i],6); break; case 2: putabits(bs,scalar[k][0][i],6); }} /*=======================================================================\| 下面的程序是在心理声学模型已经计算出掩蔽阈值后进行的 || |\=======================================================================*/ /************************************************************************/*/* I_bits_for_nonoise (Layer I)/* II_bits_for_nonoise (Layer II)/*/* 功能:用计算出的掩蔽噪声比可以计算出分配给子带信号的量化位数/*/* 结构描述:/* bbal = # 用来为比特分配进行编码所需的bits /* bsel = # 用来为比例因子选择信息进行编码所需的bits/* banc = # 用来为辅助信息进行编码所需的bits/*/* 对每个子带和信道,我们累加bit的值直到出现以下情况:
/* -达到该信道能允许分配的最大bit位数
/* -掩蔽噪声比(MNR)好于或等于最小掩蔽水平
/*/* 支持联合立体声/*/************************************************************************/static double snr[18] = {0.00, 7.00, 11.00, 16.00, 20.84, 25.28, 31.59, 37.75, 43.84, 49.89, 55.93, 61.96, 67.98, 74.01, 80.03, 86.05, 92.01, 98.01};int I_bits_for_nonoise(perm_smr, fr_ps)double perm_smr[2][SBLIMIT];frame_params *fr_ps;{ int i,j,k; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; int req_bits = 0; req_bits = 32 + 4 * ( (jsbound * stereo) + (SBLIMIT-jsbound) ); for(i=0; i<SBLIMIT; ++i) for(j=0; j<((i<jsbound)?stereo:1); ++j) { for(k=0;k<14; ++k) if( (-perm_smr[j][i] + snr[k]) >= NOISY_MIN_MNR) break; /* 已找到足够的bit了 */ if(stereo == 2 && i >= jsbound) for(;k<14; ++k) if( (-perm_smr[1-j][i] + snr[k]) >= NOISY_MIN_MNR) break; if(k>0) req_bits += (k+1)*SCALE_BLOCK + 6*((i>=jsbound)?stereo:1); } return req_bits;} /***************************** Layer II ********************************/ int II_bits_for_nonoise(perm_smr, scfsi, fr_ps)double perm_smr[2][SBLIMIT];unsigned int scfsi[2][SBLIMIT];frame_params *fr_ps;{ int sb,ch,ba; int stereo = fr_ps->stereo; int sblimit = fr_ps->sblimit; int jsbound = fr_ps->jsbound; al_table *alloc = fr_ps->alloc; int req_bits = 0, bbal = 0, berr = 0, banc = 32; int maxAlloc, sel_bits, sc_bits, smp_bits;static int sfsPerScfsi[] = { 3,2,1,2 }; /* added 92-08-11 shn */ if (fr_ps->header->error_protection) berr=16; else berr=0; for (sb=0; sb<jsbound; ++sb) bbal += stereo * (*alloc)[sb][0].bits; for (sb=jsbound; sb<sblimit; ++sb) bbal += (*alloc)[sb][0].bits; req_bits = banc + bbal + berr; for(sb=0; sb<sblimit; ++sb) for(ch=0; ch<((sb<jsbound)?stereo:1); ++ch) { maxAlloc = (1<<(*alloc)[sb][0].bits)-1; sel_bits = sc_bits = smp_bits = 0; for(ba=0;ba<maxAlloc-1; ++ba) if( (-perm_smr[ch][sb] + snr[(*alloc)[sb][ba].quant+((ba>0)?1:0)]) >= NOISY_MIN_MNR) break; /* we found enough bits */ if(stereo == 2 && sb >= jsbound) /* check other JS channel */ for(;ba<maxAlloc-1; ++ba) if( (-perm_smr[1-ch][sb]+ snr[(*alloc)[sb][ba].quant+((ba>0)?1:0)]) >= NOISY_MIN_MNR) break; if(ba>0) { smp_bits = SCALE_BLOCK * ((*alloc)[sb][ba].group * (*alloc)[sb][ba].bits); /* scale factor bits required for subband */ sel_bits = 2; sc_bits = 6 * sfsPerScfsi[scfsi[ch][sb]]; if(stereo == 2 && sb >= jsbound) { /* each new js sb has L+R scfsis */ sel_bits += 2; sc_bits += 6 * sfsPerScfsi[scfsi[1-ch][sb]]; } req_bits += smp_bits+sel_bits+sc_bits; } } return req_bits;} /************************************************************************/*/* I_main_bit_allocation (Layer I)/* II_main_bit_allocation (Layer II)/*/* 功能: 对联合立体声模式,决定使用4中联合立体声中的哪种。然后调用 *_a_bit_allocation()
/* 它将为每个子带分配比特,知道比特用完和MNR达到阈值/*/*/************************************************************************/ void I_main_bit_allocation(perm_smr, bit_alloc, adb, fr_ps)double perm_smr[2][SBLIMIT];unsigned int bit_alloc[2][SBLIMIT];int *adb;frame_params *fr_ps;{ int noisy_sbs; int mode, mode_ext, lay, i; int rq_db, av_db = *adb;static int init = 0; if(init == 0) { /* rearrange snr for layer I */ snr[2] = snr[3]; for (i=3;i<16;i++) snr[i] = snr[i+2]; init = 1; } if((mode = fr_ps->actual_mode) == MPG_MD_JOINT_STEREO) { fr_ps->header->mode = MPG_MD_STEREO; fr_ps->header->mode_ext = 0; fr_ps->jsbound = fr_ps->sblimit; if(rq_db = I_bits_for_nonoise(perm_smr, fr_ps) > *adb) { fr_ps->header->mode = MPG_MD_JOINT_STEREO;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -