Linux音频编程(一)ALSA介绍
Linux下的音频编程中有OSS和ALSA,本篇文章将对ALSA进行相关介绍。ALSA提供一系列基于命令行的工具集,比如混音器(mixer),音频文件播放器(aplay),以及控制特定声卡特定属性的工具。
一、ALSA的 API主要分为以下几种接口:
(1)控制接口:提供灵活的方式管理注册的声卡和对存在的声卡进行查询。
(2)PCM接口:管理数字音频回放(playback)和录音(capture)的接口。
(Pulse Code Modulation(脉冲编码调制)。这个词描述了一种用数字化形式表示模拟信号的方法。这种方法几乎被所有的计算机音卡所使用,它在ALSA API中用“audio”来简称。)
(3)原始MIDI接口: 支持 MIDI (Musical Instrument Digital Interface),一种标准电子音乐指令集。这些API提供访问声卡上的MIDI总线。这些原始借口直接工作在 The MIDI事件上,程序员只需要管理协议和时间。
(4)记时接口: 为支持声音的同步事件提供访问声卡上的定时器。
(5)音序器接口:一个比原始MIDI接口高级的MIDI编程和声音同步高层接口。它可以处理很多的MIDI协议和定时器。
(6)混音器接口:控制发送信号和控制声音大小的声卡上的设备。
二、
1、pcm用来描述alsa中数字音频流。Alsa音频的播放/录制可通过pcm来实现的。
2、在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。
3、alsa驱动实际上可分为两层,比如s3c24xx-iis.c或s3c24xx-ac97.c之类,主要是音频总线与硬件初始化(iis/ac97,GPIO,dma等),另一层才是wm8987.c之类的芯片驱动,主要是提供寄存器读写接口(i2c等),创建mixer设备之类。
三、PCM介绍
(一)简单介绍
1、根据ALSA写一简单的PCM应用程序,我们首先需要为PCM设备打开一个句柄(Handle),然后指定PCM流的方向是playback。
2、pcm下面有一个playback和capture stream,playback和capture下面各自有一个substream。
(1)playback如何把用户空间的应用程序发过来的PCM数据,转化为人耳可以辨别的模拟音频。
(2)capture把mic拾取到得模拟信号,经过采样、量化,转换为PCM信号送回给用户空间的应用程序。
(二)相关程序
(1)此部分程序可以参考:
可参考链接:https://blog.csdn.net/orz415678659/article/details/8995163。
其中:
snd_card 表示一个声卡实例, 包含多个声卡设备;
snd_device 表示一个声卡设备部件:
snd_pcm 表示一个PCM设备, 声卡设备的一种, 用于播放和录音 ;
snd_control 表示Control设备, 声卡设备的一种, 用于控制声卡; snd_pcm_str 表示PCM流, 分为playback和capture;
snd_pcm_substream PCM子流, 用于音频的播放或录制 ;
snd_pcm_ops PCM流操作集。
具体可参考链接:
https://www.cnblogs.com/hzl6255/p/9979377.html
(2)对于pcm.c程序可参考以下链接:
https://github.com/tinyalsa/tinyalsa/blob/master/src/pcm.c
1、合理的pcm_config可以做到更好的低时延和功耗。
struct pcm_config {
unsigned int channels;
unsigned int rate;
unsigned int period_size;
unsigned int period_count;
enum pcm_format format;
unsigned int start_threshold;
unsigned int stop_threshold;
unsigned int silence_threshold;
int avail_min;
};
(1)结构中的每个参数的单位都是frame(1帧 = 通道*采样位深):
period_size. 每次传输的数据长度。值越小,时延越小,cpu占用就越高。
(2)period_count. 缓之冲区period的个数。缓冲区越大,发生XRUN的机会就越少。
(3)format. 定义数据格式,如采样位深,大小端。
(4)start_threshold. 缓冲区的数据超过该值时,硬件开始启动数据传输。如果太大, 从开始播放到声音出来时延太长,甚至可导致太短促的声音根本播不出来;如果太小, 又可能容易导致XRUN.
(5)stop_threshold. 缓冲区空闲区大于该值时,硬件停止传输。默认情况下,这个数 为整个缓冲区的大小,即整个缓冲区空了,就停止传输。但偶尔的原因导致缓冲区空, 如CPU忙,增大该值,继续播放缓冲区的历史数据,而不关闭再启动硬件传输(一般此 时有明显的声音卡顿),可以达到更好的体验。
(6)silence_threshold. 这个值本来是配合stop_threshold使用,往缓冲区填充静音 数据,这样就不会重播历史数据了。但如果没有设定silence_size,
(7)avail_min. 缓冲区空闲区大于该值时,pcm_mmap_write()才往缓冲写数据。这个 值越大,往缓冲区写入数据的次数就越少,面临XRUN的机会就越大。Android samsung tuna 设备在screen_off时增大该值以减小功耗,在screen_on时减小该 值以减小XRUN的机会。
在不同的场景下,合理的参数就是在性能、时延、功耗等之间达到较好的平衡。
(8)struct pcm pcm_open(unsigned int card, unsigned int device, unsinged int flags, struct pcm_config config)。
2、从pcm_open这个接口可以看到,它通过几个参数获得了一个句柄,之后所有的操作都通过这个句柄来完成。这些参数里面,card代表第几块声卡,device就是上面提到的device index,它跟驱动中配置的DAI link的次序有关,flags参数中会指明这个设备是capture类型还是playback类型。通过这3个参数,就可以找到对应的PCM设备文件。
3、一个pcm设备包含播 放/录制两个流,每个流有若干个substream.一个substream只能被一个进程占用。其中snd_pcm_substream可实现音频的播放或录制。如下:
struct snd_pcm_substream {
struct snd_pcm *pcm;
struct snd_pcm_str *pstr;
void *private_data; /* copied from pcm->private_data */
int number;
char name[32]; /* substream name */
int stream; /* stream (direction) */ /* 录制/播放 */
struct pm_qos_request latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
size_t dma_max;
/* -- hardware operations -- */
const struct snd_pcm_ops *ops;
/* -- runtime information -- */
struct snd_pcm_runtime *runtime;
/* -- timer section -- */
struct snd_timer *timer; /* timer */
unsigned timer_running: 1; /* time is running */
/* -- next substream -- */
struct snd_pcm_substream *next;
/* -- linked substreams -- */
struct list_head link_list; /* linked list member */
struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */
struct snd_pcm_group *group; /* pointer to current group */
/* -- assigned files -- */
void *file; /* 指向 pcm_file */
int ref_count; /* 引用计数,打开 O_APPEND 时有用 */
atomic_t mmap_count; /* mmap 的引用计数 */
unsigned int f_flags; /* pcm 打开的文件标记 */
void (*pcm_release)(struct snd_pcm_substream *);
struct pid *pid; /* 所在进程的pid,有多个substream时用于选择使用哪个 */
/* misc flags */
unsigned int hw_opened: 1; /* 若已打开,在释放substream时需要调用close() */
};
四、补充:
alsa驱动的设备文件可在Linux系统中的/dev/snd 里查看。
其中:C0D0代表的是声卡0中的设备0,pcmC0D0c最后一个c代表capture,pcmC0D0p最后一个p代表playback。
controlC0:用于声卡的控制,例如通道选择,混音,麦克风的控制等;
midiC0D0:用于播放midi音频;
pcmC0D0c : 用于录音的pcm设备;
pcmC0D0p :用于播放的pcm设备;
seq :音序器;
timer :定时器;
Linux音频编程(一)ALSA介绍的更多相关文章
- Linux音频编程--使用ALSA库播放wav文件
在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...
- Linux音频编程
1. 背景 在<Jasper语音助理介绍>中, 介绍了Linux音频系统, 本文主要介绍了Linux下音频编程相关内容. 音频编程主要包括播放(Playback)和录制(Record), ...
- Linux音频编程指南
Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有着非常丰富的媒体功能,本文就是以多媒体应用中最基本的声音为对象,介绍如何在Linux平台下开发实际的音频应用程序 ...
- Linux音频编程指南(转)
转自: http://www.ibm.com/developerworks/cn/linux/l-audio/ Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有 ...
- [转] - Linux网络编程 -- 网络知识介绍
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- Linux音频编程(二)声卡介绍
一.声卡 1.声卡是audio interface,它含有hardware buffer,而这个hardware buffer是在声卡里面,不是内存.声卡的缓存是环状的,则ALSA中是将数据分成连续的 ...
- 【Linux系统编程应用】Linux音频编程基础(一)【转】
转自:https://blog.csdn.net/dengjin20104042056/article/details/52435290 一.数字音频 音频信号是一种连续变化的模拟信号,但计算机只能处 ...
- Linux音频编程(三)混音器介绍
一.介绍 1.mixer:用来控制多个输入.输出的音量,也控制输入(microphone,line-in,CD)之间的切换,可以将多个信号组合或者叠加在一起.声卡上的混音器由多个混音通道组成,它们可以 ...
- linux 音频编程
http://blog.csdn.net/sea918/article/details/7249216 1.音频开发模型: OSS(open sound system) linux/unix 平 ...
随机推荐
- Django REST framework的使用简单介绍
官方文档:https://www.django-rest-framework.org/ GitHub源码:https://github.com/encode/django-rest-framework ...
- Zabbix在 windows下监控网卡
1.zabbix自定义监控Windows服务器的原理 Zabbix为Windows服务器的监控提供了PerfCounter(性能计数器)这个功能.Zabbix客户端通过PerfCounter获取Win ...
- jdk8与jdk7中hashMap的resize分析
在分析代码之前,我们先抛出下面的问题: hashmap 扩容时每个 entry 需要再计算一次 hash 吗? 我们首先看看jdk7中的hashmap的resize实现 1 void resize(i ...
- 【原创】TextCNN原理详解(一)
最近一直在研究textCNN算法,准备写一个系列,每周更新一篇,大致包括以下内容: TextCNN基本原理和优劣势 TextCNN代码详解(附Github链接) TextCNN模型实践迭代经验总结 ...
- 数据结构之堆栈java版
import java.lang.reflect.Array; /* 具体原理在c++版已经说的很清楚,这里不再赘述, 就提一点:java的泛型具有边界效应,一旦离开作用域立马被替换为object类型 ...
- 【PYTHON】语法基础 | 开始使用Python
Python的热度不言而喻,机器学习.数据分析的首选语言都是Python,想要学习Python的小伙伴也很多,我之前也没有认真用过Python,所以也想体验一下它的魅力,索性花了两天集中看了一下它的基 ...
- Opengl_入门学习分享和记录_03_渲染管线(二)再谈顶点着色器以及顶点属性以及属性链接
---恢复内容开始--- 写在前面的废话:岂可修!感觉最近好忙啊,本来今天还有同学约我出去玩的.(小声bb) 正文开始:之前已经编译好的着色器中还有一些问题,比如 layout(location=0) ...
- Consul的反熵
熵 熵是衡量某个体系中事物混乱程度的一个指标,是从热力学第二定律借鉴过来的. 熵增原理 孤立系统的熵永不自动减少,熵在可逆过程中不变,在不可逆过程中增加.熵增加原理是热力学第二定律的又一种表述,它更为 ...
- [GO语言的并发之道] Goroutine调度原理&Channel详解
并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代编程语言,它的并发(并行)编程肯定是值得开发者去探究的,而Go ...
- 第 10 篇:小细节 Markdown 文章自动生成目录,提升阅读体验
目录 在文中插入目录 在页面的任何地方插入目录 处理空目录 美化标题的锚点 URL 作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 上 ...