智能路由器操作系统openwrt 之三 音频开发
音频开发
- Linux 音频架构
- 音频架构图
- Application层
- 启动脚本顺序定义
- 启动脚本书写
- HAL层
- kernel
- machine
- plarform
- codec
- openWRT 音频应用
- 调试技术
- 链路上应用层UDP截取文件
- 链路上 alsa 截取文件
- 链路上kernel 截取文件
- 关注我们
Linux 音频架构
音视频的好坏 直接影响 产品体验
音频架构图
openWRT 采用 ALSA 层次图,如下
- Application: 上层应用 主要调用alsa-lib 中的接口 实现业务逻辑。使用alsa-util中aplay,arecord,amixer,speaker-test进行相关测试。
- HAL层 : 移植alsa-lib 和 alsa-utils. 在openwrt中 feeds 自带了alsa-lib 1.1.01
- kernel: 按照ALSA 驱动层进行适配。2
Application层
openwrt中应用启动需要自定义启动脚本,放在目录/etc/init.d 目录下。
启动脚本顺序定义
05 defconfig //加载默认参数
10 boot //启动
39 usb // 加载usbfs
40 network // 设置网卡参数
45 firewall // 防火墙
50 dropbear // sshd server
50 cron // …
50 telnet // 如果没有修改root密码,则启动telnet server
60 dnsmasq // DHCP 和 DNS 服务端
95 done // …
96 led // 指示灯
97 watchdog // …
99 sysctl // 最后,进行必要的内核参数调整
启动脚本书写
按照官方Wiki脚本3,进行自定制。
HAL层
这一层不需要做太多改动,需要配置feeds选择自己需要的版本即可,
具体的接口查询,可以到alsa-project4 查询。
kernel
根据ALSA驱动进行相关分析。
machine
/* SoC machine */
struct snd_soc_card {char *name;...int (*probe)(struct platform_device *pdev);int (*remove)(struct platform_device *pdev);/* the pre and post PM functions are used to do any PM work before and* after the codec and DAIs do any PM work. */int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);int (*suspend_post)(struct platform_device *pdev, pm_message_t state);int (*resume_pre)(struct platform_device *pdev);int (*resume_post)(struct platform_device *pdev);.../* CPU <--> Codec DAI links */struct snd_soc_dai_link *dai_link;int num_links;...
};
probe/remove 可选,主要侦测machine。
suspend/resume 在codec,DAIs和DMA suspend resume 会相应的触发,也是可选的
machine DAI口配置,配置对应的结构体
/* digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link corgi_dai = {.name = "WM8731",.stream_name = "WM8731",.cpu_dai_name = "pxa-is2-dai",.codec_dai_name = "wm8731-hifi",.platform_name = "pxa-pcm-audio",.codec_name = "wm8713-codec.0-001a",.init = corgi_wm8731_init,.ops = &corgi_ops,
};/* audio machine driver */
static struct snd_soc_card snd_soc_corgi = {.name = "Corgi",.dai_link = &corgi_dai,.num_links = 1,
};
plarform
DMA 驱动,Soc DAI 驱动5
/* SoC audio ops */ struct snd_soc_ops { int (*startup)(struct snd_pcm_substream *);void (*shutdown)(struct snd_pcm_substream *);int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *); int (*hw_free)(struct snd_pcm_substream *);int (*prepare)(struct snd_pcm_substream *);int (*trigger)(struct snd_pcm_substream *, int); };
//平台驱动通过DMA接口关联起来
struct snd_soc_platform_driver { char *name;int (*probe)(struct platform_device *pdev);int (*remove)(struct platform_device *pdev);int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai); int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);/* pcm creation and destruction */int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *); void (*pcm_free)(struct snd_pcm *);/** For platform caused delay reporting.* Optional.*/ snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, struct snd_soc_dai *);/* platform stream ops */struct snd_pcm_ops *pcm_ops;};
codec
每个codec codec 驱动必须具备以下功能5:
- codec DAI 与 PCM 配置
- 使用I2C 或者SPI控制IO
- mixer audio 控制
- codec 音频操作
- DAPM 描述
- DAPM 事件处理
可选 - DAC mute处理
// DAI PCM配置
static struct snd_soc_dai_ops wm8731_dai_ops = {.prepare = wm8731_pcm_prepare,.hw_params = wm8731_hw_params,.shutdown = wm8731_shutdown,.digital_mute = wm8731_mute,.set_sysclk = wm8731_set_dai_sysclk,.set_fmt = wm8731_set_dai_fmt, };
struct snd_soc_dai_driver wm8731_dai = { .name = "wm8731-hifi",.playback = { .stream_name = "Playback",.channels_min = 1,.channels_max = 2,.rates = WM8731_RATES,.formats = WM8731_FORMATS,},.capture = { .stream_name = "Capture",.channels_min = 1,.channels_max = 2,.rates = WM8731_RATES,.formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops,.symmetric_rates = 1, };
// i2c 控制 读写
i2c_write
i2c_read
// mixer audio control
codec 说有mixer与control都定义在soc.h中
#define SOC_SINGLE(xname, reg, shift, mask, invert)
定义单一控制器:-xname 控制名称e.g. "Playback Volume"reg = codec registershift = control bit(s) offset in registermask = control bit size(s) e.g. mask of 7 = 3 bitsinvert = the control is inverted 是否反转其他宏包括: -#define SOC_DOUBLE (xname ,reg ,shift_left ,shift_right ,mask ,invert )
立体声控制#define SOC_DOUBLE_R (xname ,reg_left ,reg_right ,shift ,mask ,invert )
一个跨越2个寄存器的立体声控制#define SOC_ENUM_SINGLE (xreg ,xshift ,xmask ,xtexts )xreg = 寄存器XSHIFT = 控制位(小号)偏移在寄存器 xmask = 控制位(小号)大小xtexts = 指向描述每个设置的字符串数组的指针
//audio 控制操作
/* SoC audio ops */
struct snd_soc_ops { int (*startup)(struct snd_pcm_substream *);void (*shutdown)(struct snd_pcm_substream *);int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *); int (*hw_free (struct snd_pcm_substream *);int (*prepare)(struct snd_pcm_substream *); };
//DAPM
//DAPM handler 参考5
openWRT 音频应用
上面一节介绍了音频框架。在openWRT音频业务主要VOIP通过 ,上/下行通过模块如下:
调试技术
链路上应用层UDP截取文件
知道UDP 下的G711A 对应的buffer
// 应用层将buffer写到文件 代码块static struct file *file_g711a= NULL;int writelen = 0;if (NULL == fp){file_g711a= file_open("/test1", O_RDWR | O_CREAT, 0777);if(file_g711a == NULL){printf("g711a file = NULL");}else{printf("g711a file open ok");} }if(file_g711a != NULL){writelen = fwrite(g711a_buffer, 1, sizeof(g711a_buffer), file_g711a);}printk("writelen:%d\n",writelen);
链路上 alsa 截取文件
转换成PCM后,将对应的buffer 写道文件
// 应用层将buffer写到文件 代码块static struct file *file_pcm= NULL;int writelen = 0;if (NULL == fp){file_pcm= file_open("/test.pcm", O_RDWR | O_CREAT, 0777);if(file_pcm == NULL){printf("pcm file = NULL");}else{printf("pcm file open ok");} }if(file_pcm != NULL){writelen = fwrite(pcm_buffer, 1, sizeof(pcm_buffer), file_pcm);}printk("writelen:%d\n",writelen);
链路上kernel 截取文件
在PCM与DMA通信的函数中 将buffer 写到文件中,
// kernel 将buffer写到文件 代码块static struct file *fp = NULL;mm_segment_t fs;static loff_t pos = 0;printk("hello enter\n");if (NULL == fp){fp = filp_open("/test.pcm", O_RDWR | O_CREAT, 0777);if (IS_ERR(fp)){printk("create file error\n");return -1;}}fs = get_fs();set_fs(KERNEL_DS);int writelen = vfs_write(fp, buf, size*4, &pos);pos += size*4;printk("writelen:%d pos:%d\n",writelen, pos);
关注我们
feeds ↩︎
alsadriver ↩︎
initscript ↩︎
alsa-api ↩︎
alsa-drvier ↩︎ ↩︎ ↩︎
智能路由器操作系统openwrt 之三 音频开发相关推荐
- 智能路由器操作系统OpenWrt
小米路由器的"MiWiFi"又让路由器成了关键词,每台智能路由器的系统是该款产品的亮点之一,其系统肯定有不少"好玩"的地方.为自己的智能路由器量身打造系统,并且 ...
- 【智能路由器】openwrt创建用户软件包
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 openwrt根目录 先看看openwrt初次编译好后的目 ...
- 【智能路由器】openwrt实现内网穿透(p2p、n2n)
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 背景 有时候在对线上设备进行维护,由其是调试的时候希望技术 ...
- 【智能路由器】openwrt计划任务
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 openwrt的计划任务可以让你的程序或脚本在特定的时间启 ...
- 【智能路由器】openwrt工具uci使用指南
[智能路由器]系列文章连接 http://blog.csdn.net/u012819339/article/category/5803489 uci(Unified Configuration Int ...
- 《智能路由器开发指南》——第1章 智能路由器概述 1.1 OpenWrt简介
本节书摘来自异步社区<智能路由器开发指南>一书中的第1章,第1.1节,作者 张永智,李章明,更多章节内容可以访问云栖社区"异步社区"公众号查看. 第1章 智能路由器概述 ...
- 《智能路由器开发指南》核心笔记(全)——转载的
另外: 看 http://openwrt.bjbook.net/ 转载于:http://blog.csdn.net/sinat_36184075/article/details/722319 ...
- 《智能路由器开发指南》核心笔记(全)
转载于:https://blog.csdn.net/sinat_36184075/article/details/72231970 [概述]2017.05.15 openWrt是实现智能路由器功能的最 ...
- 一文万字带你入门智能路由器OpenWrt系统,并在虚拟中安装配置OpenWrt
一.什么是智能路由器 接入网络的家庭用户终端越来越多,路由器控制越来越复杂,因此需要一个智能网关来管理家庭的设备,智能路由器就是这个网关. 另外,这个智能网关直接连在互联网上,需要隔离家庭网和互联网的 ...
最新文章
- 12v60ah锂电池组装图_锂电池基本参数,结合电动自行车电池应用分析
- 5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)
- 去掉烦人的“正在配置Windows”
- android hardware architecture
- java struts2上传文件_java Struts2框架下实现文件上传功能
- matlab光盘映像文件可以删除吗_DVD-Cloner 2020 for mac(DVD光盘刻录工具) 7.00.715
- 最新阿里聚划算Java 5轮面试题,涵盖GC收集器、多线程锁等
- django 1.8 官方文档翻译: 3-1-3 Django 的快捷函数
- Flink的窗口聚合操作(Time\Count Window)
- javascript的内置对象
- 项目分析:大学生个人财务管理系统的设计与实现
- python实现将文件下内每张图片按顺序命名为txt文本文件中的内容
- 腾讯“云+未来”峰会亮相山城,助力重庆成为数字中国新标杆
- 在PHP中2中特殊数据类型是,@PHP中的数据类型(2)
- python数据1-4
- C语言编程初体验 作文,我的理想是当编程师作文
- VC++实现镜像劫持(360保险箱启动原理)
- css手指代码,CSS3动画:通过Animation实现简单的手指点击动画
- 微信小程序开发者工具打不开的问题
- 如何设计淘宝天猫这种成功而有价值大数据可视化?
热门文章
- 03 Vue进阶extend使用方法详讲
- 计算机测试杀毒软件的代码,检测你电脑的杀毒软件时候到了 一段代码测试杀毒软件...
- 疾病研究:8岁男童成为美国首位接受基因治疗的杜氏进行性肌营养不良患者
- C++如何测试dll_Win7系统丢失libcurl.dll怎么办
- h5 + vant + ts展示pdf
- 水族箱泵市场深度研究分析报告
- java游戏开发入门(八) -图像
- SEO基础:什么是结构化数据?- WP站长
- android编译boost,使用android ndk编译boost动态库
- PySide2、nltk、wordcloud、gensim、sklearn、pyinstaller实现词嵌入可视化、绘制词云图、制作GUI并打包的踩坑总结