首页 理论教育 Linux驱动程序开发实例ALSA音频缓冲逻辑实现

Linux驱动程序开发实例ALSA音频缓冲逻辑实现

时间:2023-10-19 理论教育 版权反馈
【摘要】:snd_pcm_runtime结构几乎包含了音频缓冲逻辑所有的信息:snd_pcm_uframes_t与snd_pcm_sframes_t为内核中音频帧的单位。snd_pcm_substream结构的runtime成员用于记录缓冲的运行状态。应用层读写指针为runtime->control->appl_ptr,硬件读写指针为runtime->status->hw_ptr。为了计算方便,内核将这个缓冲虚拟成runtime->boundary大小:runtime->control->appl_ptr的范围从0到runtime->boundary,但实际写数据时的地址会映射到runtime->dma_area开始的区域:appl_ofs=appl_ptr%runtime->buffer_size;ALSA环形缓冲逻辑如图15-6所示。

Linux驱动程序开发实例ALSA音频缓冲逻辑实现

snd_pcm_runtime结构几乎包含了音频缓冲逻辑所有的信息:

978-7-111-56706-6-Chapter15-68.jpg

978-7-111-56706-6-Chapter15-69.jpg

snd_pcm_uframes_t(无符号类型)与snd_pcm_sframes_t(有符号类型)为内核中音频帧的单位。snd_pcm_substream结构的runtime成员用于记录缓冲的运行状态。内核环形缓冲实际大小为runtime->buffer_size(音频帧),基地址为runtime->dma_area。应用层读写指针为runtime->control->appl_ptr,硬件读写指针为runtime->status->hw_ptr。为了计算方便,内核将这个缓冲虚拟成runtime->boundary大小:

978-7-111-56706-6-Chapter15-70.jpg

runtime->control->appl_ptr的范围从0到runtime->boundary,但实际写数据时的地址会映射到runtime->dma_area开始的区域:

appl_ofs=appl_ptr%runtime->buffer_size;

ALSA环形缓冲逻辑如图15-6所示。

978-7-111-56706-6-Chapter15-71.jpg

图15-6 ALSA音频缓冲逻辑

应用层调用Alsalib的snd_pcm_writei函数写音频数据,snd_pcm_writei函数通过IOCTL命令(SNDRV_PCM_IOCTL_WRITEI_FRAMES)向内核写入音频数据,该命令会调用内核的snd_pcm_lib_write1函数,而snd_pcm_lib_write1函数会根据runtime->control->appl_ptr找到当前应用指针,复制应用层的数据到内核后更新runtime->control->appl_ptr:

978-7-111-56706-6-Chapter15-72.jpg(www.xing528.com)

978-7-111-56706-6-Chapter15-73.jpg

DMA控制器每次传输runtime->period_size个音频帧,传输完毕会调用snd_pcm_update_hw_ptr0函数更新硬件指针,并进行下一次runtime->period_size个音频帧的传输,周而复始。

978-7-111-56706-6-Chapter15-74.jpg

snd_pcm_playback_hw_avail函数返回已经到达的音频数据:

978-7-111-56706-6-Chapter15-75.jpg

snd_pcm_playback_avail函数返回剩余音频缓冲:

978-7-111-56706-6-Chapter15-76.jpg

978-7-111-56706-6-Chapter15-77.jpg

runtime->start_threshold是声卡处于准备状态时启动音频播放的缓冲阈值,内核缓冲的数据量大于这个阈值,则启动播放。

978-7-111-56706-6-Chapter15-78.jpg

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