简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址: Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏地址: 多媒体系统工程师系列原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🌻1. 前言

本篇目的:Linux PulseAudio 深度解析之 pa_stream_set_read_callback 调用流程与实战。

要点概括

  • 核心功能:为录音 Stream 注册“可读数据到达”回调函数。
  • 工作机制:当 PulseAudio Server 有新的录音数据到达时,由 libpulse 异步触发应用层 read callback。

🌻2. 用法与应用场景

pa_stream_set_read_callback
是 PulseAudio 录音链路中的核心接口之一。

在 PulseAudio 中:

  • 录音数据到达是异步的
  • 麦克风采集是持续流式的
  • 应用层无法主动轮询高效获取数据

因此:

PulseAudio 使用 read callback 通知应用层“新的 PCM 数据已经到达”。

函数原型

void pa_stream_set_read_callback(
        pa_stream *p,
        pa_stream_request_cb_t cb,
        void *userdata);

参数说明

p:
目标 pa_stream

cb:
录音数据到达回调函数

userdata:
用户私有数据

回调函数原型

typedef void (*pa_stream_request_cb_t)(
        pa_stream *p,
        size_t nbytes,
        void *userdata);

应用场景

1. 麦克风录音

pa_stream_set_read_callback(
        stream,
        read_cb,
        NULL);

用于:

  • PCM 录音
  • 麦克风采集
  • 实时语音输入

2. 实时语音识别

例如:

  • ASR
  • AI 语音助手
  • 实时字幕

都依赖:

read callback

实时获取音频数据。


3. 音频数据分析

例如:

  • FFT
  • VU Meter
  • 波形显示
  • 音量检测

都需要:

实时获取 PCM 数据。


🌻3. 调用流程剖析

🌻3.1 核心步骤

1. 应用层注册 read callback
pa_stream_set_read_callback(
        stream,
        read_callback,
        userdata);

2. libpulse 保存回调函数

内部本质执行:

stream->read_callback = cb;
stream->read_userdata = userdata;

3. 服务端产生录音数据

例如:

  • 麦克风采集
  • Source 输出
  • monitor source 数据

都会产生:

PCM 数据块

4. libpulse 接收到音频数据

native protocol 收到:

RECORD_STREAM_DATA

数据包后:

libpulse 把数据写入:

stream buffer

5. libpulse 触发 read callback

内部自动执行:

stream->read_callback(
        stream,
        nbytes,
        userdata);

通知应用层:

有新的录音数据到达。


🌻3.2 调用流程图

Application
应用程序

调用 pa_stream_set_read_callback

libpulse 保存 callback

PulseAudio Server 持续录音

产生 PCM 数据

发送 RECORD_STREAM_DATA

libpulse 接收数据

写入 stream buffer

触发 read callback

应用层读取 PCM 数据

🌻3.3 Read Callback 生命周期图

connect_record

PA_STREAM_READY

注册 read callback

麦克风采集数据

服务端发送 PCM

libpulse 接收数据

触发 read callback

pa_stream_peek

处理 PCM 数据

pa_stream_drop

🌻4. 实战应用案例

#include <pulse/pulseaudio.h>
#include <stdio.h>

void read_callback(
        pa_stream *s,
        size_t nbytes,
        void *userdata) {

    const void *data;

    /*
     * 获取 PCM 数据
     */
    if (pa_stream_peek(
                s,
                &data,
                &nbytes) < 0) {

        printf("pa_stream_peek failed\n");
        return;
    }

    if (!data || nbytes == 0) {

        pa_stream_drop(s);
        return;
    }

    printf("收到录音数据: %zu bytes\n",
           nbytes);

    /*
     * 这里可执行:
     *
     * FFT
     * ASR
     * 编码
     * 保存文件
     */

    /*
     * 数据消费完成
     */
    pa_stream_drop(s);
}

int main() {

    pa_stream *stream;

    /*
     * 假设 stream 已 connect_record 成功
     */

    pa_stream_set_read_callback(
            stream,
            read_callback,
            NULL);

    return 0;
}

🌻5. 源码层核心原理

pa_stream_set_read_callback
在 libpulse 中本质非常简单。

内部逻辑类似:

void pa_stream_set_read_callback(
        pa_stream *s,
        pa_stream_request_cb_t cb,
        void *userdata) {

    pa_assert(s);

    s->read_callback = cb;
    s->read_userdata = userdata;
}

真正复杂的是:

read callback 的触发时机。

内部核心流程:

服务端录音
    ↓
native protocol
    ↓
客户端接收数据
    ↓
写入 memblockq
    ↓
触发 read callback

因此:

它涉及:

  • Socket 通信
  • shm/memfd 共享内存
  • memblockq
  • 异步主循环
  • protocol-native

属于:

PulseAudio 录音链路中的核心异步机制。

🌻6. 一句话总结

pa_stream_set_read_callback
本质上是:

“给 PulseAudio 录音流安装数据到达监听器”。

它负责:

  • 接收录音数据
  • 驱动实时语音链路
  • 驱动 PCM 数据处理
  • 驱动 ASR/FFT/编码

是 PulseAudio 录音体系中的核心基础接口之一。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