偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1748)
分类: Android平台
2014-07-26 11:32:11
TinyAlsa是 Android 默认的 alsalib, 封装了内核 ALSA 的接口,用于简化用户空
间的 ALSA 编程。
TinyAlsa的设计目标是:
可以看出,TinyAlsa是个很轻量级的库,很容易让我们一窥究竟。
在include/asoundlib.h头文件里声明了TinyAlsa的所有接口。
/* Open and close a stream */ struct pcm *pcm_open(unsigned int card, unsigned int device, unsigned int flags, struct pcm_config *config); int pcm_close(struct pcm *pcm); int pcm_is_ready(struct pcm *pcm); /* PCM API*/ int pcm_write(struct pcm *pcm, const void *data, unsigned int count); int pcm_read(struct pcm *pcm, void *data, unsigned int count); int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count); int pcm_set_avail_min(struct pcm *pcm, int avail_min); /* MIXER API */ mixer_ctl_get_XX(struct mixer_ctl *ctl); mixer_ctl_set_XX(struct mixer_ctl *ctl);
头文件没有暴露struct pcm的内部成员,这意味着调用者只能使用它的API对音频设备 访问。 在播放操作时,pcm_mmap_write()比pcm_write()减少了内存拷贝的开销,但 由于它需要增加系统调用来同步数据指针,在缓冲区小的情况下,效率不一定总是更高, 但它提供了更好的灵活性。
合理的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; };
解释一下结构中的各个参数,每个参数的单位都是frame(1帧 = 通道*采样位深):
在不同的场景下,合理的参数就是在性能、时延、功耗等之间达到较好的平衡。
有朋友问为什么在pcm_write()/pcm_mmap_write(),而不在pcm_open()调用 pcm_start()? 这是因为音频流与其它的数据不同,实时性要求很高。作为 TinyAlsa的实现者,不能假定在调用者open之后及时的write数据,所以只能在有 数据写入的时候start设备了。
Mixer的实现很明了,通过ioctl()调用访问kcontrols.
TinyAlsa说复杂的操作应该由上层来处理,可能指的是重采样、插件功能等。但由于 不能直接访问声卡设备,以至于要添加一些功能,如非阻塞打开声卡等,只能修改它的 源代码才能实现。导出pcm的文件描述符就有那么难么?
~EOF~