杰理 SDK 文档中心
首页
首页
  • 入门指南

    • SDK 概述与芯片平台
    • 环境搭建与开发工具链
    • 编译、烧录与快速开始
  • 应用层开发

    • 语音玩具应用 voice_toy
    • 扩音器应用 voice_enhanced
    • 语音功能状态机 voice_func
    • 应用公共框架与配置
  • 音频子系统

    • 音频解码器与 MIDI 播放
    • 音频编码与录音
    • 音效算法(ANS、变调、变声、混响)
    • 音频输出、功放与硬件重采样
  • 存储与文件系统

    • 文件系统层(FAT、NOR_FS、SYDF 等)
    • 存储设备与设备管理
    • 参数存储 VM 与保留区
  • 系统机制

    • 消息与事件机制
    • 电源管理与低功耗
    • 固件升级机制
    • 外设驱动(按键、红外、SPI、USB)
    • 实时时钟与定时器
  • 构建系统与工具

    • 构建系统(Makefile 与 Code::Blocks)
    • 编译后处理与语音资源打包
  • 硬件平台与文档

    • 芯片平台与启动流程
    • 硬件文档、规格书与原理图

音频输出、功放与硬件重采样

本文档介绍 AD24N SDK 中音频输出(DAC)子系统的完整实现:DAC 输出通道管理、功放(APA)控制、采样率配置与硬件重采样机制,以及音量、静音、淡入淡出、多通道混音等核心行为。

Purpose and Scope

本页覆盖音频链路末端的 DAC 输出通路:从解码器/音效处理后的 PCM 数据经环形缓冲进入 DAC 引擎,到硬件数模转换、功放放大并驱动扬声器的完整过程,包括:

  • DAC 通道注册与数据填充(regist_dac_channel / fill_dac_fill)
  • 数字音量曲线(vol_tab)与硬件音量(DAC_VOL、rdac_phy_vol)
  • 输出采样率配置与硬件重采样(AUDAC_SR*、adda_clk_open)
  • 功放(APA)使能与时钟选择(DAC0_APA_SEL、apa_clk_sel)
  • 静音与淡入淡出(dac_mute、dac_fade_*)

以下相关主题由兄弟页面覆盖,不在本页展开:音频解码与播放管理(decoder/player 子系统)、音效处理(sound_effect)、ADC/录音通路。本文只引用与 DAC 输出直接相关的源码。

概述

在 AD24N 这样的蓝牙/音频 SoC 中,DAC(Digital-to-Analog Converter)是音频回放链路的最后一级数字处理单元:它接收各音频源(解码器、提示音、USB 等)写入的 PCM 数据,在内部完成多通道混音、数字音量缩放、抗混叠/去直流处理,输出模拟信号经功放(APA)驱动扬声器。

SDK 通过三层封装管理这条通路:

  1. 应用层 API(dac_api.h / dac_api.c):提供 dac_* / auout_* 接口,负责通道注册、音量、采样率、静音等策略;
  2. 驱动/硬件层(audio_dac_cpu.h 及对应实现):直接操作 JL_AUDDAC 寄存器,配置采样率、DMA、去直流滤波器、APA 输出;
  3. 模拟前端:audio_analog / adda_* 负责模拟电路上电、时钟开闭。

其中"硬件重采样"体现在:DAC 引擎本身支持从 8K 到 96K 的一族固定输出采样率(AUDAC_SR*),当解码器输出采样率与 DAC 目标采样率不一致时,由驱动层的时钟与采样率管理(adda_clk_open(sr)、audio_dac_sr_api)完成重采样/时钟切换,保证输出时钟与解码数据速率匹配。

架构

