解码一帧Layer3第5步:立体声处理 -- class Layer3的ms_stereo和i_stereo方法
MP3采用的立体声编码方式有中侧立体和强度立体声两种。
1.中侧立体声(Middle/Side stereo)简称MS_stereo,在这种模式中,用中/侧声道规格化值Mi/Si取代左/右声道的值Li/Ri,重建左/右声道的值Li/Ri用下述公式:
变换前Mi值在左声道,Si值在右声道。应用上述公式把Mi/Si频谱值变换为Li/Ri并放到左/右声道,就完成了中侧立体声解码。
2.强度立体声(intensity stereo) 在MP3编码一帧结束后,有损压缩把频谱中表现音乐细节的高频成份压缩掉了。为了保留频谱中的高频部分,把这些高频数据编码附加到频带的后面部分。以长块为例,用rzero_bandL保存非零哈夫曼值的频带数,则从rzero_bandL至21的频带为强度立体声的编码数据。
压制MP3时采用强度立体声编码,能提升音乐的细节,使压缩后的MP3听起来层次上更丰富。但是,很遗憾地告诉你,强度立体声是专利算法,受法律保护滴,很多MP3压缩器都没的这个功能,所以用强度立体声编码的MP3并不多见。
对采用强度立体声编码的MP3,是否其进行强度声解码,不是训练有素的耳朵,听不出差别,反正我在调试程序时硬就没听出关闭强度立体声解码前后的区别。ISO/IEC 11172-3不对混合块中的长块作强度立体声处理,但很多MP3解码程序都作了处理,源码中把处理混合块中的长块的强度立体声的代码注释掉了,如果你愿意的话,可以取消掉注释把它加进来。是否对混合块中的长块作强度立体声处理,我也听不出什么差别,音乐细胞不发达呀,尽管我很喜欢听。记得去年的某个时候,我把以前买的CD拿出来听,好久没听过了,特亲切。放CD没的MP3方便,于是上网一顿海搜,找到MP3压缩器的No.1--LAME,用VBR模式的128Kpbs--320Kpbs,540M的CD压缩至不到60M,听起来和CD没的什么差别,觉得MP3编码真是个好,于是又上网海搜,想了解下MP3的技术细节,但是很遗憾,其中泛泛而谈的多,深入介绍其细节的少。好奇心的驱使下,想搞明白MP3的那些事,很长一段时间,业余时间就耗这上面了。也是有感于很多涉及MP3解码的关键技术的论文,都不是免费的,我就想把我弄清的部分公开出来,算是一个科谱宣传吧(这话说的:)可能你比我还懂的多)。
联合立体声,请复习《(二)用JAVA编写MP3解码器——帧头信息解码》,对联合立体声(jiont stereo)作了简介。
【提示】以下代码是Layer3.java的一部分,应遵守《(一)用JAVA编写MP3解码器——前言》中的许可协议。
今天就说到这,下回再说,上源码。class Layer3内的立体声解码方法的源码如下:
//5. //>>>>STEREO=============================================================== /* * 在requantizer方法内已经作了除以根2处理, ms_stereo()内不再除以根2. */ private void ms_stereo() { int sb, ss; float tmp0, tmp1; int rzero_xr = (rzero_index[0] > rzero_index[1]) ? rzero_index[0] : rzero_index[1]; int rzero_sb = (rzero_xr + 17) / 18; for (sb = 0; sb < rzero_sb; sb++) for (ss = 0; ss < 18; ss++) { tmp0 = xr[0][sb][ss]; tmp1 = xr[1][sb][ss]; xr[0][sb][ss] = tmp0 + tmp1; xr[1][sb][ss] = tmp0 - tmp1; } rzero_index[0] = rzero_index[1] = rzero_xr; } private static float[][] lsf_is_coef; private static float[] is_coef; /* * 解码一个频带强度立体声,MPEG 1.0 */ private void is_lines_1(int is_pos, int idx0, int max_width,int idx_step) { float xr0; int sb32 = idx0 / 18; int ss18 = idx0 % 18; for (int w = max_width; w > 0; w--) { xr0 = xr[0][sb32][ss18]; xr[0][sb32][ss18] = xr0 * is_coef[is_pos]; xr[1][sb32][ss18] = xr0 * is_coef[6 - is_pos]; ss18 += idx_step; if (ss18 >= 18) { ss18 -= 18; sb32++; } } } /* * 解码一个频带强度立体声,MPEG 2.0/2.5 */ private void is_lines_2(int tab2, int is_pos, int idx0, int max_width,int idx_step) { float xr0; int sb32 = idx0 / 18; int ss18 = idx0 % 18; for (int w = max_width; w > 0; w--) { xr0 = xr[0][sb32][ss18]; if (is_pos == 0) xr[1][sb32][ss18] = xr0; else { if ((is_pos & 1) == 0) xr[1][sb32][ss18] = xr0 * lsf_is_coef[tab2][(is_pos - 1) >> 1]; else { xr[0][sb32][ss18] = xr0 * lsf_is_coef[tab2][(is_pos - 1) >> 1]; xr[1][sb32][ss18] = xr0; } } ss18 += idx_step; if (ss18 >= 18) { ss18 -= 18; sb32++; } } } /* * 强度立体声(intensity stereo)解码 * 公式: * lsf_is_coef -- coefficients for LSF intensity stereo,ISO 13818-3,sesion 2.4.3.2 * lsf_is_coef[0][i] = (1 / sqrt(sqrt(2)))^(i + 1) * lsf_is_coef[1][i] = (1 / sqrt(2)) ^(i + 1) * i=0..14 * * is_coef -- coefficients for intensity stereo,iso11172-3,sesion 2.4.3.4.9.3 * is_coef[i] = tan(i * (PI / 12)) * is_coef[i] = is_coef[i] / (1 + is_coef[i]) * i=0..6 */ private void i_stereo(final int gr) { if(objSI.ch[0].gr[gr].mixed_block_flag != objSI.ch[1].gr[gr].mixed_block_flag || objSI.ch[0].gr[gr].block_type != objSI.ch[1].gr[gr].block_type) return; GRInfo gr_info = objSI.ch[1].gr[gr]; //信息保存在右声道. int is_p, idx, sfb; if(objHeader.getVersion() == Header.MPEG1) { //MPEG 1.0 if(gr_info.block_type == 2) { //MPEG 1.0, short block/mixed block int w3; //int do_long = 0; //if(gr_info.mixed_block_flag == 1) // do_long = 1; for (w3 = 0; w3 < 3; w3++) { sfb = rzero_bandS[w3]; //混合块sfb最小为3 //if (sfb > 3) // do_long = 0; for (; sfb < 12; sfb++) { idx = 3*intSfbIdxShort[sfb] + w3; is_p = scfS[1][w3][sfb]; if(is_p >= 7) continue; is_lines_1(is_p,idx,intWidthShort[sfb],3); } } /*if(do_long == 1) { for (sfb = rzero_bandL; sfb < 8; sfb++) { is_p = scfL[1][sfb]; if(is_p < 7) is_lines_1(is_p,sfbIndexOfEndL[sfb],intWidthLong[sfb],1); } }*/ } else { //MPEG 1.0, long block for (sfb = rzero_bandL; sfb <= 21; sfb++) { is_p = scfL[1][sfb]; if(is_p < 7) is_lines_1(is_p,intSfbIdxLong[sfb],intWidthLong[sfb],1); } } } else { //MPEG 2.0/2.5 final int tab2 = gr_info.scalefac_compress & 0x1; if(gr_info.block_type == 2) { //MPEG 2.0/2.5, short block/mixed block int w3; //int do_long = 0; for (w3 = 0; w3 < 3; w3++) { sfb = rzero_bandS[w3]; //混合块sfb最小为3 //if (sfb > 3) // do_long = 0; for (; sfb < 12; sfb++) { idx = 3*intSfbIdxShort[sfb] + w3; is_p = scfS[1][w3][sfb]; is_lines_2(tab2, scfS[1][w3][sfb], idx, intWidthShort[sfb],3); } } //if(do_long == 1) // for (sfb = rzero_bandL; sfb < 8; sfb++) // is_lines_2(tab2, scfL[1][sfb], sfbIndexOfEndL[sfb], intWidthLong[sfb],1); } else { //MPEG 2.0/2.5, long block for (sfb = rzero_bandL; sfb <= 21; sfb++) is_lines_2(tab2, scfL[1][sfb], intSfbIdxLong[sfb], intWidthLong[sfb],1); } } } //<<<<STEREO===============================================================
【下载地址】http://jmp123.sourceforge.net/
相关推荐
在"pcm-capture-play"这个项目中,源代码很可能是用C++、C#或Java等编程语言编写的,涵盖了音频采集、编码/解码(如果涉及G711-Alaw)和播放的整个流程。开发者可能使用了一些开源库,如PortAudio用于跨平台的音频I/...
嵌入式八股文面试题库资料知识宝典-华为的面试试题.zip
训练导控系统设计.pdf
嵌入式八股文面试题库资料知识宝典-网络编程.zip
人脸转正GAN模型的高效压缩.pdf
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
少儿编程scratch项目源代码文件案例素材-鸡蛋.zip
嵌入式系统_USB设备枚举与HID通信_CH559单片机USB主机键盘鼠标复合设备控制_基于CH559单片机的USB主机模式设备枚举与键盘鼠标数据收发系统支持复合设备识别与HID
嵌入式八股文面试题库资料知识宝典-linux常见面试题.zip
面向智慧工地的压力机在线数据的预警应用开发.pdf
基于Unity3D的鱼类运动行为可视化研究.pdf
少儿编程scratch项目源代码文件案例素材-霍格沃茨魔法学校.zip
少儿编程scratch项目源代码文件案例素材-金币冲刺.zip
内容概要:本文深入探讨了HarmonyOS编译构建子系统的作用及其技术细节。作为鸿蒙操作系统背后的关键技术之一,编译构建子系统通过GN和Ninja工具实现了高效的源代码到机器代码的转换,确保了系统的稳定性和性能优化。该系统不仅支持多系统版本构建、芯片厂商定制,还具备强大的调试与维护能力。其高效编译速度、灵活性和可扩展性使其在华为设备和其他智能终端中发挥了重要作用。文章还比较了HarmonyOS编译构建子系统与安卓和iOS编译系统的异同,并展望了其未来的发展趋势和技术演进方向。; 适合人群:对操作系统底层技术感兴趣的开发者、工程师和技术爱好者。; 使用场景及目标:①了解HarmonyOS编译构建子系统的基本概念和工作原理;②掌握其在不同设备上的应用和优化策略;③对比HarmonyOS与安卓、iOS编译系统的差异;④探索其未来发展方向和技术演进路径。; 其他说明:本文详细介绍了HarmonyOS编译构建子系统的架构设计、核心功能和实际应用案例,强调了其在万物互联时代的重要性和潜力。阅读时建议重点关注编译构建子系统的独特优势及其对鸿蒙生态系统的深远影响。
嵌入式八股文面试题库资料知识宝典-奇虎360 2015校园招聘C++研发工程师笔试题.zip
嵌入式八股文面试题库资料知识宝典-腾讯2014校园招聘C语言笔试题(附答案).zip
双种群变异策略改进RWCE算法优化换热网络.pdf
内容概要:本文详细介绍了基于瞬时无功功率理论的三电平有源电力滤波器(APF)仿真研究。主要内容涵盖并联型APF的工作原理、三相三电平NPC结构、谐波检测方法(ipiq)、双闭环控制策略(电压外环+电流内环PI控制)以及SVPWM矢量调制技术。仿真结果显示,在APF投入前后,电网电流THD从21.9%降至3.77%,显著提高了电能质量。 适用人群:从事电力系统研究、电力电子技术开发的专业人士,尤其是对有源电力滤波器及其仿真感兴趣的工程师和技术人员。 使用场景及目标:适用于需要解决电力系统中谐波污染和无功补偿问题的研究项目。目标是通过仿真验证APF的有效性和可行性,优化电力系统的电能质量。 其他说明:文中提到的仿真模型涉及多个关键模块,如三相交流电压模块、非线性负载、信号采集模块、LC滤波器模块等,这些模块的设计和协同工作对于实现良好的谐波抑制和无功补偿至关重要。
内容概要:本文探讨了在工业自动化和物联网交汇背景下,构建OPC DA转MQTT网关软件的需求及其具体实现方法。文中详细介绍了如何利用Python编程语言及相关库(如OpenOPC用于读取OPC DA数据,paho-mqtt用于MQTT消息传递),完成从OPC DA数据解析、格式转换到最终通过MQTT协议发布数据的关键步骤。此外,还讨论了针对不良网络环境下数据传输优化措施以及后续测试验证过程。 适合人群:从事工业自动化系统集成、物联网项目开发的技术人员,特别是那些希望提升跨协议数据交换能力的专业人士。 使用场景及目标:适用于需要在不同通信协议间建立高效稳定的数据通道的应用场合,比如制造业生产线监控、远程设备管理等。主要目的是克服传统有线网络限制,实现在不稳定无线网络条件下仍能保持良好性能的数据传输。 其他说明:文中提供了具体的代码片段帮助理解整个流程,并强调了实际部署过程中可能遇到的问题及解决方案。
基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档~ 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档