一. alsa展现的三层结构:
   (1)audio interface:
             audio interface就是声卡,它含有hardware buffer,注意,这个hardware buffer是在声卡里面,不是内存。
  (2)computer:
            这个指的是计算机的内核和驱动(驱动由alsa提供),当(1)的audio interfacce引发中断,内核会捕捉到,再把处理移交alsa。
 (3)application:
           这个就是你写的程序,你开辟一个buffer,比如playback,就交给alsa来play。

在上面的框架下,流程如下:
  (1)playback:
          application开辟一个buffer,填上数据,调用alsa接口,alsa把buffer数据复制到其驱动的空间,再把数据交给 hardware buffer。
  (2)record:
         同playback,相似的。

二. 细节:
    按照上面的流程,其中有许多细节我们可以加以控制,这里仅仅指出应用程序需要关心的:
    1) 操作的设备:
       在alsa驱动这一层,目前为止,抽象出了4层设备:
       一是如hw:0,0,二是plughw:0,0,三是default:0,四是default至于 一是清楚了,二和二以上可以做数据转换,以支持一个动态的范围,比如你要播放7000hz的东西,那么就可以用二和二以上的。而你用7000hz作为参 数,去设置一,就会报错。三和四,支持软件混音。我觉得default:0表示对第一个声卡软件混音,default表示对整个系统软件混音,由于我没有 多声卡,所以没法试验四的效果。
       这里提出两点:
          (1)一般为了让所有的程序都可以发音,为使用更多的默认策略,我们选用三和四,这样少一些控制权,多一些方便。
          (2)对不同的层次的设备,相同的函数,结果可能是不一样的。
             比如,设置Hardware Parameters里的period和buffer size,这个是对硬件的设置,所以,default和default:0这两种设备是不能设置的。
             比如,如果直接操作hw:0,0,那么snd_pcm_writei只能写如8的倍数的frame,比如16,24,否则就会剩下一点不写入而退回,而 default,就可以想写多少就写多少,我们也不必要关心里面具体的策略。

2) Hardware Parameters:
       说明:之所以叫做Hardware Parameters,是因为alsa这一层API是较为底层的,它允许用户对上面提到的三层结构的audio interface和computer两层都做设置。其中对computer,也就是alsa驱动这一层的设置,叫做Software Parameters,而对audio interface(声卡)的设置叫做Hardware Parameters。(当然,要设置hardware parameters,也肯定是通过alsa驱动来完成,只不过哪些参数是指导硬件的,哪些是指导alsa驱动的,分开设置了)
    (1)Sample rate: 不用说了(这些,对于default设备也能设的,上面已经说了)
    (2)Sample format: 不用说了
    (3)Number of channels: 不用说了
    (4)Data access and layout:简单点,就是说,在一个period以内,数据是按照channel1排完了再排channel2呢,还是一个frame一个frame的 来排(frame在alsa里指的是一次采样时间内,两个channel的数据放一块儿就是一个frame)。默认是第二种。
    (5)Interrupt interval:中断间隔,就是靠periods决定的,有函数来设置periods,也就是说这个hardware buffer在一次遍历之内,要中断多少次,来通知内核(最终是到alsa驱动)来写入或读走数据。比如buffer是8192个frame大,而 period设为4个frame大,那么比如playback,则每当有4个frame大的hardware buffer空间空出,就会中断,通知内核(alsa驱动)来写入数据。这个是影响实时效果的关键!!!但是,我观察的,我的电脑的默认period就是 4个frame,按16字节,双通道来算的话,也就是16个字节!所以,默认就很实时了!!一般的实时程序已经够用了!!一般不用调整。
    (6)Buffer size:就是hardware buffer的大小,如果alsa整套体系主要靠这个来做缓冲,那么这个的大小,将影响缓冲效果,但是一般也不调整。