flowchart TD
    subgraph sg_Source["音频源 (Source)"]
        Decoder["解码器 / 播放器"]
        KeyVoice["提示音 d_key_voice"]
        MIO["MIO 混音输入"]
    end

    subgraph sg_App["应用层 API (dac_api)"]
        Regist["regist_dac_channel / unregist_dac_channel"]
        Fill["fill_dac_fill_phy"]
        Vol["dac_vol / phy_vol_set"]
        SrApi["dac_sr_api / auout_sr_api"]
        Mute["dac_mute / dac_fade"]
    end

    subgraph sg_Chan["DAC 通道管理 (DAC_MANAGE)"]
        Sound["sound_out_obj *sound[]"]
        Cbuf["环形缓冲 p_obuf"]
        Kick["kick 回调"]
    end

    subgraph sg_Hw["硬件层 (audio_dac_cpu / analog)"]
        AUDDAC["JL_AUDDAC 寄存器"]
        AddaClk["adda_clk_open / adda_clk_close"]
        APA["功放 APA (DAC0_APA_SEL)"]
    end

    Decoder -->|"注册通道"| Regist
    Regist --> Sound
    Sound --> Cbuf
    KeyVoice --> Fill
    MIO --> Fill
    Fill -->|"混音/音量/钳位"| AUDDAC
    Vol -->|"vol_tab / DAC_VOL"| AUDDAC
    SrApi --> AddaClk
    AddaClk -->|"采样率/重采样"| AUDDAC
    Mute --> AUDDAC
    AUDDAC -->|"模拟输出"| APA
    APA --> Speaker["扬声器"]

架构说明:

  • 音频源:解码器通过 regist_dac_channel 把 sound_out_obj(内含环形缓冲与 kick 回调)注册进 DAC 管理器;提示音、MIO 等其他来源直接写入 DAC 填充缓冲。
  • DAC_MANAGE:dac_api.c 中的全局管理结构,保存最多 DAC_CHANNEL_NUMBER 路 sound_out_obj 指针与 kick 回调、当前数字音量、物理音量设置函数等,存放于 .DAC_BUFFER 内存段。
  • 硬件层:JL_AUDDAC 寄存器组控制采样率(DAC_SR*)、通道使能、DMA、去直流(DAC0_CHPHSET)、抖动(DAC0_DITHER)与 APA 输出;adda_clk_open(sr) 按目标采样率配置模拟时钟,即硬件重采样的时钟基准。
  • 功放:DAC0_APA_SEL 位与 apa_clk_sel() 控制片内功放的使能与时钟,最终驱动扬声器。

关键实现

DAC 通道注册与环形缓冲

解码器要发声必须先注册通道。regist_dac_channel 接收 sound_out_obj(含数据缓冲 p_obuf)与 kick 回调;DAC 中断/填充逻辑按需从各通道环形缓冲取数。dac_cbuff_active 判断通道是否"就绪":当通道处于 B_DEC_PAUSE(暂停)或 B_DEC_FIRST(首包未满)状态时,需等环形缓冲填充过半才真正放行,防止启动瞬间输出半包数据:

SEC(.audio_d.text.cache.L2)
bool dac_cbuff_active(void *sound_hld)
{
    sound_out_obj *psound = sound_hld;
    if (psound->enable & (B_DEC_PAUSE | B_DEC_FIRST)) {
        if (cbuf_get_data_size(psound->p_obuf) >= (cbuf_get_space(psound->p_obuf) / 2)) {
            psound->enable &= ~B_DEC_FIRST;
        }
        return false;
    } else {
        return true;
    }
}

来源:dac_api.c

设计意图:B_DEC_FIRST 是"首包欠载保护"——播放刚开始时缓冲内数据不足,若立刻读取会输出断续/噪声;待缓冲过半后再清除该标志,保证连续稳定输出。

多通道混音与数据填充

fill_dac_fill_phy 是 DAC 中断驱动的核心填充函数:它对所有已使能且活跃的通道执行"读环形缓冲 → 逐样点累加混音 → 软件音量缩放 → 防直流偏移 → 饱和钳位 → 写回输出缓冲"。

