ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:27.28KB ,
资源ID:6916676      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-6916676.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(madplay 源码工作原理分析.docx)为本站会员(b****4)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

madplay 源码工作原理分析.docx

1、madplay 源码工作原理分析madplay 源码工作原理分析madplay 源码工作原理分析: 本人因项目工作需要,要在基于6410的开发板上移植madplay的代码,其中要修改相关代码以适应 项目需求,于是有了对madplay源码的分析,整理后发出以方便后来人移植改写madplay用 1. 目标:弄清madplay的主要流程机理,结合工作目标重点摸清有关Play,Pause,Resume,Next mp3,Prev mp3,Stop, shuffle, loop,Vol adjustment 的工作机理,为改写代码作准备 2.总体机理: 版本:madplay-0.15.2b,libmad

2、-0.15.1b,libid3tag-0.15.1b 入口点:madplay.c: main() 下面主要集中在所关心的骨架流程方面,各个小细节除非与工作目标相关,否则一律略去 * main() 流程分析 * - player用于全局记录有关变量 - step 1: main():player_init(&player)初始化player参数 - step 2: main():get_options(argc, argv, &player)对argv各类参数进行解析,记录在player-options,或player-output或 其它相关变量中: 看几个与工作目标有关的: 1)输出声音通道

3、及Mono还是Stereo选择: -1,-2,-m,-S:用于设置player-output.select为:PLAYER_CHANNEL_LEFT or PLAYER_CHANNEL_RIGHT or PLAYER_CHANNEL_MONO or PLAYER_CHANNEL_STEREO 2)loop -r:player-repeat保存重复播放的次数,如无重复播放,则设为-1 3)volume方面 player-output.attamp_db 减弱的分贝 player-output.voladj_db 设定的分贝 - step 3: main():player_run()执行播放,这里

4、实现对mp3(单个或多个)进行播放,是主要函数 - step 4: main():player_finish() 小结: madplay()主体流程简单: player_init()+get_options()=player_run()=player_finish() 也即初始化全局结构,及cmd命令选项解析=mp3播放=结束扫尾工作 * main() 分析Over * * player_run() 流程分析 - 核心 * 1.player_run()入口参数分析: player_run(&player, argc - optind, (char const *) &argvoptind) a

5、rgc:为多少首播放歌,argv为mp3路径 见下面的调试记录 - /test$ ls madplay shell test2.mp3 test3.wav test5.mp3 test7.mp3 test9.mp3 madplay_test test1.mp3 test3.mp3 test4.mp3 test6.mp3 test8.mp3 /test$ gdb -args ./madplay test1.mp3 test2.mp3 test3.mp3 GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. Lic

6、ense GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type show copying and show warranty for details. This GDB was configured as i486-linux-gnu. (gdb) b player_run Breakpoint 1 at 0x804f845: f

7、ile player.c, line 2700. (gdb) r Starting program: /home/yuxu/test/madplay test1.mp3 test2.mp3 test3.mp3 Thread debugging using libthread_db enabled MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al. New Thread 0xb7c446b0 (LWP 6724) Switching to Thread 0xb7c446b0 (LWP 67

8、24) Breakpoint 1, player_run (player=0xbf95631c, argc=3, argv=0xbf9565d8) at player.c:2700 warning: Source file is more recent than executable. 2700 (gdb) p argv0 $1 = 0xbf95760e test1.mp3 (gdb) p argv1 $2 = 0xbf957618 test2.mp3 (gdb) p argv2 $3 = 0xbf957622 test3.mp3 (gdb) - 2.player_run():player-p

9、laylist.entries,player-playlist.length的意义: 有了上面的分析,这两个-playlist.entries,-playlist.length就清楚了,不多说 player-playlist.entries = argv; player-playlist.length = argc; 3.player_run()=setup_tty()=tty_fd = open(TTY_DEVICE, O_RDONLY); TTY_DEVICE:/dev/tty 这里打开终端,用于后面在播放过程中,对键盘进行读取工作,以判定用户发出什么指令如:Stop,Pause,Resu

