ALSA笔记

news2024/12/11 18:26:08

alsa笔记

ALSA(Advanced Linux Sound Architecture)简介

在这里插入图片描述
以上是android和linux系统的音频整体架构图,他们不同的区别主要是在用户空间,Linux通过ALSA-Lib来和ALSA交互,而android则是tingyAlsa,其位于aosp源码根目录的/external/tinyalsa下;

在Kernel层,Alsa向上封装的Driver驱动,通过向上暴露设备位于/dev/snd/目录的设备节点,提供交互
还有重要ALSA ASoc是ALSA的核心部分,它将音频系统分为Codec、Platform和Machine模块,并为每个模块提供相关的注册接口,协作各个模块,提供灵活的音频解决方案,除上面3个模块外,还有DAPM动态音频电源管理、pcm substream等音频数据处理。

hardware:包含platform、codec和machine,他们三者的关系如下图:
在这里插入图片描述
dai(Digital Audio Interfaces)表示数字音频接口,一种抽象的传递音频数据接口

Platform模块包含dma、cpu,其中dma允许外设(磁盘、网络接口)快速从内存中存取数据而不需要CPU处理,这里的cpu_dai相当于平台内部硬件资源,将音频数据取出来后,通过音频数字接口DAI,与Codec_dai进行数据收发;通常其相关的底层数字接口有i2s、pcm、tdm和S/PDIF等等,相关接口可参考数字音频接口,具有平台相关性

Codec模块通常与Platfrom模块的硬件是分开的,外接专门codec芯片,提供编解码、混音、DAC、ADC等等功能,此块驱动与平台无关,通过codec_dai与Platfrom的cpu_dai连接,用于数据收发,其传输协议根据cpu_dai的硬件能力来定,比如i2s、pcm、tdm等等

Machine模块则是将dma、cpu和codec三个dai连接在一起,形成一条通路,提供完整的音频数据收发功能;因为这三个dai,每个都可能存在1个或多个

ALSA源码通常位于:kernel/sound/目录下,其子目录soc是各个产商的驱动相关代码;子目录core与产商无关,通用代码Asoc core

cpu_dai通过数字接口dai与codec_dai连接,实际codec内部的编解码、ADC、DAC和音量控制等都是在外部DSP芯片中,但是codec_dai相关的驱动代码在平台侧,这块驱动也是通过I2S等接口与外部dsp芯片通信,传递寄存器地址和指令来执行外部dsp的功能;如AK7738、TAS6424、SAF7759等;但也有平台侧集成了外部audio dsp的功能,如Snapdragon 888、Jacinto 7 DRA829V等


ASoc Core通用结构体

通常在创建如如dma、cpu和codec的dai结构时,各个模块已定义了snd_soc_component_driver变量,他们在向alsa core注册自身时,会在core创建snd_soc_component,一一对应,建立连接,最后在将snd_soc_component加入到一个全局链表,后续需要的时候就从这个全局链表中去找,结构体拓扑图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3G6hjlP-1733753825327)(component.png)]

结构体如下:

//componet组件,可以理解有i2s、adma等component组件
struct snd_soc_component {
   
        const char *name;
        int id;
        const char *name_prefix;
        struct device *dev;
        struct snd_soc_card *card;

        unsigned int active;

        unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
        unsigned int registered_as_component:1;
        unsigned int suspended:1; /* is in suspend PM state */

        struct list_head list;
        struct list_head card_aux_list; /* for auxiliary bound components */
        struct list_head card_list;

        struct snd_soc_dai_driver *dai_drv;     //指向snd_soc_dai_driver,位于qcom-i2s.c中的qcom_i2s_dai_drv实例中,是cpu_dai
        int num_dai;

        const struct snd_soc_component_driver *driver;  //这个driver位于qcom-i2s.c中的qcom_i2s_component_drv实例中,

        /*dai_list保存的是snd_soc_componet的链表,比如当前的componet属于cpu,则这个dai_list对应的是cpu接口相关的snd_soc_dai,每个dai的支持的能力不一样,如单声道、多声道等*/
        struct list_head dai_list;