for (sp_cnt = 0; sp_cnt < sp_number; sp_cnt++) {
    t_sp = 0;
    for (i = 0; i < DAC_CHANNEL_NUMBER; i++) {
        if (0 == rptr[i]) {
            continue;
        }
        if (0 == olen[i]) {
            rptr[i] = cbuf_read_alloc(dac_mge.sound[i]->p_obuf, &olen[i]);
            if (0 == olen[i]) {
                log_char('x');
                rptr[i] = 0;
            }
            continue;
        }
        p_cnt[i]++;
        t_sp += *rptr[i];
        rptr[i]++;
        if ((p_cnt[i] * 2) >= olen[i]) {
            cbuf_read_updata(dac_mge.sound[i]->p_obuf, p_cnt[i] * 2);
            olen[i] = 0;
            p_cnt[i] = 0;
            rptr[i] = cbuf_read_alloc(dac_mge.sound[i]->p_obuf, &olen[i]);
        }
    }
    if ((NULL == dac_mge.phy_vol_set) && (MAX_PHY_VOL != dac_mge.vol_phy)) {
        t_sp = (t_sp * dac_mge.vol_phy) / (MAX_PHY_VOL + 1);
    }
    t_sp += sp_buf[sp_cnt];
    dac_sp_handle(t_sp);
    if (t_sp > 32767) {
        t_sp = 32767;
    } else if (t_sp < -32768) {
        t_sp = -32768;
    }
    sp_buf[sp_cnt] = t_sp;
}

来源:dac_api.c

要点:

  • 每路通道通过 cbuf_read_alloc 零拷贝取读指针,按样点累加,耗尽的段用 cbuf_read_updata 推进;log_char('x'/'y'/'z') 打印欠载诊断字符。
  • 软件音量:仅当未注册 phy_vol_set(即不采用硬件音量)且当前物理音量非最大时,对混音结果按 vol_phy 缩放,避免整数溢出。
  • dac_sp_handle(t_sp) 是硬件辅助宏:每次调用在 ±1 间交替加到样点上,形成极小幅度的直流偏移补偿(配合去直流滤波器使用)。
  • 最终样点做 16-bit 饱和钳位(32767/-32768),防止多路混音溢出产生爆音。

音量控制:对数曲线与硬件音量

DAC 音量采用 0~31 级指数(近似对数听觉)曲线 vol_tab,从 0 到满幅 16383 递增,每级约 1.5~1.7 倍,保证人耳听感线性:

const u16 vol_tab[] = {
    0, 164, 191, 223, 260, 303, 353, 412, 480, 559, 652, 760, 887,
    1034, 1205, 1405, 1638, 1910, 2227, 2597, 3028, 3530, 4115,
    4798, 5594, 6523, 7605, 8867, 10338, 12053, 14052, 16383
};
#define MAX_VOL_LEVEL ((sizeof(vol_tab)/2) - 1)
#define MAX_PHY_VOL   vol_tab[MAX_VOL_LEVEL]

来源:dac_api.c

dac_mode_init(vol, phy_vol_set_func) 是音量初始化入口:若传入 phy_vol_set_func,后续音量由该函数(硬件写 DAC_VOL 寄存器,如 rdac_phy_vol)执行,软件只保存当前级数;否则直接写 JL_AUDDAC->DAC_VOL 为固定值 16384,音量完全由软件样点缩放完成。代码注释明确给出设计取向:"调节音量建议固定硬件数字音量,只调节软件样点幅值来改变音量"——即硬件音量固定在中间值,用软件乘法缩放避免低音量下信噪比恶化。