10、me,Vol Adjustment ,Next Mp3,Prev Mp3 再就是一些其它操作:如设置相应的TYTY属性及信号处理函数,略去不表 - 具体调试分析见下: /test$ gdb -args ./madplay test1.mp3 test2.mp3 test3.mp3 GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change a

11、nd redistribute it. There is NO WARRANTY, to the extent permitted by law. Type show copying and show warranty for details. This GDB was configured as i486-linux-gnu. (gdb) b player_run Breakpoint 1 at 0x804f845: file player.c, line 2700. (gdb) r Starting program: /home/yuxu/test/madplay test1.mp3 te

12、st2.mp3 test3.mp3 Thread debugging using libthread_db enabled MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al. New Thread 0xb7bf66b0 (LWP 6832) Switching to Thread 0xb7bf66b0 (LWP 6832) Breakpoint 1, player_run (player=0xbfe087dc, argc=3, argv=0xbfe08a98) at player.c:2

13、700 warning: Source file is more recent than executable. 2700 (gdb) s 2704 player-playlist.entries = argv; (gdb) 2705 player-playlist.length = argc; (gdb) s 2710 if (player-options & PLAYER_OPTION_TTYCONTROL) & (gdb) p /x player-options $1 = 0x40 (gdb) p /x PLAYER_OPTION_TTYCONTROL $2 = 0x40 (gdb) s

14、 54 return _open_alias (_path, _oflag, _va_arg_pack (); (gdb) 2538 tty_fd = open(TTY_DEVICE, O_RDONLY); (gdb) bt #0 player_run (player=0xbfe087dc, argc=3, argv=0xbfe08a98) at player.c:2538 #1 0x0804b9fd in main (argc=3, argv=0xbfe08a94) at madplay.c:816 (gdb) s 2539 if (tty_fd = -1) (gdb) bt #0 play

15、er_run (player=0xbfe087dc, argc=3, argv=0xbfe08a98) at player.c:2539 #1 0x0804b9fd in main (argc=3, argv=0xbfe08a94) at madplay.c:816 (gdb) s 2546 if (tcgetattr(tty_fd, &save_tty) = -1) (gdb) - 强调一点:这里主要意义就在于后面的播放过程中,要读取用户的键盘输入,就是用read(tty_fd, &key, 1)来处理的 4.player_run():setup_filters()=addfilter(pl

16、ayer, tty_filter, player) 将会执行代码段: # if defined(USE_TTY) if (player-options & PLAYER_OPTION_TTYCONTROL) & addfilter(player, tty_filter, player) = -1) return -1; # endif 而在addfilter()中=filter_new()中malloc()一个新filter=filter_init()初始化:filter-func = tty_filter() player-output.filters将指向这个新分配的filter,而且这个

17、新分配的filter-func为tty_filter(): 特别说明: tty_filter()=readkey()=swtich.case处理各类键盘输入的命令: void filter_init(struct filter *filter,filter_func_t *func, void *data, struct filter *chain) filter-func = func; . int addfilter(struct player *player, filter_func_t *func, void *data) struct filter *filter; filter =

18、 filter_new(func, data, player-output.filters); . player-output.filters = filter; return 0; = 有关tty_filter函数调用链的说明: 1):流程: tty_filter()=command=readkey(blocking:阻塞否)=switch(command).case处理各种命令:如:KEY_STOP,KEY_PAUSE KEY_FORWARD,KEY_BACK,KEY_QUIT,KEY_GAINDECR,KEY_GAININCR,KEY_GAINZERO, 如下为清理过的流程示意图: 提醒

19、一点:KEY_PAUSE:readkey(1)即,当Pause时,读键操作是阻塞的,即进入readkey()执行以下代码: do count = read(tty_fd, &key, 1); while (count = -1 & errno = EINTR); 当无键按下时,read()阻塞睡眠,用top查看果然没有占用cpu了 而总的流程是这样的: 先tty_filter()查看有无key按下,此时是readkey(0)不阻塞形式,无键按下即返回之,有键按下则执行命令,见下面的 代码框架,再去每次取40, 000Bmp3数据进行mp3解码,然后送往alsa驱动去pcm播放,再又回到tty_