3) Software Parameters:
    (1)snd_pcm_sw_params_set_avail_min (playback_handle, sw_params, 4096)
        这个仅用在interrupt-driven模式。这个模式是alsa驱动层的,不是硬件的interrupt。它的意思是,用户使用 snd_pcm_wait()时,这个实际封装的是系统的poll调用,表示用户在等待,那么在等待什么呢?对于playback来讲,就是等待下面的声 卡的hardware buffer里有一定数量的空间,可以放入新的数据了,对于record来讲,就是等待下面声卡新采集的数据达到了一定数量了。这个一定数量,就是用 snd_pcm_sw_params_set_avail_min来设置。单位是frame。实际运作,没读驱动代码,不是很清楚,可能是alsa驱动根 据用户设的这个参数,来设置Hardware Parameters里面的period,也可能是不改变硬件的period,每次硬件中断还是copy到自己的空间,然后数据积累到一定数量再 interrupt应用程序,使之从wait()出来。我不知道,也不必深究。
这种模式的使用,需要用户在snd_pcm_wait()出来以后,调用一个平常的wirtei或readi函数,来写入或读取那个“一定数量”的数据。 如果用户不用interrupt-driven模式,那么这个函数不必使用。
    (2)snd_pcm_sw_params_set_start_threshold (playback_handle, sw_params, 0U)
        这个函数指导什么时候开启audio interface的AD/DA,就是什么时候启动声卡。
对于playback,假设第三个参数设为320,那么就是说,当用户调用writei,写入的数据,将暂时存在alsa驱动空间里,当这个数据量达到 320帧时,alsa驱动才开始将数据写入hardware buffer,并启动DA转换。对于record,当用户调用readi,这个数据量达到320帧时,alsa驱动才开始启动AD转换,捕捉数据。我一般 把它设为0,我没试过非0,如果是非0, 我想第一次的writei和readi一定得够数量才行,否则设备不启动。
这个对实时效果是需要的,将第三个参数设置为0,保证声卡的立即启动。
    (3)what to do about xruns:
        xrun指的是,声卡period一过,引发一个中断,告诉alsa驱动,要填入数据,或读走数据,但是,问题在于,alsa的读取和写入操作,好象是必 须用户调用writei和readi才会发生的,它不会去缓存数据!!!,所以如果上层没有用户调用writei和readi,那么就会产生 overrun(录制时,数据都满了,还没被alsa驱动读走)和underrun(需要数据来播放,alsa驱动却不写入数据),统称为xrun。 我对它的理解是,不是一个period引发的中断就叫做xrun,而是当整个hardware buffer都被写满了(record时)或空了(play时),这个时候的中断下的情况才指的是xrun。无所谓了,怎么立解都行,不影响编程:)
        这个东西,需要用一些函数来设置,比如snd_pcm_sw_params_set_silence_threshold(),是针对playback 的,就是设置当xxx的情况下,就用silence来写入hardware buffer。至于xxx情况,以及写入多少silence,我都不是很清楚,还有,比如xrun到什么情况下,可以停止这个设备等等函数。这个(3)的 涉及的参数,我都没试过,一般情况下,就用alsa驱动的默认的xrun处理策略吧,等以后出了错误再说,而且例子里也没有提到。
但是,关于xrun,在编程时,最好这样写:
while ((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0) {
        snd_pcm_prepare(pcm_handle);
        fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
}
        就是说,如果这次读/写距离上次读/写,时间可能过长,那么这次去读/写的时候,device已经xrun了,在不知道alsa驱动对xrun的默认策略 的情况下,最好调用snd_pcm_prepare()来重新准备好设备,然后再开始下一次读写。我想,prepare()意思,可能相当于复位,不很清 楚。我想,windows下的那套API下的驱动,一定是已经有了一套对xrun的处理策略,用户根本没有接口可以调整它,我想它的策略比如 playback遇到underrun,也就是填入silence罢了。
    (4)transfer chunk size:
这个应该是用不上的,我没找到文档里有用这个的。

三. 编码模式:
    TODO LIST:以后把下面两点补上:
      (1)一般读写模式:
    (2)interrupt-driven模式:作者推荐这个模式,我决定用这个模式来做吧。
    我推测的原因:它非常清晰的告诉了用户,你需要读取数据或写入数据了! 这样允许用户即时的作出操作:比如现在让用户从wait()出来,用户知道需要比如写入数据了,它可以决定写入真实的数据,或者写如silence,或者 其他。而用一般读写模式,你不会即时知道下层的需求!!所以,相当于你只能在你下一次读/写的时候,判断有没有xrun,其他你什么都做不了:) (并且在实时性要求不高的情况下,设置一个较大的interrupt间隔,真个alsa的效率会高一点呵呵。而且这种interrupt模式,可以使得代 码简单改下就可以用到其他采用interrupt的系统上,作者这米说的)
