智能路由器操作系统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
一.什么是智能路由器 接入网络的家庭用户终端越来越多,路由器控制越来越复杂,因此需要一个智能网关来管理家庭的设备,智能路由器就是这个网关. 另外,这个智能网关直接连在互联网上,需要隔离家庭网和互联网的 ...
最新文章
- windows time 服务无法启动 错误1058 解决方法
- python行业中性_市场风险中性假设的r0只是等效r的其中之一
- 二柱子2.0编程总结
- homework1: 印象深刻的错误
- SAP Spartacus Storefront页面的page layout config
- UVA719 Glass Beads 最小表示 / 后缀自动机
- Java SecurityManager getSecurityContext()方法与示例
- 3个提升Python运行速度的方法,很实用
- 4大华为云“安全镖局”秘密法宝揭秘
- C++数据结构02--链式线性表(单链表的实现)
- 了解OutOfMemoryError异常 - 深入Java虚拟机读后总结
- docker打包部署nginx,django应用
- RenderSettings 渲染设置
- RedHat 安装 CentOS yum
- mongodb driver c#语法
- collect2: error: ld returned 1 exit status
- android设备当广告屏使用方法,Android手机与电视无线HDMI同屏器使用教程
- lync 2013标准版安装
- 如何成为一名机器学习算法工程师?
- 开启京东自动化领京豆
热门文章
- Python-Django毕业设计房屋中介管理信息系统(程序+Lw)
- 个人博客html模板 百度云盘,个人博客模板源码神马百度轻量级原创博客网站模板...
- MATLAB代码:基于主从博弈理论的共享储能与综合能源微网优化运行研究
- 安装docker 并构建私有库
- 程序化广告定量评估收益指标——eCPM
- wgc84 笛卡尔_大地坐标系(WGS84)转空间直角坐标系(笛卡尔坐标系XYZ)
- 漫画赏析:Linux 内核到底长啥样
- 腾讯元老、上市公司CTO赚够钱后辞职到安徽农村隐居,亲手建造200亩农场
- 给准备自考本科想学汉语言专业的一些建议
- 教会大家—如何快速批量重命名文件