ALSA 架构

ALSA 架构

主要内容来之参考文档,对一些描述做了些修正.

ALSA 架构_第1张图片

ALSA 的基本架构可以用上图表示,组成部分主要有:

  • ALSA 应用:可能是 Native Application 或 Server,用户通过调用 ALSA 库来实现声音的播放、录制和控制。
  • ALSA Library :ALSA 用户空间库,提供统一的API,常见有 tinyalsa、alsa-lib等。
  • ALSA Layer:内核中 ALSA 核心层,与应用层的 ALSA Library 进行交互。向上提供逻辑设备系统调用,向下驱动硬件设备。主要内容为 ALSA core 和一些辅助驱动。
  • ASoC Layer:ASoC 是为支持 SoC 芯片设计的。SoC 芯片的集成度较高,传输总线、DSP、甚至 Codec 都有可能集成在一个芯片上。ASoC 层提供了一个嵌入式系统的设备管理框架,由三个部分组成:Machine、Platform、Codec。

ALSA 应用

ALSA 应用调用 ALSA 库提供的 API 来实现自己的需求。ALSA 库不同,代码实现差别也很大,这里不会做过多介绍。我们只是以 tinyalsa 为例,介绍一下声音播放的简单流程。

    struct pcm_config config;
    struct pcm *pcm;
    char *buffer;
    int size;
    int num_read;

    /* 设置音频的配置,通道、采样率、采样周期、编码格式等等 */
    config.channels = xxx;
    config.rate = xxx;
    config.period_size = xxx;
    config.period_count = xxx;
    config.format = xxx;
    
    /* 打开 PCM 设备 */
    pcm = pcm_open(card, device, PCM_OUT, &config); 

    /* 根据音频配置计算需要的 buffer */
    size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
    buffer = malloc(size);

    /* 读取数据,写入到 PCM 设备中 */
    do {
        num_read = fread(buffer, 1, size, file);
        if (num_read > 0) 
            pcm_write(pcm, buffer, num_read));
    } while (num_read > 0);

    /* 释放 buffer,关闭设备 */
    free(buffer);
    pcm_close(pcm);
}

ALSA Library

应用一般通过 ALSA Library 与内核空间交互,尽管各种 Library 在实现上差别很大,但最终都是通过 Kernel ALSA Layer 提供系统调用完成调用。

  • alsa-lib:ALSA 项目中提供的应用接口库,可以提供全部的接口支持,包括 PCM、Control、MIDI、Mixer、Sequencer、Timer等。同时在软件层面支持采样率转换、软件混音等复杂的实现。
  • tinyalsa:tinyalsa 是一个简化的 ALSA Library,在 Android 中被使用。tinyalsa 仅支持 PCM 和 Control 接口,软件层面也非常简单。正因为其简单,所以很适合在嵌入式系统中使用。

ALSA Layer

ALSA Layer 是 ALSA 架构的核心层,在内核空间实现。它为用户空间提供逻辑设备接口,如PCM、Control、Mixer等等。同时为驱动提供接口来驱动硬件设备,如总线接口、DMA、Codec等等。

该层的主要数据结构包括,

- snd_card      表示一个声卡实例, 包含多个声卡设备
- snd_device    表示一个声卡设备部件
- snd_pcm       表示一个PCM设备, 声卡设备的一种, 用于播放和录音
- snd_control   表示Control设备, 声卡设备的一种, 用于控制声卡
- snd_pcm_str   表示PCM流, 分为playback和capture
- snd_pcm_substream PCM子流, 用于音频的播放或录制
- snd_pcm_ops   PCM流操作集

各数据结构的关系如下,

ALSA 架构_第2张图片

核心驱动的一般实现步骤如下,

  1. 调用snd_card_create创建声卡实例(struct snd_card)。
  2. 定义声卡的私有结构体用于存放该声卡的一些资源信息, 如中断资源、IO资源、DMA资源等。
  3. 硬件初始化, 包括数字音频接口初始化、DMA控制器初始化、编解码器初始化。
  4. 调用snd_pcm_new创建逻辑设备, 并实现其操作集snd_pcm_ops。
  5. 调用snd_card_register注册声卡实例及声卡设备

ASoC Layer

为了简化 SoC 芯片上 ALSA 驱动的开发,在核心层的基础上构建了 ASoC(ALSA System on Chip) 层。ASoC 层主要由如下三部分组成:

  • Codec:控制音频编解码器,完成音频采集和播放过程中模拟与数字间的转换。
  • Platform:主要负责 SoC 芯片上音频 DMA 的传输控制,和数字音频接口的配置和控制,如I2S、PCM、AC97等。
  • Machine:做为 Codec 和 Platform 的载体,将硬件设备关联起来,形成完整的硬件通路。

ASoC Layer 主要负责驱动音频硬件设备,对外表现为一个整体的 Machine。Platform 控制 SoC 芯片中数字音频传输。Codec 控制音频编解码器,可能为内置或外置,通常使用 I2C 进行控制。

ASoC 支持三种主流的数字音频接口(Digital Audio Interfaces):AC97、I2S 和 PCM。注意这里的 PCM 表示只有硬件接口协议,与上面所说的软件 PCM 接口不同。

AC97: 通常用于PC声卡, 为5线接口, 每个AC97帧为21uS长, 被分为13个时隙

  • BCLK: 由AC97驱动, 为12.288 MHz
  • SYNC: 同步信号, 由Controler驱动, 为48 kHz
  • SDATDIN: 用于capture, AC97->Controler
  • SDATAOUT: 用于playback, Controler->AC97
  • RESET: 由Controler生成, 用于唤醒AC97

I2S是HiFi、STB和便携式设备中常用的4线DAI

  • SCLK: 串行时钟
  • LRCK: 也称WS, 声道选择线
  • Tx: 用于传输音频数据
  • Rx: 用于接收音频数据

PCM是另一种4线接口, 与I2S非常相似, 可以支持更灵活的协议

  • BCLK: 位时钟, 根据采样率而变化
  • SYNC: 同步信号
  • Tx: 用于传输音频数据
  • Rx: 用于接收音频数据

Codec驱动用于配置编解码器、FM、MODEM、BT 或外部 DSP, 以提供 playback 和 capture。每个Codec驱动必须提供如下功能:

  1. Codec DAI和PCM配置
  2. 使用RegMap实现的Codec控制IO
  3. Mixers和Audio控制
  4. Codec音频操作
  5. DAPM描述
  6. DAPM事件处理
  7. DAC静音控制(可选)
参考文档:

Linux ALSA详解

你可能感兴趣的:(linux-kernel,音频)