TODO: 再好好想想这个模式,其实我不确定实际使用上有什么好?

四. 和windows API的比较:
    windows audio接口的那些需要加入的buffer,属于应用程序的buffer,windows靠用户添加buffer queue来设置缓冲,而alsa并不提供接口让用户设置应用层的缓冲区,缓冲区的作用,就是减弱或消除数据流或用户操作偶尔过快或过慢造成的影响,所以 alsa是一定要有缓冲区的,我不知道是否,hardware buffer独自承担着alsa里面的buffer角色?
alsa的writei和readi好象可以改成
TODO: 根据实际的编程结果,从效果看看,这样做是否效果也很好。

五. 其他:
    对声卡的编程就是对两个设备进行指导的过程, 下面分3点叙述:
    1. 关于Mixer编程.
    我了解到的声卡,有三个主要部分:
    (1)mixer
    (2)dsp(ad,da)
    (3)buffer
    可以认为它们按上面(1)(2)(3)的顺序联接起来, 而buffer和计算机总线间接相连.
    目前认为的原理是这样的:
    (1)图1表现了一个mixer, 图2是很多个mixer, 但实际上, 声卡里至少有两个mixer, 一个叫做input mixer, 一个叫做output mixer. input mixer接收外来模拟信号, output mixer接收dsp给它的模拟信号. 需要知道的是, mixer的输入和输出都是模拟信号, 输入和输出的线路也叫做混音通道, 我觉得这是物理线路的范畴, 这也就是为什么一个程序调整mixer, 会影响另一个程序的原因, 因为我觉得它调整的是物理参数. 图中蓝色的方框就是可调节增益的地方(总之, 我认为它们是可供软件调节的硬件线路参数)
    (2)一个mixer的输出可以作为另一个mixer的输入. 比如考虑这样一种情景, 怎样混合CD和自己的歌声? 我估计就是CD的数字信号, 先到buffer, 经dsp的D/A转换, 输入"输出混音器"的一个混音通道(source line), 再从destination line出来后, 不送往speaker, 而是送往"输入混音器"混音通道, 这样和人声(从"输入混音器"的microphone混音通道进入)一起混音, 再从destination line出来, 送往dsp做A/D转换, 最后送往buffer.
    而调节各个source line/destination line的增益, 以及route souce line和destination line就是mixer做的, 也是软件可以调节的.
    至于系统mixer面板上的master和pcm的区别, 我想pcm是dsp输出的模拟信号, 也就是outmixer的source line的增益吧, 而master也许是outmixer的destination line的增益吧.这个其实找不到具体的声卡结构图是很难搞清楚的.
    2. 关于dsp编程.
    这个最好理解为是上述mixer体系中的一条默认的流程.对于用户来讲,dsp设备就是完成基本的播放和录音功能.
    而用户当然应该指导dsp完成工作, 就象指导mxier一样. 用户给dsp的指导参数主要是format(frame/s和bits/frame)和channel数, 要不然dsp怎样能做D/A或A/D转换呢.
    3. 关于buffer.
    涉及到的buffer有三个, 一是声卡的buffer, 二是驱动的kernel buffer, 三是用户指定的user buffer. 数据就是这样一个接一个复制上来的,或一个一个复制下去的, 复制的信号是声卡的interrupt信号. 当buffer满了(读)或buffer空了(写)时, 就会引发中断.