        int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);
        int (*write)(struct snd_soc_component *, unsigned int, unsigned int);

        struct regmap *regmap;
        int val_bytes;

        struct mutex io_mutex;

        /* attached dynamic objects */
        struct list_head dobj_list;

#ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_root;
#endif
        /*
        * DO NOT use any of the fields below in drivers, they are temporary and
        * are going to be removed again soon. If you use them in driver code the
        * driver will be marked as BROKEN when these fields are removed.
        */

        /* Don't use these, use snd_soc_component_get_dapm() */
        struct snd_soc_dapm_context dapm;               //这是实体不是指针

        struct snd_soc_codec *codec;            //指向codec结构体

        int (*probe)(struct snd_soc_component *);
        void (*remove)(struct snd_soc_component *);
        int (*suspend)(struct snd_soc_component *);
        int (*resume)(struct snd_soc_component *);

        int (*set_sysclk)(struct snd_soc_component *component,
                          int clk_id, int source, unsigned int freq, int dir);
        int (*set_pll)(struct snd_soc_component *component, int pll_id,
                       int source, unsigned int freq_in, unsigned int freq_out);
        int (*set_jack)(struct snd_soc_component *component,
                        struct snd_soc_jack *jack,  void *data);

        /* machine specific init */
        int (*init)(struct snd_soc_component *component);

#ifdef CONFIG_DEBUG_FS
        void (*init_debugfs)(struct snd_soc_component *component);
        const char *debugfs_prefix;
#endif
};

/* 每个component对应的driver,可以是i2s、adma */
struct snd_soc_component_driver {
   
        const char *name;

        /* Default control and setup, added after probe() is run */
        const struct snd_kcontrol_new *controls;
        unsigned int num_controls;
        const struct snd_soc_dapm_widget *dapm_widgets;
        unsigned int num_dapm_widgets;
        const struct snd_soc_dapm_route *dapm_routes;
        unsigned int num_dapm_routes;

        int (*probe)(struct snd_soc_component *);
        void (*remove)(struct snd_soc_component *);
        int (*suspend)(struct snd_soc_component *);
        int (*resume)(struct snd_soc_component *);

        /* component wide operations */
        int (*set_sysclk)(struct snd_soc_component *component,
                          int clk_id, int source, unsigned int freq, int dir);
        int (*set_pll)(struct snd_soc_component *component, int pll_id,
                       int source, unsigned int freq_in, unsigned int freq_out);
        int (*set_jack)(struct snd_soc_component *component,
                        struct snd_soc_jack *jack,  void *data);

        /* DT */
        int (*of_xlate_dai_name)(struct snd_soc_component *component,
                                 struct of_phandle_args *args,
                                 const char **dai_name);
        int (*of_xlate_dai_id)(struct snd_soc_component *comment,
                               struct device_node *endpoint);
        void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
                int subseq);
        int (*stream_event)(struct snd_soc_component *, int event);

        /* probe ordering - for components with runtime dependencies */
        int probe_order;        //系统启动有个order顺序,probe_order是当前结构体在某个order启动了
        int remove_order;
};
//kcontrol主要给用户空间提供可以访问控制音频codec芯片的多路开关接口或组件,如Mixer等
struct snd_kcontrol_new {
   
        snd_ctl_elem_iface_t iface;     /* interface identifier类型 */
        unsigned int device;            /* device/client number */
        unsigned int subdevice;         /* subdevice (substream) number */
        const unsigned char *name;      /* ASCII name of item */
        unsigned int index;             /* index of item 在声卡中的编号*/
        unsigned int access;            /* access rights 访问类型,按bit位来区分*/
        unsigned int count;             /* count of same elements */
        snd_kcontrol_info_t *info;
        snd_kcontrol_get_t *get;
        snd_kcontrol_put_t *put;
        union {
   
                snd_kcontrol_tlv_rw_t *c; 
                const unsigned int *p; 
        } tlv;
        unsigned long private_value; /*通过info、get和put可以访问该私有值,可以是一个soc_mixer_control*/
};