void dac_mode_init(u16 vol, void *phy_vol_set_func)
{
    memset(&dac_mge, 0, sizeof(dac_mge));
    /* 调节音量建议固定硬件数字音量,只调节软件样点幅值来改变音量 */
    if (phy_vol_set_func) {
        dac_mge.phy_vol_set = phy_vol_set_func;
    } else {
        SFR(JL_AUDDAC->DAC_VOL,  0, 16, 16384);
    }
#if DAC_FADE_ENABLE
    dac_mge.vol = vol;
    if (dac_mge.vol > MAX_VOL_LEVEL) {
        dac_mge.vol = MAX_VOL_LEVEL;
    }
#else
    dac_vol(0, vol);
#endif
    auout_mode_init();
}

来源:dac_api.c

采样率配置与硬件重采样

DAC 引擎支持固定的输出采样率族,由 audio_dac_cpu.h 中的 AUDAC_SR* 宏定义(8K ~ 96K,含 44.1K/48K 等标准率):

//dac 输出采样率
#define AUDAC_SR96K       (0b0000)
#define AUDAC_SR88K2      (0b0001)
#define AUDAC_SR64K       (0b0010)
#define AUDAC_SR48K       (0b0100)
#define AUDAC_SR44K1      (0b0101)
#define AUDAC_SR32K       (0b0110)
#define AUDAC_SR24K       (0b1000)
#define AUDAC_SR22K05     (0b1001)
#define AUDAC_SR16K       (0b1010)
#define AUDAC_SR12K       (0b1100)
#define AUDAC_SR11K025    (0b1101)
#define AUDAC_SR8K        (0b1110)
#define AUDAC_SRBITS      (0b1111)

来源:audio_dac_cpu.h

应用层通过 dac_sr_api(sr)(宏映射为 auout_sr_api → audio_dac_sr_api)切换输出采样率;驱动层 adda_clk_open(u32 sr) 负责为该采样率配置模拟时钟(PLL/分频),adda_clk_close 在关闭时释放。这即是"硬件重采样"的时钟侧实现:DAC 输出率独立于解码率,由硬件时钟与数据速率匹配完成转换,应用只需在切换播放内容时调用 dac_sr_api 一次。初始化时 dac_init_api(sr, delay_flag) 完成 DAC 上电初始化——注释强调"上电开机调用需要延时至少 1.2ms",用于等待模拟电路稳定。

//1:有延时 0:没有延时, 上电开机调用需要延时至少1.2ms
void dac_init_api(u32 sr, bool delay_flag)
{
    auout_init(sr, delay_flag);
}

void dac_sr_api(u32 sr)
{
    auout_sr_api(sr);
}

void dac_off_api(void)
{
    auout_off_api();
}

来源:dac_api.c

功放(APA)与模拟输出控制

功放使能与输出控制集中在 audio_dac_cpu.h 的寄存器宏中。DAC0_APA_SEL (1 << 9) 选择片内功放(APA)输出路径;DAC_CON0_DEFAULT 是默认配置,含中断使能(DAC0_IE)、DEM 抗混叠(DAC0_DEM_EN + DAC0_DEM_LS(3))、通道使能(DAC0_CHEN)、DMA 使能(DAC0_DMA_EN)、去直流滤波器(DAC0_CHPHSET,注释建议 14)与抖动(DAC0_DITHER(3),分频 8):

#define DAC0_APA_SEL         (1 << 9)
#define DAC0_RELEASE_RST     (1 << 8)
#define DAC0_PND             (1 << 7)
#define DAC0_CPND            (1 << 6)
#define DAC0_IE              (1 << 5)
#define DAC0_DMA_EN          (1 << 4)

#define DAC_CON0_DEFAULT  \
    ( \
      DAC0_IE        |\
      DAC0_DEM_EN    |\
      DAC0_DEM_LS(3) |\
      DAC0_CHEN      |\
      DAC0_DMA_EN    |\
      DAC0_CHPHSET   |\
      DAC0_DITHER(3) \
    )

来源:audio_dac_cpu.h

