当前位置: 移动技术网 > 科技>操作系统>Linux > Linux音频编程(一)ALSA介绍

Linux音频编程(一)ALSA介绍

2019年09月07日  | 移动技术网科技  | 我要评论

linux下的音频编程中有ossalsa,本篇文章将对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)此部分程序可以参考:

可参考链接:

 

其中:

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中的设备0pcmc0d0c最后一个c代表capturepcmc0d0p最后一个p代表playback

controlc0用于声卡的控制,例如通道选择,混音,麦克风的控制等

midic0d0用于播放midi音频

pcmc0d0c  用于录音的pcm设备

pcmc0d0p 用于播放的pcm设备

seq 音序器

timer 定时器

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网