/*
 * Digital Audio Interface Driver.
 *
 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
 * operations and capabilities. Codec and platform drivers will register this
 * structure for every DAI they have.
 *
 * This structure covers the clocking, formating and ALSA operations for each
 * interface.
 */
struct snd_soc_dai_driver {
   
        /* DAI description */
        const char *name;
        unsigned int id; 
        unsigned int base;
        struct snd_soc_dobj dobj;

        /* DAI driver callbacks */
        int (*probe)(struct snd_soc_dai *dai);
        int (*remove)(struct snd_soc_dai *dai);
        int (*suspend)(struct snd_soc_dai *dai);
        int (*resume)(struct snd_soc_dai *dai);
        /* compress dai */
        int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
        /* Optional Callback used at pcm creation*/
        int (*pcm_new)(struct snd_soc_pcm_runtime *rtd,
                       struct snd_soc_dai *dai);
        /* DAI is also used for the control bus */
        bool bus_control;

        /* ops */
        const struct snd_soc_dai_ops *ops;
        const struct snd_soc_cdai_ops *cops;

        /* DAI capabilities */
        struct snd_soc_pcm_stream capture;
        struct snd_soc_pcm_stream playback;
        unsigned int symmetric_rates:1;
        unsigned int symmetric_channels:1;
        unsigned int symmetric_samplebits:1;

        /* probe ordering - for components with runtime dependencies */
        int probe_order;
        int remove_order;
};

struct snd_soc_dai_ops {
   
        /*
         * DAI clocking configuration, all optional.
         * Called by soc_card drivers, normally in their hw_params.
         */
        int (*set_sysclk)(struct snd_soc_dai *dai,
                int clk_id, unsigned int freq, int dir);
        int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
                unsigned int freq_in, unsigned int freq_out);
        int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
        int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio);

        /*
         * DAI format configuration
         * Called by soc_card drivers, normally in their hw_params.
         */
        int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
        int (*xlate_tdm_slot_mask)(unsigned int slots,
                unsigned int *tx_mask, unsigned int *rx_mask);
        int (*set_tdm_slot)(struct snd_soc_dai *dai,
                unsigned int tx_mask, unsigned int rx_mask,
                int slots, int slot_width);
        int (*set_channel_map)(struct snd_soc_dai *dai,
                unsigned int tx_num, unsigned int *tx_slot,
                unsigned int rx_num, unsigned int *rx_slot);
        int (*set_tristate)(struct snd_soc_dai *dai, int tristate);

        /*
         * DAI digital mute - optional.
         * Called by soc-core to minimise any pops.
         */
        int (*digital_mute)(struct snd_soc_dai *dai, int mute);
        int (*mute_stream)(struct snd_soc_dai *dai, int mute, int stream);

        /*
         * ALSA PCM audio operations - all optional.
         * Called by soc-core during audio PCM operations.
         */
        int (*startup)(struct snd_pcm_substream *,
                struct snd_soc_dai *);
        void (*shutdown)(struct snd_pcm_substream *,
                struct snd_soc_dai *);
        /*
         * NOTE: Commands passed to the trigger function are not necessarily
         * compatible with the current state of the dai. For example this
         * sequence of commands is possible: START STOP STOP.
         * So do not unconditionally use refcounting functions in the trigger
         * function, e.g. clk_enable/disable.
         */
        int (*trigger)(struct snd_pcm_substream *, int,
                struct snd_soc_dai *);
        int (*bespoke_trigger)(struct snd_pcm_substream *, int,
                struct snd_soc_dai *);
        /*
         * For hardware based FIFO caused delay reporting.
         * Optional.
         */
        snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
                struct snd_soc_dai *);
};

/*
 * Digital Audio Interface runtime data.
 *
 * Holds runtime data for a DAI., 位于snd_soc_pcm_runtime中codec_dais成员中
 */
struct snd_soc_dai {
   
        const char *name;                       //通常和snd_soc_dai_driver的name一致
        int id; 
        struct device *dev;

