流行音频解码的嵌入式移植-毕业论文_第1页
流行音频解码的嵌入式移植-毕业论文_第2页
流行音频解码的嵌入式移植-毕业论文_第3页
流行音频解码的嵌入式移植-毕业论文_第4页
流行音频解码的嵌入式移植-毕业论文_第5页
免费预览已结束,剩余40页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本科毕业论文(科研训练、毕业设计)题 目:流行音频解码的嵌入式移植姓 名:学 院:软件学院系:软件工程专 业:软件工程年 级: 学 号:指导教师(校内): 职称: 指导教师(校内): 职称: 指导教师(校外): 职称: 年 月39厦门大学本科毕业论文流行音频解码的嵌入式移植摘要 本文以S3C2410作为目标平台,介绍WMA音频解码程序的优化和移植。首先提出项目的背景和目标,接着,介绍系统的软硬件开发平台以及相关开发工具。然后,针对S3C2410目标平台的特性,提出优化WMA解码程序的总体方案。重点阐述通过浮点转定点、空间换时间以及汇编等方案来优化MPlayer中WMA解码程序的详细过程。最后,以图表的形式对优化前后WMA解码速度进行对比,体现出优化的效果,并提出进一步的优化方案。关键词 WMA解码优化 浮点转定点 S3C2410 MPlayerTransplantation of popular audio decoder to Embedded SystemAbstract In this paper, we describe the optimization and transplantation of WMA audio decoder to S3C2410 platform. Firstly, we point out the background and meaning of the project. In succession, we introduce the hardware platform, software platform and related tools about this project. According to the characteristic of S3C2410, we bring forward the total methods to optimizing WMA decoder. Then, we describe that using convert of float point number to fixed point number; using space to save time and using assemble language to optimize WMA decoder of mplayer in details. Finally, we compare the primary WMA decoder with the optimized WMA decoder through diagrams and tables; showing the optimized result of WMA decoder. According to the result, we introduce the advanced optimized methods to optimize WMA decoder in MPlayer.Key words optimizing WMA decoder float number to fixed number S3C2410 MPlayerContents目录第一章 引言111 项目背景和意义112 总体设计目标2第二章 软硬件开发平台以及开发工具简介321 硬件平台322 软件平台6221 MPlayer介绍6222 mplayer.c中main函数框架6223 MPlayer中的WMA解码程序8224 GDB+GdbServer远程调试工具9第三章 MPlayer的移植以及WMA解码优化方案的提出1231 MPlayer的移植1232 提出WMA解码优化方案13第四章 详细优化过程1441 浮点运算转定点运算14411 浮点数与定点数14412 定点化原理16413 关键运算的实现19414 定点化WMA解码库2242 空间换时间2543 汇编优化25第五章 优化结果32第六章 结束语35致谢语36参考文献37附录38ContentsChapter 1 Preamble111 The Background and Meaning of The Project112 Total Designal Object2Chapter 2 Software Platform, Hardware Platform and Related Tools of The Project321 Hardware Platform322 Software Platform6221 Introduction of MPlayer6222 The Frame of Main Function in mplayer.c6223 WMA Decoder Program in MPlayer8224 Remote Debug Tool GDB+GdbServer9Chapter 3 Transplatation of MPlayer and Introducing Methods of Optimizing WMA Decoder1231 Transplatation of MPlayer1232 Introducing Methods of Optimizing WMA Decoder13Chapter 4 Particular Process of Optimization1441 Converting Float Number to Fixed Number14411 Float Number and Fixed Number14412 The Principle of Fixing16413 The Implement of Important Calculation19414 Fixing WMA Decoder2242 Using Space to Save time2543 Using Assemble Language to Optimize25Chapter 5 The Results of Optimization32Chapter 6 Summary35Acknowledgement36References37Supplement38第一章 引言第一章 引言随着计算机技术的迅速发展,嵌入式设备在信息家电、仪器仪表、数据网络、工业控制、医疗卫生和航空航天等众多领域得到了广泛的应用,巨大的市场需求也促使了嵌入式软硬件技术的不断进步。近年来,在各类电子消费产品中,嵌入式数字音频设备受到了广大消费者的青睐。因此,开发一个嵌入式音频播放设备,既可以单独应用,也可以作为其他系统的子模块,具有广泛的应用前景和实际意义。11 项目背景和意义这次毕业设计,我参加了Mediatek厦门大学软件学院嵌入式多媒体联合实验室的一个实习项目流行音频解码的嵌入式移植。该项目以fft-2410实验箱(S3C2410)作为目标平台,实现MP3和WMA等音频解码程序的优化和移植。我主要负责WMA音频解码模块,在这里,先从软硬件等方面来对该项目背景做个简要介绍。在硬件方面,ARM体系作为嵌入式系统设计的通用处理器内核,具备高性能、低功耗、易扩展的特点,尤其是ARM9系列微处理器在高性能和低功耗特性方面提供了最佳的性能,并且也提供了很好的综合功能,能够满足许多嵌入式系统的应用需求。目前,市场上比较多的ARM9芯片是S3C2410。使用S3C2410作为目标平台,在性能和价格等方面都比较合理。在软件方面,MPlayer是一个面向Linux操作系统的媒体播放软件。它不仅支持各种各样的输出设备,而且支持几乎全部的流行媒体格式,包括WMA音频格式。MPlayer是开源软件,使用它的解码库来解码WMA文件,便于我们对源代码进行修改和优化,使其符合我们的系统开发要求。在多媒体音频方面,WMA(Windows Media Audio)是微软公司推出与MP3格式齐名的一种音频压缩格式,支持Stream流技术和版权保护。WMA即使在较低的采样频率下也能产生较好的音质。这些特性使得WMA音频文件得到了广泛的应用,尤其适用于数字电台架设、在线试听等领域。从以上几个方面的分析可知,以S3C2410作为目标平台,优化MPlayer中的WMA音频解码程序,最终移植到目标平台,不仅具有可行性,而且具有广泛的应用前景和意义。这个项目严格按照实习项目的要求来开发,最终要应用到实际项目中,具有现实应用意义。另外,该项目的开发具有一定的难度,涉及的知识面广,参与这个项目的开发,也能使我各方面的能力得到进一步的提高。12 总体设计目标我们以S3C2410(FFT2410实验箱)为目标平台,把MPlayer移植到目标平台上,用来播放WMA音频文件,最终实现WMA音频解码的嵌入式移植。对于没有优化的WMA解码库,如果在目标平台上,解码速度不够快,再通过浮点运算转定点运算、空间换时间以及汇编等优化方案,对MPlayer中的WMA解码库进行优化,最终在S3C2410目标平台上,使得WMA的解码速度得到显著提升,甚至能够流畅播放WMA音频文件。与PC机上应用系统的开发不同,在嵌入式系统开发中,软件和硬件结合的比较紧密,应用程序的开发必须严格按照目标系统的特性来进行。因此,在开发中,要先了解开发环境以及目标系统的特性,然后针对这些特性来进行开发。第二章 软硬件开发平台以及开发工具简介第二章 软硬件开发平台以及开发工具简介绝大多数Linux 软件开发都是以native 方式进行的,即本机(HOST)开发、调试,本机运行的方式。这种方式通常不适合于嵌入式系统的软件开发,因为对于嵌入式系统开发来说,没有足够的资源在本机(即目标系统)运行开发工具和调试工具。通常,嵌入式系统的软件开发采用一种交叉编译调试的方式。所谓的交叉编译就是:利用运行在某机器上的编译器编译某个源程序生成在另一台机器上运行的目标代码的过程。交叉编译调试环境建立在宿主机(即一台PC 机)上,对应的开发板叫做目标板。运行Linux 的PC(宿主机)开发时使用宿主机上的交叉编译、汇编及连接工具形成可执行的二进制代码(这种可执行代码并不能在宿主机上执行,而只能在目标板上执行),然后把可执行文件下载到目标机上运行。调试时可以使用串口,以太网口等,具体使用哪种调试方法可以根据目标机处理器提供的支持做出选择。在编译器编译时可以选择开发所需的宿主机和目标机从而建立开发环境。在进行嵌入式开发前第一步的工作就是要安装一台装有指定操作系统的PC 机作宿主开发机,对于嵌入式LINUX,宿主机上的操作系统一般要求为REDHAT LINUX。嵌入式开发通常要求宿主机配置有网络,支持NFS(为交叉开发时mount 所用)。然后要在宿主机上建立交叉编译调试的开发环境,最主要的就是安装交叉编译器。因此,在这一章里将介绍S3C2410、MPlayer等软硬件开发平台以及相关开发工具。21 硬件平台宿主机(PC)我们采用通常的个人计算机,操作系统使用 REDHAT LINUX 9.0,在安装的时候,选择了全部安装,保证具备了各种服务(比如:NFS)。目标板我们采用fft-2410实验箱,如图2-1所示,它是由傅立叶电子科技有限公司设计生产的ARM9 的嵌入式电脑平台,它基于三星公司的ARM 处理器S3C2410,适用于设计移动手持设备类产品,具有高性能、低功耗、接口丰富和体积小等优良特性。fft-2410 正是基于此芯片本身的各种特点而设计的。图2-1 fft-2410实验箱S3C2410 使用ARM920T 内核,该内核是ARM 公司系列微处理器核的一种,它采用5 阶段管道化技术,同时配备了Thumb扩展、Embedded ICE 调试技术和Harvard 总线,内部带有全性能的MMU(内存处理单元)。在生产工艺相同的情况下,性能可达ARM7TDMI 的2倍以上。S3C2410芯片不具有FPU(浮点运算单元),在S3C2410执行浮点运算实际上是通过软浮点的形式来实现的,即通过调用目标平台上的Float Point Emulator 软件来模拟浮点运算。这样一来,当程序对浮点运算要求较高时,就有必要减少浮点运算或者把浮点运算转化为定点运算,从而使程序在目标平台上的执行效率得到提高。在硬件上,fft-2410 采用核心板与接口分离的形式,将S3C2410 的最小系统高度集成在核心板上,而系统的外围设备,以太网络、视频、音频、SD卡等则从地板上引出。fft-2410实验箱硬件描述:S3C2410:16/32bit ARM920T内核;标准工作频率:203MHz;运算能力:220MIPS;最高工作频率:266MHz;系统时钟:内部PLL产生200266MHz CPU内核工作频率;外部总线频率:100133MHz ;FlashRom:核心板64Mbyte NandFlash;SDRAM:核心板64Mbyte(可升级至128Mbyte);LCD控制器:CPU内置STN/CSTN/TFT LCD控制器,支持1024*768分辨率下的各种液晶VGA接口(需选配VGA卡);触摸屏控制器:CPU内置4线制电阻式触摸屏控制器 ;UART:2通道RS232串口;RS485:1路 ;USB主口:4个;USB从口:1个 ;SD/MMC卡接口:1个;RTC实时时钟:具备后备电池插座;IIC接口的EEPROM:1个;A/D:8通道,500KSPS采样,12位分辨率;D/A:2通道,8位;SPI:2通道SPI高速同步串行口;IIS音频输入/输出接口;麦克风输入接口:1个;1W扬声器:1个;中断和测试按键:4个;10M以太网口:1个;10M/100M以太网口:1个; 多功能扩展口:32bit数据总线 /bit地址总线 /片选、读写、中断等系统控制总线;8 X 8 LED矩阵:1组;数码管:2个;流水LED灯:4个;JTAG:接口;高速CAN总线接口2路,总线模式;直流电机:1个;一路IDE 接口,可完成硬盘挂接测试试验;支持的操作系统:WINCE /Linux/uCOS-II。在软件上,fft-2410采用了韩国MIZI 公司所公布的开放源代码的免费嵌入式操作系统arm-Linux以及GNU的arm-linux-gcc 3.3.2交叉编译器。arm-linux-gcc就是一种交叉编译器,它是GCC的ARM 改版。GCC是个功能强大的C 语言编译工具,其年龄比Linux 还长。交叉编译器可以通过下载源码编译安装,不过,我们采用的实验箱,提供了编译后的arm-linux-gcc编译器,直接把现成的编译器文件复制到相应的PC机目录下并进行相应的配置即可,十分方便。22 软件平台221 MPlayer介绍MPlayer是Linux 上的媒体播放器,也能跑在许多其它Unices上,甚至非x86CPU上。它通过调用各种编解码器,播放大多数MPEG,VOB,AVI,OGG,VIVO,ASF/WMV,QT/MOV,FLI,RM,NuppelVideo,yuv4mpeg,FILM,RoQ文件。MPlayer不需要avifile库,就可以播放VideoCD,SVCD,DVD,3ivx,RealMedia,和DivX格式的电影。MPlayer的另一个大的特色是广泛的输出设备支持。它可以在X11,Xv,DGA, OpenGL,SVGAlib,fbdev,AAlib,DirectFB下工作,也可以使用GGI和SDL和一些低级的硬件相关的驱动模式。MPlayer还支持通过硬件MPEG解码卡显示,诸如DVB 和DXR3与Hollywood+。MPlayer支持十几种字幕格式,同时也提供多种皮肤界面供用户使用。MPlayer是一个开源软件,方便开发者进行进一步开发。MPlayer中包含了许多编解码库,FFmpeg就是其中一个。FFmpeg包括一组开放源码的解码器包,能够提供比Win32解码器或DivX.com的DivX4/5库更高的速度解码以 H263/MJPEG/RV10/DivX3/DivX4/DivX5/MP41/MP42/WMV1/WMV2/HuffYUV编码格式编码的视频流。同时,它还包含很多不错的解码器,包括DivX 3,DivX 4,DivX 5,Windows Media Video 7(WMV1)以及WMA音频解码器。MPlayer的主程序在源码目录下的mplayer.c文件中,而FFmpeg的源代码在MPlayer源码包的libavcodec目录下,WMA解码程序主要在这个目录下的wmadec.c文件中,因此,分析wmadec.c和mplayer.c中的源代码以及两者之间的关系,对下一步的优化工作是很有必要的。222 mplayer.c中main函数框架mplayer.c中的main函数是整个程序的入口点,MPlayer的总体流程就是在main函数中体现,通过对mplayer.c文件的分析,得到了main函数的总体框架,如图2-2所示。图2-2 mplayer.c中main函数框架图对main函数的总体框架有了一定了解后,有助于我们了解程序流程以及函数之间的调用关系,进而帮助我们在优化时对程序进行跟踪调试。223 MPlayer中的WMA解码程序MPlayer中的WMA解码程序主要在wmadec.c文件中,在这个文件里定义了WMA解码相关的结构体和函数。WMADecodeContext结构体,它包含了WMA文件解码的相关信息。WMA解码初始化函数wma_decode_init,这个函数主要负责初始化WMADecodeContext结构体以及DSP相关操作。WMA解码结束函数wma_decode_end,这个函数主要负责一些资源的释放工作。WMA解码函数主要包括三个:wma_decode_superframe、wma_decode_frame以及wma_decode_block。因为WMA编码时,一个superframe包含一个或多个frame,一个frame又包含一个或多个block。所以解码时,先调用wma_decode_superframe,它再去调用wma_decode_frame,最后,这个函数再去调用wma_decode_block。另外,decode_exp_vlc和decode_exp_lsp也是解码相关的函数。WMA文件如果采用LSP指数编码,则调用decode_exp_lsp函数;如果采用VLC指数编码,则调用decode_exp_vlc函数。一个WMA文件要么采用VLC指数编码,要么采用LSP指数编码,不会同时采用两种指数编码,这两个函数是不同的分支。因此,在测试的时候,也要拿两种不同指数编码类型的文件来分别测试。在wmadec.c文件的最后定义了两个AVCodec结构体类型的变量,一个是针对第一版本的WMA文件,另一个是针对第二版本的,两个变量差别不大。这里只列出针对V2的结构体变量,并做简要说明。AVCodec wmav2_decoder = wmav2, CODEC_TYPE_AUDIO, CODEC_ID_WMAV2, sizeof (WMADecodeContext), wma_decode_init, NULL, wma_decode_end, wma_decode_superframe,;AVCodec结构体定义了MPlayer中各种音频以及视频相同的编解码变量和函数,在这里可以把这个结构体理解为面向对象中的类,其中的变量和函数声明,相当于类中成员变量以及成员函数声明。在wmav2_decoder结构体变量中,定义了WMA文件的版本、类型、ID以及大小这几个变量,定义了音频解码初始化函数为wma_decode_init,音频解码结束函数为wma_decode_end,音频解码函数为wma_decode_superframe。定义了这个变量以后,MPlayer主程序在解码WMA音频的时候就会调用这三个函数进行解码。也就是说,wmav2_decoder变量声明了外部文件或程序调用WMA解码的API。解码一个WMA文件,wma_decode_init和wma_decode_end只调用一次,然后循环调用wma_decode_superframe来进行解码。因此在优化的时候,需要重点优化频繁调用的wma_decode_superframe、wma_decode_frame和wma_decode_block这几个函数,尤其是wma_decode_block及其所调用的函数。从这里我们也可以看出,MPlayer程序框架的具有良好的可扩展性。当要添加一种新的解码库,只需要定义好相应的解码函数,然后定义一个AVCodec结构体变量,最后在调用处声明这个外部变量,即可调用,十分灵活。这个WMA解码函数只支持V1以及V2的WMA文件,WMA 9 Pro版本的WMA音频文件需要使用另外的解码库。目前,大部分WMA文件都是按照V2版本编码的,因此,wmadec.c中的解码函数可以解码大部分WMA音频文件。224 GDB+GdbServer远程调试工具一般情况下,程序中明显的错误容易查出,而一些逻辑上的、隐蔽的错误则很难直接找出来,这时就需要调试器的帮助。调试器用来跟踪可执行程序的运行情况,它使你能够在程序运行时观察程序的内部结构和内存的使用情况,从而根据这些信息对有错误的程序进行修改。在这一小节里,我将介绍针对嵌入式平台的远程调试工具。使用过VC 6.0的人,应该都领略过VC图形化调试工具的强大功能。在Linux下,调试跟踪工具虽然没有像VC的图形化调试工具那么简单,但是GNU的GDB调试工具提供的强大功能,也能方便地帮助你对程序进行跟踪调试。GDB的主要功能包括:监视程序中变量的值、可设置断点以及单步调试等。另外,GDB能够在C和汇编语言之间自动切换,因此对于C和汇编混合编程的程序,GDB也能同时地、方便地对程序进行跟踪。以下列出GDB常用的一些命令(按字母顺序排列):break/b NUM在指定的行上设置断点。bt 显示所有的调用栈帧。该命令可用来显示函数的调用顺序。clear 删除设置在特定源文件、特定行上的断点。其用法为:clear FILENAME:NUM。continue/c继续执行正在调试的程序,在下一断点处停止执行。该命令用在程序由于处理信号或断点而导致停止运行时。delete/d NUM删除指定的断点。display EXPR 每次程序停止后显示表达式的值,表达式由程序定义的变量组成。file FILE 装载指定的可执行文件进行调试。help NAME 显示指定命令的帮助信息。info break 显示当前断点清单,包括到达断点处的次数等。info files 显示被调试文件的详细信息。info func 显示所有的函数名称。info local 显示当函数中的局部变量信息。info prog 显示被调试程序的执行状态。info register显示当前各个寄存器的值,常用于汇编程序调试。info var 显示所有的全局和静态变量名称。kill 终止正被调试的程序。list/l 显示源代码段,也可以在list 后面加上FILENAME:NUM参数。make 在不退出GDB的情况下运行make 工具。next/n 在不单步执行进入其他函数的情况下,向前执行一行源代码。print EXPR 显示表达式EXPR 的值。run/r FILE开始运行待调试的程序。step/s在单步执行进入其他函数的情况下,向前执行一行源代码。GDB支持很多与UNIX shell程序一样的命令编辑特征,按Tab 键让GDB帮你补齐一个唯一的命令,如果不唯一的话GDB会列出所有匹配的命令。你也能用光标键上下翻动历史命令。在Linux操作系统下,一般带有GDB调试工具,在PC机上可以方便使用。由于嵌入式实验设备资源的有限性,在嵌入式设备上调试用户程序需要通过远程调试这种方式来实现。远程调试环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用GDB标准串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。调试stub是嵌入式系统中的一段代码,作为宿主机GDB和目标机调试程序间的一个媒介而存在。远程调试一般采用GDB + GdbServer的方式,GDB在宿主机上运行,GdbServer则在目标系统中运行。这里的GDB和GdbServer都是要针对目标板编译生成的二进制可执行文件,不能直接使用Linux操作系统自带的GDB。因此,需要下载GDB源码到本地机子,然后针对目标平台,对源码进行编译,生成需要的GDB和GdbServer可执行程序。建立好远程调试环境后,就可以使用GDBGdbServer来调试目标板上的程序。在优化WMA解码库的过程中,难免会出现一些错误,而对于那些隐蔽的错误,可以通过远程调试来查找错误。因此,了解GDB调试工具的作用以及使用方法,对下一步的开发也是很有必要的。第三章 MPlayer的移植以及WMA解码优化方案的提出第三章 MPlayer的移植以及WMA解码优化方案的提出从上一章中,我们了解到了系统开发的软硬件开发平台以及相关工具。在这一章里我们将介绍把未优化的MPlayer移植到目标平台的过程,并尝试用MPlayer在目标平台上播放WMA音频文件,然后根据播放效果提出优化WMA解码的总体方案。31 MPlayer的移植所谓MPlayer移植就是使用交叉编译器把MPlayer源码编译成能够在目标平台上正确执行的程序的过程。采用的交叉编译器为arm-linux-gcc 3.3.2,MPlayer采用MPlayer v1.0rc1源码。首先对MPlayer源码进行交叉编译,先运行configure命令对源码进行配置,再运行make命令对源码进行交叉编译(这时使用的编译器是arm-linux-gcc)。如果编译过程没有错误,就可以在MPlayer的源码目录下生成mplayer可执行程序,它是运行在S3C2410目标平台上的。然后通过NFS把mplayer所在的目录mount到目标板上,就可以尝试在板子上执行mplayer程序。如果可执行程序能够正确运行,就完成了移植过程。在移植的过程中,关键的就是配置这一环节。在配置的时候要加上一些参数,有选择地编译MPlayer源码。比如我们采用的目标平台是S3C2410,运行在目标平台上的是Linux操作系统,在配置的时候就可以通过“-target=arm-linux”选项,指明所使用的目标平台。“-enable-static”选项,用来指定把mplayer编译成静态的。“-disable-gui”用来指定mplayer不使用图形化界面。一般情况下,一个选项都有disable和enable两种,你可以根据需要来选择。有的选项,单单enable是不够的,比如“-enable-mad”选项。MAD是开源的MP3定点解码库,它适合于在嵌入式设备上解码MP3文件。如果需要把MAD解码库编译进mplayer中,不仅仅要加上“-enable-mad”选项,而且还要先交叉编译MAD源码,生成mad.h文件以及MAD解码链接库。然后使用“-with-extraincdir=PATH”指定mad.h所在的路径,使用“-with-extralibdir=PATH”指定MAD相关链接库所在的路径。加上这三个选项之后,就可以成功把MAD解码库编译到mplayer可执行程序中。另外,MPlayer中还有很多配置选项可以选,你可以通过./configure -help 命令查看所有的选项以及这些选项的含义,明白了这些选项的意义之后,就可以根据需要来设置相应的选项。32 提出WMA解码优化方案使用上一节移植到目标平台上的可执行程序,尝试在目标平台上播放一个WMA文件,我们看到的结果是:初始化过程比较慢,播放的时候,断断续续的,而且停顿的时间很长,不能流畅播放WMA音频文件。MPlayer播放时,会在终端上实时显示一些信息,其中有一个参数表示的时CPU使用率,这时我们看到CPU使用率为1000%左右。上面的现象表明: MPlayer中的WMA解码库在S3C2410上的解码速度不够快,需要对其进行优化,才能使解码的速度提高,甚至达到流畅播放WMA文件的效果。根据S3C2410目标平台的特性,我们提出了以下几种方案来对WMA解码程序进行优化:(1) 浮点运算转为定点运算:S3C2410上没有FPU(浮点运算单元),浮点运算是通过仿真方式来实现的,如果程序中浮点运算比较多,就会耗费比较多的时间。wmadec.c中的解码函数用到的浮点运算比较多,所以可以首先考虑把浮点运算转为定点运算。(2) 空间换时间:对于一些运算,可以通过查表方式来获取计算结果;另外,对于被频繁调用的小函数采用inline 关键字修饰。虽然以上两点会增加数据段和代码段的空间,但是获得的性能改善也是显著的。(3) 汇编优化:对于关键运算,采用汇编语言实现,以获得更高效的目标代码,从而提高系统的性能。第四章 详细优化过程第四章 详细优化过程在这一章里,将介绍使用浮点运算转为定点运算、空间换时间以及汇编优化这三种方案对MPlayer中WMA解码程序进行优化的详细过程。41 浮点运算转定点运算411 浮点数与定点数在计算机内部表示数据时,为了节省空间,数值型数据的小数点位置是隐含的,且小数点位置既可以是固定的,也可以是变化的。如果小数点的位置已经事先确定好了,不再改变,此类型的数据称为定点数,例如C语言中的int类型;如果小数点位置是可变的,则称为浮点数,例如C语言中的float类型。假设用两个字节来存储数值型数据,采用定点数的方式,小数点位置在第7位与第8位之间,同样小数点也是隐含的,如图4-1所示:图4-1 定点数的存储方式按照图4-1的存储方式,二进制数10.01B,即十进制数2.25的存储方式如图4-2所示:图4-2 10.01B定点数的存储方式对于定点数,只要小数点位置固定了,它所能表示数的范围以及精度就确定了。如图4-1的存储方式,小数点位置在第7位和第8位之间,则小数点右边的8位就用来表示精度,小数点左边的8位就用来表示数值(整数部分)的范围。不过,这种存储方式有一个缺点,如果我们只需要使用小数点后4位来表示精度时,那么存储空间最低的4位就没有使用,造成浪费。如图4-3所示,进行 10.0010B + 100.0101B二进制运算时,最低的4位存储空间就白白浪费了,如果小数点的位置在第3位到第4位之间,则空间就不会浪费,多出了4位(这时小数点左边已经变成12位)来表示数据,这样所能表示的数据范围就扩大了。浮点数正是居于这种思想产生的。图4-3 定点数加法运算浮点数分为单精度和双精度两种,相当于C语言中的float和double类型。由于在定点化过程中,只涉及float类型,所以在这里只介绍float类型的存储格式。double类型的存储格式请参考相关文档。目前大多数高级语言(包括C)都按照IEEE-754标准来规定浮点数的存储格式,IEEE-754规定,单精度浮点数用4个字节存储,分为三个部分:符号位、阶码和尾数。阶码即指数,尾数即规范化后的有效小数。其中,符号位占1位,阶码占8位,尾数占23位。实际上,尾数总共为24位,在第22位和第23位之间有一个隐含位也要加到尾数部分。如图4-4所示:图4-4 IEEE单精度浮点数格式在单精度浮点数格式中,尾数部分必须是规范化的尾数,当规范化一个浮点数时,总是调整它使其值大于等于1而小于2,这样就允许只存储23位就可以表示24位尾数,隐含的1位是规范化后浮点数的第一位。因为规范化的尾数大于等于1而小于2,所以这个隐含位始终为1。例如110100B,对其规格化的结果为1.101B乘以25,尾数为1.101B,但最高位的1并不需要存储在23位尾数部分内,这个1“存储”(实际上是不用储存的,它始终为1,只要在用的时候,记得有这个1即可)。阶码是以移码的形式存储,偏移量为127(7FH)。存储浮点数的阶码之前,偏移量要先加到阶码上。前面例子中,阶码为5,在单精度浮点数中,移码后的结果为127+5即132(84H)。另外,浮点数有两个例外。对于数值0.0,存储为全零;对于无限大数,阶码存储为全1,尾数部分全零,符号位指示正无穷或者负无穷。综上所述,按照单精度浮点数的格式,110100B存储形式如图4-5所示:图4-5 单精度浮点数110100B的存储形式从浮点数的格式来看,它充分利用了存储空间,可以根据数值运算的需要来调整小数点的位置,比定点数具有更大的动态调整范围。412 定点化原理浮点运算是指有浮点数参与的运算。对于浮点加法和减法,由于浮点数的小数点位置不固定,在进行加法和减法之前,要先判断两个操作数是否对齐,如果没有对齐,则要先对齐两个操作数,然后再进行相应的运算。最后还要对运算结果的尾数进行规范化,并修改相应的指数。而对浮点乘法和除法来讲,不需要先进行对齐,但做完乘法和除法后,也要对运算结果的尾数进行规范化以及修改相应的指数,才能得到正确的结果。这些也正是FPU所要做的工作,如果以软件仿真的方式来实现浮点运算,要进行的运算比较多。在对浮点运算要求较高的情况下,这种方式运算效率不够高,不能满足要求。因此,有必要把浮点运算定点化。这里所说的定点化是指用整数来替换浮点数,把整数存储空间的一部分用来表示浮点数的小数部分,另一部分用来表示浮点数的整数部分。假设用32位的int类型来表示浮点数,用高16位来表示浮点数的整数部分,用低16位来表示浮点数的小数部分,即“小数点”的位置在第15位和第16位之间。这个小数点是假定的,在定点化过程中,要考虑到这个小数点的存在,当全部定点化完毕之后,就只有整数运算了,这个假定的小数点自然就消除。用这种方式来表示1.0B,如图4-6所示,相当于整数65535。同时,这也可以理解为把1.0B放大了216倍。图4-6 16.16定点数1.0B的存储形式因为整数是定点的,因此把浮点数用整数替换后,就实现了“定点化”。这里定点化加上引号的意思在于:仅仅用上面的方法把浮点数用整数替换掉是不够的,对于一些运算(比如乘法和除法)还需要做相应的调整才能得到正确的运算结果,具体情况将在下面的文章中详细说明。为了方便,在本部分的例子中,定点数均采用32位int类型,如果用高n位表示整数部分,低(32n)位表示小数部分,则直接称这种定点数为n.(32n)的定点数。按照上面的定点化方法,把浮点数转换为定点数,相应的运算也要做必要的转换,才能做到真正的定点化,以下分别对各个运算进行说明。(1) 定点数加法对于定点数加法,可以直接进行标准的整数加法,不需要对计算结果进行调整。例如对于浮点数运算1.0 + 2.0 = 3.0,用16.16的定点数定点化后变成10000H + 20000H = 30000H。16.16的定点数30000H表示的正是浮点数3.0,不需要做调整。从数学公式(4-1)上也可以明显看出来: (4-1)公式(4-1)中的f相当于定点数中,用f位来表示浮点数的小数部分(下同)。在理解这些公式的时候,你可以把公式两边同时除以,这样公式左边的等式就变成了原来的浮点数运算,同时,根据公式右边的等式就可以方便地判断是否需要调整以及如何调整。当然,如果参与运算的两个定点数“小数点”的位置不一样,这时也要使两个数先对齐(这里的对齐与浮点数的对齐是不一样的,这里只需要做移位操作),然后再进行运算。假设一个16.16的定点数加上一个8.24的定点数,你可以把16.16的定点数左移8位变成8.24的定点数,也可以把8.24的定点数右移8位变成16.16的定点数,或者把两个都变成12.20的定点数,然后再进行加法运算。关键的是要保证最后相加的两个数,“小数点”的位置是对齐的,至于如何调整这两个数,你可以根据计算机结果的范围以及精度来考虑。(2) 定点数减法对于定点数减法,原理跟加法一样,可以直接进行标准的整数减法,不需要对结果做调整。(3) 定点数乘法先来看一个例子:1.0 * 2.0 = 2.0,用28.4的定点数定点化后变成10H * 20H = 200H,这时,定点数200H表示浮点数为32.0,不等于2.0。也就是说定点数乘法不能直接用标准的整数乘法代替。那该怎么办呢?再来看一下数学公式(4-2): (4-2)从公式(4-2)中,我们可以看出,如果直接使用整数的标准乘法,结果多乘上了,要把结果除以,才能得到正确的结果。因此,对于定点数乘法,使用标准的整数乘法进行运算后,要把结果右移f位,才能得到正确的结果。如果两个定点数的“小数点”位置不一样,这时可以根据结果需要的定点数形式来调整,公式如下: (4-3)公式(4-3)中表示的意思是:一个(32-m).m的定点数乘以一个(32-n).n的定点数,要得到一个(32-f).f的定点数结果,需要把结果除以。当公式(4-3)中的m=n=f时,就变成了公式(4-2)。可见,公式(4-2)是公式(4-3)的一个特例。(4) 定点数除法定点数除法,跟乘法的原理有点类似,所以说明原理的过程也类似。先看一个例子:2.0 / 1.0 = 2.0,用28.4的定点数定点化后变成20H / 10H = 2H,这时定点数2H表示的浮点数是0.125,不等于2.0。这表明,定点数除法不能直接用标准整数除法来代替。再来看看数学公式: (4-4)从公式中(4-4)可以看出,直接使用标准的整数除法,结果多除了,要把结果乘以,才能得到正确的结果。因此,对于定点数除法,使用标准的整数除法进行运算后,要把结果左移f位,才能得到正确的结果。如果两个定点数的“小数点”位置不一样,这时可以根据结果需要的定点数形式来调整,公式如下: (4-5)公式(4-5)中表示的意思是:一个(32-m).m的定点数除以一个(32-n).n的定点数,要得到一个(32-f).f的定点数结果,需要把结果乘以。当公式(4-5)中的m=n=f时,就变成了公式(4-4)。可见,公式(4-4)是公式(4-5)的一个特例。细心的人可能已经发现,先进行整数相除,然后再移位,这表明在移位前,运算过程已经丢弃了很多数据,大大降低了运算结果的精度。因此,我们可以把公式(4-5)两边分别乘以,得到公式(4-6): (4-6)公式(4-6)是把先对被除数进行移位,然后在进行整数除法运算,做了这个改变后,不但结果是正确的,而且提高了运算结果的精度。只有把浮点数用定点数替换后,并把相应的运算转换为定点运算,才能真正做到定点化。413 关键运算的实现一般情况下,把浮点数定点化后,要保证浮点数的精度,定点数中就需要有足够的位来表示小数部分。因此,定点数都是数值比较大的整数。数值大,在运算过程中也就容易产生溢出,对溢出的情况要做特别的处理。另外,定点数中的用来表示精度的位数越多,则定点数所能表示的浮点数范围就越小。在保证精度的前提下,如果定点数表示的数值范围不够大,则可以采用更长的整数来表示定点数。通常情况下,可以使用32位或者64位整数来表示定点数。在定点化WMA解码过程中,很多都要用到64位整数来表示定点数,因此,在这一小节里,先介绍一些关键运算的实现。(1) 64位定点数乘法运算64位定点数乘法,就是两个64位整数的乘法。在GCC编译器中,用 signed long long 类型表示有符号64位整数;用unsigned long long 类型表示无符号64位整数。对于两个64位定点数x和y,如果直接用来计算乘积,GCC编译器也会进行适当处理,并计算出结果。遗憾的是,这样直接处理,我们很难判断在什么情况下会溢出,无法对溢出做出适当的处理。因此,我们采用下面的算法来实现64位定点数的乘法。对于定点数x和y,为了方便处理,先把负数转换为正数,如果x和y同号,结果不变,如果x和y异号,结果要加上负号。一个无符号的64位定点数X可以表示为: (4-7)在公式(4-7)中,High和Low都是无符号64位整数类型。High表示X的高31位,第32到62位;Low表示X的低31位,第1到31位(为了方便,舍弃第0位,这对最后结果影响不大)。其原理就是把64数看成高低两

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论