驱动层通过 au_const_apa_en / au_const_dac_digital_en / au_const_dac_analog_en / au_const_adda_common_en 等常量控制数字/模拟/公共模块的电源门控顺序,apa_clk_sel() 选择功放时钟,audio_dac_analog_init() / adda_dac_analog_init() 完成模拟电路上电,adda_dac_analog_close() 关闭。这些步骤保证"先开数字 → 再开模拟 → 最后开功放"的上电次序,避免 pop 音。

静音与淡入淡出

dac_mute(bool) 提供硬件级静音(B_DAC_MUTE 标志位)。淡入淡出仅在 D_MBOX_SDK 配置下编译启用(DAC_FADE_ENABLE),通过 dac_fade_in() / dac_fade_out(delay) 实现;未启用时这些调用被展开为空宏,零开销:

#ifdef D_MBOX_SDK
#define DAC_FADE_ENABLE  1
#else
#define DAC_FADE_ENABLE  0
#endif
#if DAC_FADE_ENABLE
void dac_fade(void);
void dac_fade_in(void);
void dac_fade_out(u32 delay);
#define dac_fade_api        dac_fade
#define dac_fade_in_api     dac_fade_in
#define dac_fade_out_api    dac_fade_out
#else
#define dac_fade_api()
#define dac_fade_in_api()
#define dac_fade_out_api(...)
#endif

来源:dac_api.h

硬件层面,DAC_CON1 寄存器提供 DAC1_FADE_EN、DAC1_FADE_STEP(n)(每步幅值)、DAC1_FADE_SLOW(n)(步进慢速分频)与 DAC1_FADE_BUSY,即淡入淡出可由硬件自动执行,CPU 只需配置步进参数并查询忙标志。该机制用于播放开始/结束、切歌或蓝牙断开时平滑过渡音量,消除突变的咔嗒声。

核心流程

sequenceDiagram
    participant App as 应用/播放器
    participant DAC as DAC_MANAGE (dac_api)
    participant HW as JL_AUDDAC 驱动
    participant APA as 功放/扬声器

    App->>DAC: dac_mode_init(vol, phy_vol_set)
    DAC->>DAC: 保存音量表与音量函数
    DAC->>HW: auout_mode_init() 配置默认寄存器
    App->>DAC: dac_init_api(sr, delay)
    DAC->>HW: auout_init: 上电 + 1.2ms 延时
    App->>DAC: regist_dac_channel(sound, kick)
    DAC->>DAC: 登记 sound_out_obj 与 kick
    App->>DAC: dac_sr_api(sr) 切换采样率
    DAC->>HW: audio_dac_sr_api / adda_clk_open(sr)
    HW-->>DAC: 时钟就绪 (硬件重采样基准)
    loop DAC 中断周期
        DAC->>DAC: fill_dac_fill_phy: 多通道混音 + 音量 + 防直流
        DAC->>HW: DMA 填充输出缓冲
        HW->>APA: 模拟输出 → 功放 → 扬声器
    end
    App->>DAC: dac_mute(true) / dac_fade_out
    App->>DAC: unregist_dac_channel / dac_off_api

流程要点: 初始化顺序为"音量表 → 模式初始化 → DAC 上电(含 1.2ms 延时)→ 注册通道 → 采样率切换";此后 DAC 中断驱动的 fill_dac_fill_phy 每周期拉取各通道数据、混音并送入 DMA;关断顺序与上电相反(先淡出/静音、注销通道、最后 dac_off_api),以保证无 pop 音。

使用示例

基本使用:初始化与注册输出通道

以下序列是播放器打开 DAC 输出的标准做法:设置音量模式 → 初始化 DAC → 注册通道 → 设置采样率。

/* 初始化:0~31 级音量,phy_vol_set 传 NULL 则使用软件音量 */
dac_mode_init(25, NULL);
/* 上电初始化,delay_flag=1 表示上电需 1.2ms 延时 */
dac_init_api(44100, 1);
/* 注册解码器输出通道 */
regist_dac_channel(sound, kick);
/* 切换输出采样率(硬件重采样时钟跟随) */
dac_sr_api(44100);