        /* driver ops */
        struct snd_soc_dai_driver *driver;

        /* DAI runtime info */
        unsigned int capture_active:1;          /* stream is in use */
        unsigned int playback_active:1;         /* stream is in use */
        unsigned int symmetric_rates:1;
        unsigned int symmetric_channels:1;
        unsigned int symmetric_samplebits:1;
        unsigned int probed:1;

        unsigned int active;

        struct snd_soc_dapm_widget *playback_widget;
        struct snd_soc_dapm_widget *capture_widget;

        /* DAI DMA data */
        void *playback_dma_data; //标记了从dma传输过来的数据类型,是单通道还是多通道等等
        void *capture_dma_data;

        /* Symmetry data - only valid if symmetry is being enforced */
        unsigned int rate;
        unsigned int channels;
        unsigned int sample_bits;

        /* parent platform/codec */
        struct snd_soc_codec *codec;
        struct snd_soc_component *component;

        /* CODEC TDM slot masks and params (for fixup) */
        unsigned int tx_mask;
        unsigned int rx_mask;

        struct list_head list;  //list_head用于链表,会加入到snd_soc_componet组件的list链表中去管理
};
电源管理结构体
/* dapm widget */
struct snd_soc_dapm_widget {
   
        enum s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2256906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哈希表实现

哈希概念 哈希(hash)又称散列,是一种组织数据的方式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字 Key 跟存储位置建立一个映射关系,查找时通过这个哈希函数计算出 Key 存储的位置,进行快…

web复习(四)

JavaScript编程 1.计算圆的面积。 (1)表单中设置2个文本框、1个按钮、1个重置按钮,其中圆的面积文本框设置为只读; (2)编写两个自定义函数,分别是计算圆的面积函数area(radius&…

第六届地博会世界酒中国菜助力广州龙美地标美食公司推动地标发展

第六届知交会暨地博会:世界酒中国菜助力广州龙美地标美食公司推动地标产品创新发展 2024年12月9日至11日,第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会在中新广州知识城盛大启幕。本届盛会吸引了全球众多知识产权领域的专业人士和…

【期末复习】编译原理

1. 语法描述 1.1. 上下文无关文法 1.2. 句子 & 句型 & 语言 推导出来的都是句型但是如果句型中只含有终结符,那就是句子所有的句子合起来,才是语言 1.3. 文法 文法就是推导的式子。 1.4. 文法二义性 1.5. 文法二义性证明——根据最左 \ 最右推…

AI绘画设计实战-Day2

Stable Diffusion 提示词前缀 FF,(masterpiece:1.2),best quality,highres,extremely detailed CG,perfect lighting,8k wallpaper,anime,comic,game CG, FF,(杰作:1.2),最高质量,高分辨率,极其…

python数据分析之爬虫基础:requests详解

1、requests基本使用 1.1、requests介绍 requests是python中一个常用于发送HTTP请求的第三方库,它极大地简化了web服务交互的过程。它是唯一的一个非转基因的python HTTP库,人类可以安全享用。 1.2、requests库的安装 pip install -i https://pypi.tu…

鸿雁电器发力,能否抢占康养卫浴新蓝海?

经济下行,叠加房地产行业的调整以及数智化浪潮的强劲推动,建材行业正面临着前所未有的变革与机遇。为了更好地把握行业趋势,求新求变,12月9日,鸿雁电器在青山湖园区鸿雁物联网大厦17楼鸿鹄厅成功举办了第四届“智创变革…

Scratch教学作品 | 3D飞行模拟器——体验飞行的无限乐趣! ✈️

今天为大家推荐一款令人惊叹的Scratch作品——《3D飞行模拟器》!由BamBozzle制作,这款游戏完全用Scratch构建,带你体验开放世界飞行的自由与乐趣。从起飞到降落,每一步都需要你的精准操作!更棒的是,这款游戏…

Linux服务器运维管理面板之1panel

华子目录 安装1panel使用卸载浏览器登录 安装 网站:https://community.fit2cloud.com/#/products/1panel/downloads 解压 [rootdocker-node1 ~]# tar -zxf 1panel-v1.10.13-lts-linux-amd64.tar.gz[rootdocker-node1 ~]# cd 1panel-v1.10.13-lts-linux-amd64/ [ro…

SpringBoot【二】yaml、properties两配置文件介绍及使用

一、前言 续上一篇咱们已经搭建好了一个springboot框架雏形。但是很多初学的小伙伴私信bug菌说,在开发项目中,为啥.yaml的配置文件也能配置,SpringBoot 是提供了两种2 种全局的配置文件嘛,这两种配置有何区别,能否给大…

学习笔记063——通过使用 aspose-words 将 Word 转 PDF 时,遇到的字体改变以及乱码问题

文章目录 1、问题描述:2、解决方法: 1、问题描述: Java项目中,有个需要将word转pdf的需求。本人通过使用aspose-words来转换的。在Windows中,转换是完全正常的。但是当部署到服务器时,会出现转换生成的pdf…

Linux下redis环境的搭建

1.redis的下载 redis官网下载redis的linux压缩包,官网地址:Redis下载 网盘链接: 通过网盘分享的文件:redis-5.0.4.tar.gz 链接: https://pan.baidu.com/s/1cz3ifYrDcHWZXmT1fNzBrQ?pwdehgj 提取码: ehgj 2.redis安装与配置 将包上传到 /…

帝可得-运营管理App

运营管理App Android模拟器 本项目的App客户端部分已经由前端团队进行开发完成,并且以apk的方式提供出来,供我们测试使用,如果要运行apk,需要先安装安卓的模拟器。 可以选择国内的安卓模拟器产品,比如:网…

用 Python 从零开始创建神经网络(十六):二元 Logistic 回归

二元 Logistic 回归 引言1. Sigmoid 激活函数2. Sigmoid 函数导数3. Sigmoid 函数代码4. 二元交叉熵损失(Binary Cross-Entropy Loss)5. 二元交叉熵损失导数(Binary Cross-Entropy Loss Derivative)6. 二进制交叉熵代码&#xff0…

高质量阅读微信小程序ssm+论文源码调试讲解

第2章 开发环境与技术 高质量阅读微信小程序的编码实现需要搭建一定的环境和使用相应的技术,接下来的内容就是对高质量阅读微信小程序用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的,是经常变动的&…

AI 学习框架:开启智能未来的钥匙

一、热门人工智能学习框架概述 人工智能学习框架在当今的科技发展中占据着至关重要的地位,它为开发者提供了强大的工具,有力地推动了人工智能的发展,同时也极大地降低了开发的难度。 人工智能学习框架是帮助开发者和研究人员快速构建、训练…

go-blueprint create exit status 1

1. 异常信息 2024/12/06 10:59:19 Could not initialize go.mod in new project exit status 1 2024/12/06 10:59:19 Problem creating files for project. exit status 1 Error: exit status 12. 排查思路 手动进行go mod init查看手动的报错解决报错 3. 解决问题 发现是GO11…

Python利用海龟画图turtle库做一个篮球比赛计时画面

Python利用海龟画图turtle库做一个篮球比赛计时画面,代码如下 import turtle import time import random r random.random() g random.random() b random.random() turtle.speed(0) for j in range(1,2,1):for i in range(1,60,1):print(i)time.sleep(0.1)turtl…

若依集成更好用的easyexcel

背景 若依使用的是apach poi并在此基础上进行封装apach poi的原生的api是很复杂的,若依简化了了此操作apach poi的上传速率和下载速率都是没有优化的,依赖于文件大小的限制在此前提下,如果没法满足客户的需求(超大型文件的上传&am…

代码随想录算法训练营day51|动态规划part13

回文子串 回文子串这里的递推式不太一样,dp[i] 和 dp[i-1] ,dp[i 1] 看上去都没啥关系。所以要回归到回文的定义 而我们发现,判断一个子字符串(字符串下标范围[i,j])是否回文,依赖于,子字符串…