20、filter查看有无键按下 就是这样的一个播放循环,后面还会讲到 2)代码框架: enum mad_flow tty_filter(void *data, struct mad_frame *frame) command = readkey(0); if (command = -1) return MAD_FLOW_BREAK; again: switch (command) case KEY_STOP: . case KEY_PAUSE: stop_audio(player, stopped); command = readkey(1); . break; case KEY_FORWARD:

21、 case KEY_CTRL(n): case : player-control = PLAYER_CONTROL_NEXT; goto stop; case KEY_QUIT: case KEY_CTRL(c): case Q: player-control = PLAYER_CONTROL_STOP; goto stop; case KEY_GAINDECR: case KEY_GAININCR: case KEY_GAINZERO: case KEY_GAININFO: switch (command) case KEY_GAINDECR: db = set_gain(player, G

22、AIN_ATTAMP | GAIN_RELATIVE, -0.5); break; case KEY_GAININCR: db = set_gain(player, GAIN_ATTAMP | GAIN_RELATIVE, +0.5); break; case KEY_GAINZERO: db = set_gain(player, GAIN_ATTAMP, 0); break; default: db = set_gain(player, 0, 0); break; . stop: stop_audio(player, 1); = 5.音量Gain设定: set_gain(player, 0,

23、 0);= db = player-output.voladj_db + player-output.attamp_db; player-output.gain = db ? mad_f_tofixed(pow(10, db / 20) : MAD_F_ONE; player-output.gain保存了最终的音量db设定值 那么音量Gain是如何执行的呢? 1.gain_filter的初始化设定: player_run()=setup_filters()= addfilter(player, gain_filter, &player-output.gain); =player-output.

24、filters指向的filter list中挂上了gain_filter,同时,还有前面所说的tty_filter gain_filter用于调节音量,而tty_filter用于读取键盘输入确定用户的命令输入 补充参数初始值来源: main()=get_options()=依据选项-a 或 -A对参数进行player-output.attamp_db,player-output.voladj_db设定初 始值 case a: player-output.attamp_db = get_decibels(optarg); preamp = 1; break; case A: player-out

25、put.voladj_db = get_decibels(optarg); 2.音量调节的方法: play_all()=play_one()=decode()=mad_decoder_run()=run_sync()=decoder-filter_func()= decoder-filter_func(decoder-cb_data, stream, frame)=gain_filter() = # define mad_f_mul(x, y) (x) * (y) frame-sbsamplechssb = mad_f_mul(frame-sbsamplechssb, gain); = mad

26、_synth_frame()=synth_full()=dct32() 也就是:调用gain_filter进行对mp3声音原始数据进行gain处理,也就是直接将gain融入mp3数据中,然后再离散余弦变换 解码mp3文件的编码,这样声音音量级别就提高了,也就是音量调节是纯软件的,直接对数据进行的处理变换 = 6.播放mp3的工作机理: 1)主架构流程: player_run()=setup_tty()=open TTY_DEVICE =setup_filters()=gain_filter,tty_filter加入filter list =audio_control_init(&control

27、, AUDIO_COMMAND_INIT)+player-mand(&control)=audio_alsa()= init()=snd_pcm_open() =play_all() = 核心函数 =audio_control_init(&control, AUDIO_COMMAND_FINISH)+player-mand(&control)=stop()= snd_pcm_drop(),snd_pcm_prepare() play_all()核心函数: =处理随机播放:见下代码,不多说,easy if (player-options & PLAYER_OPTION_SHUFFLE) srand(time(0); for (i = 0; i entriesi; playlist-entriesi = playlist-entriesj; playlist-entriesj = tmp; =重要参数说明: count = playlist-length;播放mp3文件数量 playlist-current:当前所播放的mp3的位置 playlist-entriesplaylist-current:当前播放的mp3文件 =开始播放一首mp3:若播放失败,则该

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2