来源:dac_api.h 接口声明;实现见 dac_api.c

音量与静音控制

/* 设置音量 0~31,返回实际生效等级 */
u8 cur = dac_vol(0, 20);
/* 静音 / 取消静音 */
dac_mute(true);
dac_mute(false);
/* 播放结束淡出后关闭 */
dac_fade_out_api(100);
dac_off_api();

来源:dac_api.h

硬件音量模式(注册物理音量函数)

若板级驱动提供硬件音量函数(如 rdac_phy_vol),将其注册给 DAC 管理器,音量由硬件寄存器执行:

#define D_PHY_VOL_SET_FUNC  rdac_phy_vol
/* 传入硬件音量设置函数,软件不再缩放样点 */
dac_mode_init(30, D_PHY_VOL_SET_FUNC);

来源:audio_dac_cpu.h、dac_api.c

配置选项

选项类型默认值说明
DAC_PACKET_SIZE宏32*8(SH57 为 32*2)DAC 每次填充的数据包大小(采样点×字节)
DAC_DECODER_BUF_SIZE宏DAC_PACKET_SIZE * 5解码器侧 DAC 缓冲大小
SR_WORKMODE枚举SR_NORMALSR_NORMAL=随解码率切换;SR_CONSTANT=固定输出率
DAC_FADE_ENABLE宏0(D_MBOX_SDK 时为 1)是否启用淡入淡出 API
vol_tabconst u16[32]0~16383 指数表0~31 级数字音量映射表
MAX_VOL_LEVEL宏31最大音量级数(vol_tab 元素数-1)
MAX_PHY_VOL宏16383最大物理音量
DAC0_CHPHSET寄存器位14去直流滤波器配置(建议值 14)
DAC0_DITHER(n)寄存器位3(分频 8)抖动分频选择
SR_DEFAULT宏32000DAC 默认输出采样率
AUDAC_SR*宏—8K~96K 固定输出采样率编码

API 参考

bool dac_mute(bool mute)

设置/取消 DAC 静音(硬件 B_DAC_MUTE 标志)。

  • 参数:mute — true 静音,false 取消。
  • 返回:操作后的静音状态。

void dac_mode_init(u16 vol, void *phy_vol_set_func)

初始化 DAC 管理模式与音量。

  • 参数:vol — 初始音量级(0~31,超出则钳位到 MAX_VOL_LEVEL);phy_vol_set_func — 硬件音量设置函数,NULL 表示软件音量并固定 DAC_VOL=16384。
  • 说明:内部清零 dac_mge,随后调用 auout_mode_init()。

void dac_init_api(u32 sr, bool delay_flag)

DAC 上电初始化。

  • 参数:sr — 初始输出采样率(Hz);delay_flag — 1 表示上电需 ≥1.2ms 延时。
  • 说明:透传 auout_init(sr, delay_flag)。

void dac_sr_api(u32 sr)

切换 DAC 输出采样率(触发硬件重采样时钟切换)。

  • 参数:sr — 目标采样率(如 44100/48000)。
  • 说明:透传 auout_sr_api → audio_dac_sr_api,配合 adda_clk_open 配置时钟。

void dac_off_api(void)

关闭 DAC 输出,透传 auout_off_api()。

u32 fill_dac_fill(u8 *buf, u32 len, AUDIO_TYPE type)

DAC 数据填充入口(中断路径),内部调用 fill_dac_fill_phy 完成混音、音量缩放、防直流与钳位。

  • 参数:buf — 输出 PCM 缓冲;len — 字节数;type — 音频类型。
  • 返回:填充字节数。

u8 dac_vol(char set, u8 vol)

设置/读取音量级。

  • 参数:set — 非 0 写入、0 读取;vol — 目标音量级 0~31。
  • 返回:实际生效音量级。

bool regist_dac_channel(void *sound, void *kick) / bool unregist_dac_channel(void *dec_hld)