【ALSA】关于alsa的总结相关推荐

  1. Ubunt下使用Alsa以及Alsa和PulseAudio

    Ubunt下使用Alsa以及Alsa和PulseAudio 安装 可能出现的问题 安装 直接命令,安装alsa sudo apt-get install alsa* 接着测试录音 sudo areco ...

  2. linux4.9下alsa架构,[Alsa]4, wm8524 Kernel音频子系统入口

    上篇说到音频子系统的环境搭建和ASoC,我们会发现这样一个问题,对于已有的,已驱动的音频Codec,我们可以很方便地用aplayer.arecorder来录放音频,但是这表象背后到底隐藏了什么不为人知 ...

  3. alsa声音编程介绍

    http://blog.csdn.net/q553716434/article/details/7881552 period(周期):硬件中中断间的间隔时间.它表示输入延时. 声卡接口中有一个指针来指 ...

  4. 【QT】linux下alsa库的移植和QT中音视频的处理笔记

    一.音频的输入 linux下有一个开源的音频库----alsa库,实现了录音的功能,alsa库包含如下内容: alsa-lib-1.0.22.tar.bz2 ------- alsa的核心支持库 al ...

  5. 【嵌入式流媒体开发】Linux ALSA 声卡数据采集与播放

    文章目录 ALSA框架 环境搭建 ALSA 交叉编译移植 alsa-lib alsa-util 配置USB声卡 查看声卡设备并测试 查看音卡: 录音测试 播放测试 音频采集常见参数 WAV文件头 编程 ...

  6. arm linux alsa驱动使用 usb 声卡

    这里写目录标题 一:添加alsa驱动 二:添加alsa-lib和alsa-utils 三:录音测试 四:播放测试 五:alsa 库文件与头文件 一:添加alsa驱动 alsa内核配置选项: 二:添加a ...

  7. 荔枝派Zero(全志V3S)开启alsa,测试codec

    文章目录 前言 一.ALSA 简介 二.ALSA 框架 三.buildroot 配置 四.烧录到 SD 卡 五.测试 1.查看 CODEC 设备 2.alsa-utils 使用 ①.查看设备 ②.调节 ...

  8. Linux ALSA音频驱动之一:框架概述

    1.ALSA概述 ALSA表示高级Linux声音体系结构(Advanced Linux Sound Architecture).它由一系列内核驱动,应用程序编译接口(API)以及支持Linux下声音的 ...

  9. MT6737 Android N 平台 Audio系统学习----ALSA Driver

    1.ALSA简述   ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构,在内核设备驱动层,ALSA提供了alsa-dri ...

  10. alsa与PulseAudio

    alsa包括alsa driver, alsa lib等 pulse audio可以使用alsa driver或者其他驱动接口,实现的一个比alsa lib更加强大的音频服务程序. 如果做语音,回声消 ...

最新文章

  1. python列表中互换位置_如何在Python列表中切换两个项目的位置?
  2. SAP PM 初级系列13 - PM Revision
  3. java 泛型 get()_Java泛型,get类的泛型参数
  4. 无责任Windows Azure SDK .NET开发入门篇三[使用Azure AD 管理用户信息]
  5. 引用类型的转换 java,java中引用类型的强制转换
  6. 计算图片相似度的方法
  7. C# 利用位运算传递多个参数方法
  8. 实战Makefile
  9. 纯css3实现瀑布流布局
  10. 好看的按钮设计HTML+CSS,漂亮的动画设计
  11. YOLO-V3可视化
  12. 辩证看待倾向性评分法
  13. OneNote无法粘贴图片
  14. python全局变量(模块法和global)
  15. 7个等级 容灾等级_详细分析容灾备份的区别以及容灾的级别分类
  16. 限制 input text 只能输入数字
  17. ThreadLocal的短板,我TTL来补
  18. 阿里云无影研发负责人任晋奎:无影核心技术能力突破,打造云网端融合的全新体验
  19. 教务系统模拟登录与成绩爬取一
  20. Redis 6.0 新特性-多线程连环 13 问!

热门文章

  1. 前端之网站结构语义化
  2. 99. Recover Binary Search Tree(恢复二叉搜索树)
  3. python 解码js escape,encodeURI
  4. JavaSwing_3.1: JPanel(面板)
  5. greenplum-执行SQL创建SliceGang 学习计划。
  6. 网络舆情怎么分析研判的方案
  7. 亚马逊的这个Bug居然要花两个月时间来解决?
  8. verilog的一些技巧,就靠他拿offer了!
  9. 微信企业号开发实例源码
  10. border-radius 使用技巧