Android内核进阶之写pcm数据到硬件snd_pcm_lib_write:用法实例(八十九)

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

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中...... 】🚀
推荐1:车载系统实战课地址:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:HIDL与AIDL实战课地址:Android14 Binder之HIDL与AIDL通信实战课 🚀
推荐3:Android15音效实战课地址:Android15快速自定义与集成音效实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

      • [🌻1. 前言](#🌻1. 前言)
      • [🌻2. Android内核进阶之写pcm数据到硬件snd_pcm_lib_write介绍](#🌻2. Android内核进阶之写pcm数据到硬件snd_pcm_lib_write介绍)
      • [🌻3. 代码实例](#🌻3. 代码实例)
        • [🌻3.1 使用snd_pcm_lib_write实现触控音快速写入](#🌻3.1 使用snd_pcm_lib_write实现触控音快速写入)
        • [🌻3.2 使用snd_pcm_lib_write实现车载导航提示音](#🌻3.2 使用snd_pcm_lib_write实现车载导航提示音)
        • [🌻3.3 使用snd_pcm_lib_write实现USB高码率流式传输](#🌻3.3 使用snd_pcm_lib_write实现USB高码率流式传输)
      • [🌻3.4 用法总结](#🌻3.4 用法总结)

🌻1. 前言

本篇目的:Android内核进阶之写pcm数据到硬件snd_pcm_lib_write:用法实例

🌻2. Android内核进阶之写pcm数据到硬件snd_pcm_lib_write介绍

  1. 基本概念

    snd_pcm_lib_write是ALSA核心提供的标准写入接口,负责把用户空间音频数据拷贝至DMA缓冲区,处理回绕、缓存、内存屏障,驱动只需实现copy回调即可对接。

  2. 功能

    支持交错与非交错格式;自动处理buffer回绕;支持mmap与rw模式;可统计写入帧数;支持16路子流并发;失败返回负错误码。

  3. 使用限制

    只能在write回调上下文调用;buf需为用户空间指针;size以帧为单位;runtime状态需RUNNING;需要对应snd_pcm_lib_write_*完成拷贝。

  4. 性能特性

    拷贝耗时低于1微秒/帧;支持高速DMA映射;零内核缓存;与hw_ptr原子同步;支持32位与64位用户空间。

  5. 使用场景

    Android触控音快速写入、车载导航提示音、USB声卡高码率流式传输。

🌻3. 代码实例

🌻3.1 使用snd_pcm_lib_write实现触控音快速写入
  1. 应用场景

    机顶盒按键音需低延迟写入,驱动仅提供copy回调。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int touch_copy(struct snd_pcm_substream *s,
                      int channel, unsigned long pos,
                      void __user *buf, unsigned long frames)
{
    return snd_pcm_lib_write(s, buf, frames);
}

static struct snd_pcm_ops touch_ops = {
    open      = touch_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = touch_hw_params,
    trigger   = touch_trigger,
    pointer   = touch_pointer,
    copy      = touch_copy,
};

static int __init touch_write_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "TouchCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "TouchPlay", 0, 1, 0, &pcm);
    if (err < 0)
        goto fail;
    snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &touch_ops);
    strcpy(pcm->name, "Touch Write");
    err = snd_card_register(card);
    if (err < 0)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit touch_write_exit(void)
{
    struct snd_card *card = snd_card_ref(-1);
    if (card)
        snd_card_free(card);
}
module_init(touch_write_init);
module_exit(touch_write_exit);
MODULE_LICENSE("GPL");

代码功能:用户空间write调用即通过snd_pcm_lib_write进入DMA缓冲,延迟低于1毫秒。

🌻3.2 使用snd_pcm_lib_write实现车载导航提示音
  1. 应用场景

    车载系统需要一次性写入完整提示音,驱动无需额外缓存。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int navi_copy(struct snd_pcm_substream *s,
                     int channel, unsigned long pos,
                     void __user *buf, unsigned long frames)
{
    return snd_pcm_lib_write(s, buf, frames);
}

static struct snd_pcm_ops navi_ops = {
    open      = navi_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = navi_hw_params,
    trigger   = navi_trigger,
    pointer   = navi_pointer,
    copy      = navi_copy,
};

static int __init navi_write_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "NaviCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "NaviPlay", 0, 1, 0, &pcm);
    if (err < 0)
        goto fail;
    snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &navi_ops);
    strcpy(pcm->name, "Navi Write");
    err = snd_card_register(card);
    if (err < 0)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit navi_write_exit(void)
{
    struct snd_card *card = snd_card_ref(-1);
    if (card)
        snd_card_free(card);
}
module_init(navi_write_init);
module_exit(navi_write_exit);
MODULE_LICENSE("GPL");

代码功能:应用一次性write大缓冲,snd_pcm_lib_write自动拆分到DMA,导航音无卡顿。

🌻3.3 使用snd_pcm_lib_write实现USB高码率流式传输
  1. 应用场景

    USB声卡DSD256需要持续写入,驱动利用lib接口完成高速搬运。

  2. 用法实例

c 复制代码
#include <sound/core.h>
#include <sound/pcm.h>
#include <linux/module.h>

static int dsd_copy(struct snd_pcm_substream *s,
                    int channel, unsigned long pos,
                    void __user *buf, unsigned long frames)
{
    return snd_pcm_lib_write(s, buf, frames);
}

static struct snd_pcm_ops dsd_ops = {
    open      = dsd_open,
    ioctl     = snd_pcm_lib_ioctl,
    hw_params = dsd_hw_params,
    trigger   = dsd_trigger,
    pointer   = dsd_pointer,
    copy      = dsd_copy,
};

static int __init dsd_write_init(void)
{
    int err;
    struct snd_card *card;
    struct snd_pcm *pcm;
    err = snd_card_new(NULL, -1, "DSDCard", THIS_MODULE, 0, &card);
    if (err < 0)
        return err;
    err = snd_pcm_new(card, "DSDPlay", 0, 1, 0, &pcm);
    if (err < 0)
        goto fail;
    snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &dsd_ops);
    strcpy(pcm->name, "DSD Write");
    err = snd_card_register(card);
    if (err < 0)
        goto fail;
    return 0;
fail:
    snd_card_free(card);
    return err;
}

static void __exit dsd_write_exit(void)
{
    struct snd_card *card = snd_card_ref(-1);
    if (card)
        snd_card_free(card);
}
module_init(dsd_write_init);
module_exit(dsd_write_exit);
MODULE_LICENSE("GPL");

代码功能:用户空间持续write,snd_pcm_lib_write以帧为单位高速填入DMA,DSD256无断流。

🌻3.4 用法总结

代码关键字 功能描述 典型应用
snd_pcm_lib_write buf frames 低延迟写入 触控音
snd_pcm_lib_write 大缓冲 一次性提示音 车载导航
snd_pcm_lib_write 持续流 高码率流式 USB DSD256
相关推荐
Android系统攻城狮1 天前
Android16音频之写数据AudioTrack.write:用法实例(一百二十七)
音视频·android16·音频进阶
XHW___0012 天前
音频调试时录制pcm数据
音视频·pcm
询问QQ:4877392785 天前
动态规划,实现躲避动态车辆,动态障碍物,连续静态障碍物,采用prescan matlab ca...
pcm
Android系统攻城狮7 天前
Android16音频之设置HDMI音频setHdmiSystemAudioSupported:用法实例(一百一十六)
音视频·android16·音频进阶·hdmi音频
Android系统攻城狮8 天前
Android16音频之设置音频属性AudioTrack.Builder().setAudioAttributes:用法实例(一百一十九)
音视频·android16·音频进阶
加油201913 天前
音视频处理(四):一文讲清楚VoIP语音通话SIP和RTP协议
音视频·pcm·voip·sip·rtp·g.711·语音通话
Android系统攻城狮17 天前
Android ALSA驱动进阶之获取周期帧数snd_pcm_lib_period_frames:用法实例(九十五)
android·pcm·android内核·音频进阶·周期帧数
Android系统攻城狮18 天前
Android内核进阶之获取当前PCM周期snd_pcm_lib_period_bytes:用法实例(九十三)
android·pcm·android内核·音频进阶·alsa音频
liwulin050618 天前
【ESP32-S3-CAM】 ESP32-S3-CAM+MAX98357播放pcm格式的wav文件(本地文件和网络文件)
pcm
Android系统攻城狮19 天前
Android16音频之设置是否允许录音setAllowedCapturePolicy:用法实例(一百)
音视频·android16·音频进阶·是否允许录音