注册/注销一路 DAC 输出通道(sound_out_obj + kick 回调)。

  • 参数:sound — sound_out_obj*(含环形缓冲);kick — 数据请求回调;dec_hld — 解码器句柄。
  • 返回:是否成功。

bool dac_cbuff_active(void *sound_hld)

查询通道环形缓冲是否就绪(首包/暂停保护逻辑,见上文实现)。

淡入淡出(DAC_FADE_ENABLE=1 时)

  • void dac_fade(void) / void dac_fade_in(void) / void dac_fade_out(u32 delay)
  • 未启用时对应宏展开为空。

故障模式与边界情况

  • 缓冲欠载:fill_dac_fill_phy 在环形缓冲无数据时打印诊断字符 x/y/z(对应首段耗尽、重取失败、初始取数失败),并输出静音样点;长时间欠载表现为"沙沙/断续"声,应检查解码器 kick 节奏与缓冲容量(DAC_DECODER_BUF_SIZE)。
  • 启动半包:B_DEC_FIRST 保护——首包必须填满一半缓冲才放行,否则跳过该通道,避免起始爆音。
  • 混音溢出:多通道累加可能超过 16-bit 范围,fill_dac_fill_phy 末尾做 32767/-32768 饱和钳位;叠加 dac_sp_handle 的 ±1 补偿不会破坏钳位。
  • 上电时序:DAC 上电必须满足 ≥1.2ms 延时(delay_flag),否则模拟电路未稳定即输出会产生异常;关断顺序颠倒也会引入 pop 音。
  • 采样率不匹配:若解码率与 dac_sr_api 设置不一致且未切换时钟,可能出现音调偏移;应在切换播放内容时同步调用 dac_sr_api(SR_NORMAL 模式)。
  • 并发/中断:dac_mge 为全局单例,填充逻辑运行在 DAC 中断上下文;音量/通道注册等 API 应在任务上下文调用,避免在中断内修改共享结构导致竞态。

性能与运维

  • 填充函数与活跃判断标注 SEC(.audio_d.text.cache.L2) / AT(.audio_d.text.cache.L2),将热路径代码/数据放入 L2 缓存段,减少中断时延;dac_mge 位于 .DAC_BUFFER 段。
  • 混音循环对每路通道逐样点累加,通道数越多 CPU 开销越大;dac_cbuff_active 提前跳过非活跃通道可降低空转开销。
  • 硬件音量模式下软件仅保存级数,样点缩放由 DAC_VOL 完成,节省 DSP 周期;建议按注释"固定硬件数字音量、软件调幅"的组合。
  • 淡入淡出建议交给硬件 DAC1_FADE_* 寄存器(步进/慢速/忙标志)执行,避免在中断中做软件包络。

扩展点

  • 物理音量函数:dac_mode_init 的 phy_vol_set_func 参数是板级音量扩展点,可注册自定义硬件音量实现(默认 rdac_phy_vol)。
  • 新增输出通道:通过 regist_dac_channel 可挂接任意 sound_out_obj 数据源(解码器、提示音、MIO 等),混音逻辑自动合并。
  • 采样率族:AUDAC_SR* 枚举与 adda_clk_open 驱动层支持 8K~96K 全族输出率,新增采样率只需驱动层补充时钟表。
  • 淡入淡出策略:DAC_FADE_ENABLE 编译开关控制 API 面,可在 D_MBOX_SDK 下扩展淡入淡出策略。

相关链接

  • DAC 硬件寄存器与采样率定义:audio_dac_cpu.h
  • DAC 应用层接口:dac_api.h
  • DAC 实现与混音/音量逻辑:dac_api.c
  • 平台 DAC 驱动实现:dac_cpu.c
  • 相关主题:解码/播放子系统(decoder/player)、音效处理(sound_effect)、ADC 录音通路,请参阅音频子系统下对应页面。
Prev
音效算法(ANS、变调、变声、混响)