Playback / Recording / Voice 三种场景的音频数据流框图:
#mermaid-svg-nAP2CEPsCFL66meU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nAP2CEPsCFL66meU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nAP2CEPsCFL66meU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nAP2CEPsCFL66meU .error-icon{fill:#552222;}#mermaid-svg-nAP2CEPsCFL66meU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nAP2CEPsCFL66meU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nAP2CEPsCFL66meU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nAP2CEPsCFL66meU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nAP2CEPsCFL66meU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nAP2CEPsCFL66meU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nAP2CEPsCFL66meU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nAP2CEPsCFL66meU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nAP2CEPsCFL66meU .marker.cross{stroke:#333333;}#mermaid-svg-nAP2CEPsCFL66meU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nAP2CEPsCFL66meU p{margin:0;}#mermaid-svg-nAP2CEPsCFL66meU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nAP2CEPsCFL66meU .cluster-label text{fill:#333;}#mermaid-svg-nAP2CEPsCFL66meU .cluster-label span{color:#333;}#mermaid-svg-nAP2CEPsCFL66meU .cluster-label span p{background-color:transparent;}#mermaid-svg-nAP2CEPsCFL66meU .label text,#mermaid-svg-nAP2CEPsCFL66meU span{fill:#333;color:#333;}#mermaid-svg-nAP2CEPsCFL66meU .node rect,#mermaid-svg-nAP2CEPsCFL66meU .node circle,#mermaid-svg-nAP2CEPsCFL66meU .node ellipse,#mermaid-svg-nAP2CEPsCFL66meU .node polygon,#mermaid-svg-nAP2CEPsCFL66meU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nAP2CEPsCFL66meU .rough-node .label text,#mermaid-svg-nAP2CEPsCFL66meU .node .label text,#mermaid-svg-nAP2CEPsCFL66meU .image-shape .label,#mermaid-svg-nAP2CEPsCFL66meU .icon-shape .label{text-anchor:middle;}#mermaid-svg-nAP2CEPsCFL66meU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nAP2CEPsCFL66meU .rough-node .label,#mermaid-svg-nAP2CEPsCFL66meU .node .label,#mermaid-svg-nAP2CEPsCFL66meU .image-shape .label,#mermaid-svg-nAP2CEPsCFL66meU .icon-shape .label{text-align:center;}#mermaid-svg-nAP2CEPsCFL66meU .node.clickable{cursor:pointer;}#mermaid-svg-nAP2CEPsCFL66meU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nAP2CEPsCFL66meU .arrowheadPath{fill:#333333;}#mermaid-svg-nAP2CEPsCFL66meU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nAP2CEPsCFL66meU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nAP2CEPsCFL66meU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nAP2CEPsCFL66meU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nAP2CEPsCFL66meU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nAP2CEPsCFL66meU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nAP2CEPsCFL66meU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nAP2CEPsCFL66meU .cluster text{fill:#333;}#mermaid-svg-nAP2CEPsCFL66meU .cluster span{color:#333;}#mermaid-svg-nAP2CEPsCFL66meU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nAP2CEPsCFL66meU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nAP2CEPsCFL66meU rect.text{fill:none;stroke-width:0;}#mermaid-svg-nAP2CEPsCFL66meU .icon-shape,#mermaid-svg-nAP2CEPsCFL66meU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nAP2CEPsCFL66meU .icon-shape p,#mermaid-svg-nAP2CEPsCFL66meU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nAP2CEPsCFL66meU .icon-shape .label rect,#mermaid-svg-nAP2CEPsCFL66meU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nAP2CEPsCFL66meU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nAP2CEPsCFL66meU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nAP2CEPsCFL66meU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-nAP2CEPsCFL66meU .apStyle>*{fill:#e3f2fd!important;stroke:#1565c0!important;}#mermaid-svg-nAP2CEPsCFL66meU .apStyle span{fill:#e3f2fd!important;stroke:#1565c0!important;}#mermaid-svg-nAP2CEPsCFL66meU .bpStyle>*{fill:#fff3e0!important;stroke:#e65100!important;}#mermaid-svg-nAP2CEPsCFL66meU .bpStyle span{fill:#fff3e0!important;stroke:#e65100!important;}#mermaid-svg-nAP2CEPsCFL66meU .hwStyle>*{fill:#e8f5e9!important;stroke:#2e7d32!important;}#mermaid-svg-nAP2CEPsCFL66meU .hwStyle span{fill:#e8f5e9!important;stroke:#2e7d32!important;}#mermaid-svg-nAP2CEPsCFL66meU .bridgeStyle>*{fill:#fce4ec!important;stroke:#c62828!important;}#mermaid-svg-nAP2CEPsCFL66meU .bridgeStyle span{fill:#fce4ec!important;stroke:#c62828!important;}#mermaid-svg-nAP2CEPsCFL66meU .voiceStyle>*{fill:#f3e5f5!important;stroke:#7b1fa2!important;}#mermaid-svg-nAP2CEPsCFL66meU .voiceStyle span{fill:#f3e5f5!important;stroke:#7b1fa2!important;} 硬件层
BP 侧 (SPF on Modem DSP)
AP ↔ BP 边界
AP 侧 (AudioReach)
Voice 专用 (VCPM)
SPF 容器 (gen_cntr)
APM 音频处理管理器
GPR 接收
ALSA / Kernel
AGM 层
PAL 层
① Playback PCM
pcm_write
pcm_read
② Recording PCM
控制: 图配置
App / TelSDK
pal_stream_open/write/read
StreamPCM
SessionAlsaPcm / SessionAlsaVoice
graph_open/start
graph_write → gsl_write(SHMEM)
pcm_write / pcm_read
虚拟 FE PCM
gpr-lite.c
gpr_send_pkt → rpmsg
audio-pkt.c
共享内存映射
snd-soc-dummy-dai
虚拟 DAI
GPR 共享内存 Ring Buffer
SHMEM_ENDPOINT
glink modem_apps
控制命令 + 数据通知
gpr_lx.c
apm_gpr_cmd_handler
CREATE/OPEN/START/STOP
apm_graph_db
rt_proxy
读/写共享内存
模块链
gain → MFC → MBDRC → IIR
AudioIF
LPAIF I2S 驱动
VCPM 语音容器
VOICE_FLUENCE_SMECNS
EC + NS
Modem Baseband
AMR/EVS 编解码
PRI/SEC/TERT MI2S_RX
播放
PRI/SEC/TERT MI2S_TX
录音
Codec (ES8311/AK7759)
DAC / ADC
Speaker / Handset
Mic
Network
三种场景对比
┌─────────────────────────────────────────────────────────────────────────────┐
│ 音频数据流三种模式对比 │
├─────────────┬──────────────────────┬──────────────────────────────────────┤
│ 场景 │ 数据是否过 AP 内存 │ 数据通道 │
├─────────────┼──────────────────────┼──────────────────────────────────────┤
│ Playback │ ✅ 必过 │ App → pcm_write → GPR共享内存 │
│ (播放) │ │ → rt_proxy → SPF模块链 → I2S → Codec │
├─────────────┼──────────────────────┼──────────────────────────────────────┤
│ Recording │ ✅ 必过 │ Mic → Codec → I2S → SPF模块链 │
│ (录音) │ │ → rt_proxy → GPR共享内存 → pcm_read │
├─────────────┼──────────────────────┼──────────────────────────────────────┤
│ Voice Call │ ❌ 不过 │ Mic → Codec → I2S → LPASS/Modem │
│ (通话) │ (AP仅发配置命令) │ → 网络 (全在 Modem 域内闭环) │
└─────────────┴──────────────────────┴──────────────────────────────────────┘
分层架构简图
┌─────────────────────────────────────────────────────────────────┐
│ Application Layer TelSDK / 第三方 App │
├─────────────────────────────────────────────────────────────────┤
│ PAL (策略层) StreamPCM / SessionAlsaVoice │
│ resourcemanager.xml 设备路由 │
├─────────────────────────────────────────────────────────────────┤
│ AGM (图管理层) graph_open/write + ACDB GKV/CKV │
├─────────────────────────────────────────────────────────────────┤
│ ALSA / Kernel (AP) 虚拟 FE PCM + gpr-lite + audio-pkt │
├═════════════════════════════╪═══════════════════════════════════┤ ← AP/BP 边界
│ GPR 共享内存 + glink SHMEM_ENDPOINT / modem_apps │
├═════════════════════════════╪═══════════════════════════════════┤
│ GPR (BP) gpr_lx.c 接收 │
├─────────────────────────────────────────────────────────────────┤
│ APM (图管理) apm_gpr_cmd_handler 生命周期管理 │
├─────────────────────────────────────────────────────────────────┤
│ SPF 容器 gen_cntr / VCPM + 模块链 │
│ rt_proxy / gain / MFC / AudioIF │
├─────────────────────────────────────────────────────────────────┤
│ AudioIF / LPAIF I2S BCLK/WS/DATA 硬件接口控制 │
├─────────────────────────────────────────────────────────────────┤
│ Codec (外接) ES8311 / AK7759 DAC/ADC │
├─────────────────────────────────────────────────────────────────┤
│ 物理设备 Speaker / Mic / Handset / Headset │
└─────────────────────────────────────────────────────────────────┘
设备路由(MI2S 接口分配)
┌──────────────┐
│ LPASS I2S │
└──────┬───────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
PRI_MI2S SEC_MI2S TERT_MI2S
(PRIMARY) (SECONDARY) (TERTIARY)
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ ES8311 │ │ NAU8810 │ │ ES8311 │
│ Speaker │ │ Handset │ │ Headphone │
│ Speaker Mic │ │ Handset Mic │ │ Headset Mic │
└─────────────┘ └─────────────┘ └─────────────┘
AUXPCM ─── Bluetooth SCO 通话