ALSA声卡16_编写ALSA声卡应用程序_学习笔记
1、体验
(1)ALSA声卡使用体验:使用arecord录音,使用aplay播放,在Alsa-utils里面)
准备:
cd linux-3.4.2
patch -p1 < ../linux-3.4.2_alsa_wm8976_uda1341_jz2440_mini2440_tq2440.patch //打补丁
cp config_wm8976_jz2440 .config 或 cp config_uda1341_tq2440_mini2440 .config //设置配置文件
make uImage //编译内核
(2)使用新内核启动并测试
启动后创建设备节点
直接输入arecord命令查看帮助信息(arecord 选项 文件)
执行命令后,出现错误(没有匹配的通道)
搜索内核目录查看错误原因(在soc_pcm.c文件的222行)
通道最小大于通道最大值,也就是codec这一边的dai不匹配CPU这边的dai接口,他们的声道不匹配,在codec部分,对应wm8976的capture通道支持的声道数是1(最大和最小都是 ,因而应该修改为2);
而在platform(cpu部分)的IIS,capture通道支持的声道数是2,因而不匹配。
(3)修改程序后编译新内核并重新启动调试
jz2440:
i. 声音差
arecord test.wav //录音,把录到的声音放到文件test.wav里去
aplay test.wav //播放test.wav文件
对着麦克风说话,然后播放声音
(4)声音有很多噪声,解决办法是添加一些参数(改变采样率,声道数,格式)
-f cd表示每一个采样点是16位,采样率是44100(更高的采样频率),双声道
ii. 声音好
arecord -f cd test.wav
aplay test.wav
(5)对于mini2440,重新配置内核,然后编译拷贝到网络文件系统,并使用新内核启动
按上面的录音和播放声音操作,没有播放出任何声音,看原理图,录音麦克风通道是第2个通道(VINL),没有被打开
查看控制项
获取控制项Input Mux的状态,当前值是0,表示没有使用。
把第二个通道打开(用于录音)
然后录音播放
2. 编写一个应用程序
(1)分析
一边录音一边播放(仿造arecord ,aplay(都在aplay.c里面(在Alsa-utils里面),aplay.c用到alsa-lib库))
aplay.c使用alsa-lib这个库编写程序的
A Tutorial on Using the ALSA Audio API:
alsa-lib使用方法
open_the_device();//打开设备
set_the_parameters_of_the_device(); //设置参数
while (!done) {
/* one or both of these */
receive_audio_data_from_the_device(); //如果是录音就接收data
deliver_audio_data_to_the_device(); //如果播放把数据发送到设备上去
}
close the device //关闭设备
(2)main函数
int main (int argc, char *argv[])
{
int err;
char buf[512];
snd_pcm_t *playback_handle;
snd_pcm_t *capture_handle;
playback_handle = open_playback();// 打开播放设备
if (!playback_handle)
{
fprintf (stderr, "cannot open for playback\n");
return -1;
}
capture_handle = open_capture();//打开录音设备
if (!capture_handle)
{
fprintf (stderr, "cannot open for capture\n");
return -1;
}
if ((err = snd_pcm_prepare (playback_handle)) < 0) { //准备播放操作
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
snd_strerror (err));
return -1;
}
if ((err = snd_pcm_prepare (capture_handle)) < 0) { //准备录音操作
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
snd_strerror (err));
return -1;
}
while (1) {
if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) { //读操作(把数据读到buffer)
fprintf (stderr, "read from audio interface failed (%s)\n",
snd_strerror (err));
return -1;
}
if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) { //写操作(把数据写到buffer)
fprintf (stderr, "write to audio interface failed (%s)\n",
snd_strerror (err));
return -1;
}
}
snd_pcm_close (playback_handle);//关闭播放设备
snd_pcm_close (capture_handle);//关闭录音设备
return 0;
}
(3)打开设备
snd_pcm_t *open_sound_dev(snd_pcm_stream_t type)
{
int err;
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
unsigned int rate = 44100;
if ((err = snd_pcm_open (&handle, "default", type, 0)) < 0) { //打开设备,第2个参数是指使用默认的 设备名称
return NULL;
}
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { //分配参数
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { //初始化参数
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { //设置参数,数据存放方式是交叉存放SND_PCM_ACCESS_RW_INTERLEAVED(先放左声道再放右声道)
fprintf (stderr, "cannot set access type (%s)\n",
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
fprintf (stderr, "cannot set sample format (%s)\n", //设置格式SND_PCM_FORMAT_S16_LE是16位的
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &rate, 0)) < 0) { //设置采样率
fprintf (stderr, "cannot set sample rate (%s)\n",
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, 2)) < 0) { //设置通道数
fprintf (stderr, "cannot set channel count (%s)\n",
snd_strerror (err));
return NULL;
}
if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { //把构造的结构体的数据写到硬件上去
fprintf (stderr, "cannot set parameters (%s)\n",
snd_strerror (err));
return NULL;
}
snd_pcm_hw_params_free (hw_params); //释放含参数的结构体
return handle; //成功时返回句柄
}
(4)关闭声卡设备和打开播放/录音设备
void close_sound_dev(snd_pcm_t *handle) //关闭声音设备
{
snd_pcm_close (handle);
}
snd_pcm_t *open_playback(void) //打开播放设备
{
return open_sound_dev(SND_PCM_STREAM_PLAYBACK);
}
snd_pcm_t *open_capture(void) //打开录音设备
{
return open_sound_dev(SND_PCM_STREAM_CAPTURE);
}
3、Makefile
这里-lasound表示使用asound库
4、实验
编译好,拷贝到网络文件系统上
在板子上执行出现段错误
ALSA声卡16_编写ALSA声卡应用程序_学习笔记的更多相关文章
- ALSA声卡12_从零编写之添加音量控制_学习笔记
1.设置音量时应用程序的调用过程 (1)strace分析: amixer cset numid=1 30 (设置音量) /dev/snd/controlC0 open SNDRV_CTL_IOCTL_ ...
- ALSA声卡08_从零编写之框架_学习笔记
1.整体框架 (1)图示((DAI(全称Digital Audio Interface)接口)) 在嵌入式系统里面,声卡驱动是ASOC,是在ALSA驱动上封装的一层,包括以下三大块 (2)程序框架 m ...
- ALSA声卡10_从零编写之数据传输_学习笔记
1.引言 (1)应用程序使用声卡的时候,数据流程是:应用程序把数据发送给驱动,驱动把数据发送给硬件声卡,声卡把数据转换成声音数据播放出去. (2)可以使用两种方式发送数据 第一种:app发数据,等驱动 ...
- ALSA声卡09_从零编写之参数设置_学习笔记
1.参数设置分析 (1)open: soc_pcm_open 依次调用cpu_dai, dma, codec_dai, machine的open或startup函数 只在dma的open函数里添加参数 ...
- ALSA声卡07_分析调用过程_学习笔记
1.编译新的strace工具分析aplay和amixer应用程序对声卡的调用过程 (1)因为旧的strace工具不能识别不能识别alsa声卡驱动程序里面的ioctrl. (2)编译过程参考http:/ ...
- ASP.NET本质论第二章应用程序对象学习笔记1
1.请求的处理参数—上下文对象HttpContext 1) 针对每一次请求,ASP.NET将创建一个处理这次请求所使用的HttpContext对象实例,这个对象实例将用来在ASP.NET服务器的处理过 ...
- 微信小程序视频学习笔记
[清华大学]学做小程序 https://www.bilibili.com/video/av21987398 2.2创建项目和文件结构 小程序包含一个描述整体程序的app和多个描述各自页面的page 配 ...
- 《Lua程序设计》9.1 协同程序基础 学习笔记
协同程序(coroutine)与线程(thread)差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区 ...
- 第1-5章 慕课网微信小程序开发学习笔记
第1章 前言:不同的时代,不同的Web --微信小程序商城构建全栈应用 http://note.youdao.com/noteshare?id=a0e9b058853dbccf886c1a890594 ...
随机推荐
- Linux:centOS LAMP搭建之软件包下载地址
MySQL5.1 wget mysql-5.1.73-linux-i686-glibc23.tar.gz #二进制包 MySQL5.6 wget http://mirrors.sohu.com/mys ...
- SDKMAN 软件开发工具包管理器
SDKMAN 是用来在类Unix 系统中管理多个版本的开发环境的工具.提供命令行接口来安装.切换.删除.列出候选版本. SDKMAN!是在大多数基于Unix的系统上管理多个软件开发套件的并行版本的工具 ...
- 每周荐书:机器学习、Java虚拟机、微信开发(评论送书)
每周荐书:机器学习.Java虚拟机.微信开发(评论送书) 感谢大家对每周荐书栏目的支持,先公布下上周中奖名单 年精心雕琢,难得的"理论 + 实战案例 + 趟坑经验"总结 从需求分析 ...
- windows 按时自动化任务
参考文章: 1. 巧用Windows 7计划任务设置定时提醒 http://jingyan.baidu.com/article/acf728fd279fe5f8e510a333.html 2. cmd ...
- NSLayoutConstraint 布局,配合简单的动画效果
demo地址 :链接: http://pan.baidu.com/s/1c00ipDQ 密码: mi4c 1 @interface ViewController () @property (nonat ...
- 求整数A和B的二进制表示中有多少位是不同?
如果有题目要求整数A和B二进制表示中多少位是不同的? 那我们要先考虑一个unsigned类型中变量1的个数?我们可以考虑简单的移位运算,向右移位,我们进行判断如果不是1直接丢掉,使用&运算符即 ...
- HDU1800 hash+去前导0
注意一:卡map的时间,但是好好写+运气还是可以卡过,哇...求人品爆发 注意二:去前导0,毕竟‘0’也有ASCII码 #include<cstdio> #include<cstdl ...
- Java并发--同步容器
为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch).今天我们就来讨论下同步容器. ...
- 当我们使用 MVVM 模式时,我们究竟在每一层里做些什么?
这篇文章不会说 MVVM 是什么,因为讲这个的文章太多了:也不会说 MVVM 的好处,因为这样的文章也是一搜一大把.我只是想说说我们究竟应该如何理解 M-V-VM,当我们真正开始写代码时,应该在里面的 ...
- ResultSet.TYPE_SCROLL_SENSITIVE到底发生了什么?
转自:https://blog.csdn.net/axman/article/details/3984103 这个问题我在几年前说过,但今天再次从CSDN上看到有人问这个问题,可以看出,真正懂这个问题 ...