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声卡应用程序_学习笔记的更多相关文章

  1. ALSA声卡12_从零编写之添加音量控制_学习笔记

    1.设置音量时应用程序的调用过程 (1)strace分析: amixer cset numid=1 30 (设置音量) /dev/snd/controlC0 open SNDRV_CTL_IOCTL_ ...

  2. ALSA声卡08_从零编写之框架_学习笔记

    1.整体框架 (1)图示((DAI(全称Digital Audio Interface)接口)) 在嵌入式系统里面,声卡驱动是ASOC,是在ALSA驱动上封装的一层,包括以下三大块 (2)程序框架 m ...

  3. ALSA声卡10_从零编写之数据传输_学习笔记

    1.引言 (1)应用程序使用声卡的时候,数据流程是:应用程序把数据发送给驱动,驱动把数据发送给硬件声卡,声卡把数据转换成声音数据播放出去. (2)可以使用两种方式发送数据 第一种:app发数据,等驱动 ...

  4. ALSA声卡09_从零编写之参数设置_学习笔记

    1.参数设置分析 (1)open: soc_pcm_open 依次调用cpu_dai, dma, codec_dai, machine的open或startup函数 只在dma的open函数里添加参数 ...

  5. ALSA声卡07_分析调用过程_学习笔记

    1.编译新的strace工具分析aplay和amixer应用程序对声卡的调用过程 (1)因为旧的strace工具不能识别不能识别alsa声卡驱动程序里面的ioctrl. (2)编译过程参考http:/ ...

  6. ASP.NET本质论第二章应用程序对象学习笔记1

    1.请求的处理参数—上下文对象HttpContext 1) 针对每一次请求,ASP.NET将创建一个处理这次请求所使用的HttpContext对象实例,这个对象实例将用来在ASP.NET服务器的处理过 ...

  7. 微信小程序视频学习笔记

    [清华大学]学做小程序 https://www.bilibili.com/video/av21987398 2.2创建项目和文件结构 小程序包含一个描述整体程序的app和多个描述各自页面的page 配 ...

  8. 《Lua程序设计》9.1 协同程序基础 学习笔记

    协同程序(coroutine)与线程(thread)差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区 ...

  9. 第1-5章 慕课网微信小程序开发学习笔记

    第1章 前言:不同的时代,不同的Web --微信小程序商城构建全栈应用 http://note.youdao.com/noteshare?id=a0e9b058853dbccf886c1a890594 ...

随机推荐

  1. 【这些年】Linux C/C++软件开发用过的工具

          这些年一直从事Linux下C/C++软件开发,学习工作中用到了不少开发工具,一直想做个总结,却总是因为这个原因那个原因,未能动笔.趁今天天气凉爽,空气清新,花点儿功夫,做一个小结啦,防止以 ...

  2. [置顶] 滴滴插件化VirtualAPK框架原理解析(二)之Service 管理

    在前一篇博客滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理 中VirtualAPK是如何对Activity进行管理的,本篇博客,我们继续来学习这个框架,这次我们学习的是如何 ...

  3. [置顶] Android 关于SP读取与存储正确打开方式?

    一.存储方式分类:SharedPreferences存储 二.SharedPreferences存储 1.特点 ①存储单一数据,例如数值,字符串,布尔 ②文件:/date/date/包名/shared ...

  4. 配置wampserver 虚拟主机

    1.修改http.conf 找到,#Include conf/extra/httpd-vhosts.conf,修改为(有的版本服务器,默认是开启的): 2.配置httpd-vhosts.conf文件, ...

  5. 从小白开始学习iOS开发

    从事iOS开发不经意间,已经两年过去了,记得当初看到OC是,我根本就不知道那些个东西是什么?从开始学习开机,到一个个英文开始,为了能找到工作,愣是耐下心去坚持看下去. 现在回想起来,很是庆幸我没有放弃 ...

  6. BZOJ3144 Hnoi2013 切糕 【网络流】*

    BZOJ3144 Hnoi2013 切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的 ...

  7. eclipse 无用代码扫描工具UCDetector

    本文主要介绍UCDetector(无用代码扫描工具)使用方法及局限 对于沉积或多方接手开发的项目经常会遇到一坨一坨无用的代码,但一个一个类查找又相当费时,这里介绍一个eclipse插件扫描没有引用的类 ...

  8. 用fiddler设置手机代理

    做App测试的朋友可能因为环境的需要,要切换不同的测试环境,这时就需要在自己的电脑上配置好环境,然后在手机上设置代理,用WiFi连自己的电脑,这样一来,手机网络走的就是自己的电脑网络,也就是说,手机的 ...

  9. json对象和json字符串相互转换

    1.将JSON字符串转换为JSON对象 var data = JSON.parse(str); // JSON.parse();方法 console.log(data.name); 2.将JSON对象 ...

  10. lapis 处理接收到的json 数据

     备注:      在restful api 开发过程中,大家一般使用的都是json 格式的数据lapis       在处理json 数据上也是比较方便的   1. 使用的api 说明 local ...