alsa用户空间编程
来源:互联网 发布:大数据是一种思维方式 编辑:程序博客网 时间:2024/06/05 16:07
[-]
- ALSA简介
- Device naming
- 声音缓存和数据传输
- Overrun and underrun
- Display Some PCM Types and Formats
- Opening PCM Device and Setting Parameters
- Simple Sound Playback
- Simple Sound Recording
- Advanced Features
ALSA简介
alsa由以下几个部分组成:
1) driver内核驱动程序,包括硬件相关的和一些公共代码,了解可参考《writing an ALSA Driver》
2) library用户空间的函数库,需要包含头文件asoundlib.h,链接共享库libasound.so
3) lib-plugins提供了两个插件,一个用jack模拟alsa接口,一个用oss来模拟alsa接口。alsa可以作为jack的后端,jack也可以作为alsa的后端。alsa可以模拟oss,oss也可以模拟alsa。
4) utilities一些基于alsa的命令行小程序,可以作为示例代码参考
5) tools一些小工具,比如vxloader可以用来加载firmware
6) OSS compat与oss兼容的代码
目前alsa内核提供给用户空间的接口有:
1) information interface(/proc/asound)
2) control interface(/dev/snd/controlCx)
3) Mixer interfacce(/dev/snd/mixerCxDx)
4) PCM interface(/dev/sndpcmCxDx)
5) Raw MIDI interface(/dev/snd/midiCxDx)
6) Sequencer interface(/dev/snd/seq)
7) Timer interface(/dev/snd/timer)
和OSS类似,也是以文件的方式提供的,但这些接口是给alsalib使用的,而不是给应用程序使用的。应用程序应该使用alsalib,或者更高级的接口,比如jack提供的接口。
开发基于ALSA的应用程序时,不要直接使用alsa-driver提供的接口,而应该使用alsalib的函数。alsalib提供了丰富的功能,估计有好几百个函数,幸好常用的并不多。ALSA的howto提供一个简单的播放和录音的示例,值得参考。
Device naming
The library API works with logical device names rather than device files. The device names can be real hardware devices or plugins.
Hardware devices use the format hw:i,j, where i is the card number and j is the device on that card. The first sound device is hw:0,0. The alias default refers to the first sound device and is used in all of the examples in this article.
Plugins use other unique names; plughw:, for example, is a plugin that provides access to the hardware device but provides features, such as sampling rate conversion, in software for hardware that does not directly support it. The dmix and dshare plugins allow you to downmix several streams and split a single stream dynamically among different applications.
If you use the “plughw” interface, you need not care much about the sound hardware. If your soundcard does not support the sample rate or sample format you specify, your data will be automatically converted. This also applies to the access type and the number of channels. With the “hw” interface, you have to check whether your hardware supports the configuration you would like to use.
声音缓存和数据传输
每个声卡都有一个硬件缓存区来保存记录下来的样本。当缓存区足够满时,声卡将产生一个中断,内核声卡驱动使用DMA将样本传送到应用程序缓存区,类似的,对于播放,任何应用程序使用DMA将自己的缓存区数据传送到声卡的硬件缓存区中。
这个硬件缓存区是ring buffer,意味着当数据写到buffer的end时又会从buffer的start处开始写。在hardware buffer以及application buffer都有指针指向当前位置。
buffer的大小可以通过ALSA库函数调用来控制,缓存区很大,一次传输操作可能会导致不可接受的延迟,为了解决这个问题,ALSA将buffer拆分成一系列periods;ALSA以period为单元来传送数据,每个period存储一些frames;每个frame是一次采样的数据。对于立体声设备,一个frame会包含左右声道的采样。如下图:
这里左右声道的数据保存在一个frame中,叫做interleaved mode。而non-interleaved mode则是一个channel的数据保存在另一个channel数据的后面。
Overrun and underrun
在录音时,如果应用程序没有及时的从ring buffer中读取数据,ring buffer将被新的数据覆盖,这种数据的丢失叫overrun。
在播放时,如果应用程序没有及时的将数据写入到ring buffer,ring buffer将会饿死,称为underrun。
ALSA documentation称这两种情况为XRUN。
Display Some PCM Types and Formats
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
Makefile内容:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
Opening PCM Device and Setting Parameters
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
change the device name from “default” to “hw:0,0” or “plughw:0,0” and see whether the results change.
Simple Sound Playback
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
这个例子中从标准输入读取数据,然后将数据写到sound card中
./list3 < /dev/urandom 可以听到耳机口输出white noise
Simple Sound Recording
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
Advanced Features
前面几个例子中,PCM stream工作在blocking mode,也就是说,直到数据传输完了调用才返回,这种情况可能会让应用程序等待很长一段时间。ALSA允许以nonblocking mode打开stream,这样,read和write调用会立刻返回,如果数据传输被挂起而且调用得不到处理,那么ALSA会返回EBUSY。
许多图形界面应用程序使用callback来处理events,ALSA支持以asynchronous mode打开PCM stream,通过注册callback函数,当一个period的数据传输完成,callback函数会被调用。
snd_pcm_readi和snd_pcm_writei与系统调用read和write类似,”i”代表frames是interleaved,”n”代表frames是non-interleaved。
for non-interleaved access, each period contains first all sample data for the first channel followed by sample data for the second channel and so on.
ALSA也支持以mmap mode打开PCM channel。
最后,感谢这篇文章,让我们开始进入alsa用户空间编程的世界。
《Introduction to Sound Programming with ALSA》
原文:http://www.linuxjournal.com/article/6735?page=0,1
- ALSA用户空间编程
- ALSA用户空间编程
- alsa 用户空间编程
- ALSA用户空间编程
- alsa用户空间编程
- alsa用户空间编程
- alsa-lib、tinyalsa以及基于alsa的用户空间编程
- ALSA 用户空间之 TinyAlsa
- ALSA 用户空间之 TinyAlsa
- ALSA 用户空间之 TinyAlsa
- ALSA用户空间之TinyAlsa
- ALSA 内核提供给用户空间的接口
- RTAI用户空间编程
- V4L2 用户空间编程
- alsa 编程
- alsa 编程
- alsa编程
- alsa 编程
- 刨根究底字符编码之零——前言
- STL中stack(栈)的用法
- 51nod 1135 原根 (数论)
- STAR法则
- debian8.8访问win7共享文件夹
- alsa用户空间编程
- (个人训练赛) poj1064 poj3616 poj3041
- 解决windows安装jekyll时的问题
- C6678多核DSP开发——imglib应用之边缘检测
- 关于class.getResourceAsStream() 与class.getClassLoader().getResourceAsStream()区别
- 0519 G2n#W2A-B 盐水的故事
- 【React Native系列教程】Mac(OSX)平台搭建React Native开发环境
- 自定义仿Viewpager
- JNI开发之JNI实践