当前位置: 首页 > news >正文

全志V3S嵌入式驱动开发(音频输出和音频录制)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        之前在芯片公司的时候,基本没有看过音频这一块,只知道有个alsa框架这么个知识点。要驱动音频,需要两部分,一部分就是底层驱动,一部分就是alsa上层接口,两者缺一不可。对于荔枝派来说,底层的驱动其实都已经包含在linux kernel里面了,客户只要自己port好一个alsa库,或者类alsa库,就可以开始播放音频、录制音频了。

1、电路

        电路分成两个部分,一个是mic,也就是麦克风,录制音频用,

         另外一个是headphone,也就是耳机,输出音频用,

        不管是哪一个电路,通过观察发现,电路中并没有音频电路经常出现的iis接口。这就说明,v3s和网卡一样,本身已经集成了数模转换和功放功能了,不需要额外芯片了。遇到这种情况,一般soc厂商都会自己默默把驱动代码准备好,省着使用者去二次开发了。毕竟都是自己的东西,驱动写起来也得心应手,不用外人劳神劳力了。

2、设备树

        本次使用的内核依然是linux-zero-4.14.y,顶层设备树是 sun8i-v3s-licheepi-zero-dock.dts。查看一下设备树的内容,可以发现声卡驱动已经集成到里面了,

&codec {allwinner,audio-routing ="Headphone", "HP","Headphone", "HPCOM","MIC1", "Mic","Mic",  "HBIAS";status = "okay";
};

        当然仅仅有这些还是不够的,进一步阅读sun8i-v3s.dtsi文件,可以看到codec的具体实现细节,

		codec: codec@01c22c00 {#sound-dai-cells = <0>;compatible = "allwinner,sun8i-v3s-codec";reg = <0x01c22c00 0x400>;interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;clock-names = "apb", "codec";resets = <&ccu RST_BUS_CODEC>;dmas = <&dma 15>, <&dma 15>;dma-names = "rx", "tx";allwinner,codec-analog-controls = <&codec_analog>;status = "disabled";};codec_analog: codec-analog@01c23000 {compatible = "allwinner,sun8i-v3s-codec-analog";reg = <0x01c23000 0x4>;};

        有了这两个配置,基本上声卡驱动就有保证了。好在这些都是默认配置,对于用户来说,就是什么都不需要做,系统上电后,声卡就已经加载好了。

3、判断声卡是否正确加载

        判断声卡有没有加载好,主要有两个办法。第一,就是看内核启动日志;第二,就是看/dev/snd下面的节点有没有正确生成。查看日志的话,如果启动ok,应该是可以看到这些打印的,

[    1.380188] sun4i-codec 1c22c00.codec: Codec <-> 1c22c00.codec mapping ok
[    1.388822] sun6i-rtc 1c20400.rtc: setting system clock to 1970-01-01 00:00:40 UTC (40)
[    1.397167] vcc5v0: disabling
[    1.400142] ALSA device list:
[    1.403106]   #0: V3s Audio Codec

        不放心日志的话,可以输入ls -l /dev/snd进一步确认下,

# ls -l /dev/snd
total 0
crw-------    1 root     root      116,   0 Jan  1 00:00 controlC0
crw-------    1 root     root      116,  24 Jan  1 00:00 pcmC0D0c
crw-------    1 root     root      116,  16 Jan  1 00:00 pcmC0D0p
crw-------    1 root     root      116,  33 Jan  1 00:00 timer

        另外,也可以查看下/sys/class/sound下面的节点,也可以算是一种方法,

# cd /sys/class/sound/
# ls
card0      controlC0  pcmC0D0c   pcmC0D0p   timer

        不管是哪一种方法,基本上看到这些打印或者节点信息,就可以认为声卡被系统正确加载了。

4、编译安装TinyAlsa

        前面我们说过,如果需要让声卡驱动起来,除了驱动本身之外,还需要一个alsa的库。TinyAlsa就是比较适合使用的那个库,下载位置在这,

https://github.com/tinyalsa/tinyalsa

        下载好压缩包之后,拷贝到ubuntu虚拟机,直接用arm-linux-gnueabihf-交叉编译器来编译。解压一下,接着cd到解压目录后,直接输入这个命令,

 make CROSS_COMPILE=arm-linux-gnueabihf-

        不出意外的话,在utils子目录下面,就可以看到四个编译好的工具,

tinycap
tinymix
tinypcminfo
tinyplay

        通过观察编译日志,发现这四个程序都是静态链接libtinyalsa.a,所以直接拷贝四个文件即可,不需要拷贝其他动态库。

make -C src
make[1]: Entering directory '/home/feixiaoxing/Desktop/tinyalsa-master/src'
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o limits.o limits.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o mixer.o mixer.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o pcm.o pcm.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o pcm_plugin.o pcm_plugin.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o pcm_hw.o pcm_hw.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o snd_card_plugin.o snd_card_plugin.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o mixer_plugin.o mixer_plugin.c
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC    -c -o mixer_hw.o mixer_hw.c
arm-linux-gnueabihf-ar rv libtinyalsa.a limits.o mixer.o pcm.o pcm_plugin.o pcm_hw.o snd_card_plugin.o mixer_plugin.o mixer_hw.o
arm-linux-gnueabihf-ar: creating libtinyalsa.a
a - limits.o
a - mixer.o
a - pcm.o
a - pcm_plugin.o
a - pcm_hw.o
a - snd_card_plugin.o
a - mixer_plugin.o
a - mixer_hw.o
arm-linux-gnueabihf-gcc  -shared -Wl,-soname,libtinyalsa.so.2 limits.o mixer.o pcm.o pcm_plugin.o pcm_hw.o snd_card_plugin.o mixer_plugin.o mixer_hw.o -o libtinyalsa.so.2.0.0
ln -sf libtinyalsa.so.2.0.0 libtinyalsa.so.2
ln -sf libtinyalsa.so.2 libtinyalsa.so
make[1]: Leaving directory '/home/feixiaoxing/Desktop/tinyalsa-master/src'
make -C utils
make[1]: Entering directory '/home/feixiaoxing/Desktop/tinyalsa-master/utils'
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC -O2   -c -o tinyplay.o tinyplay.c
arm-linux-gnueabihf-gcc -L ../src -pie  tinyplay.o ../src/libtinyalsa.a  -ldl -o tinyplay
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC -O2   -c -o tinycap.o tinycap.c
arm-linux-gnueabihf-gcc -L ../src -pie  tinycap.o ../src/libtinyalsa.a  -ldl -o tinycap
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC -O2   -c -o tinymix.o tinymix.c
arm-linux-gnueabihf-gcc -L ../src -pie  tinymix.o ../src/libtinyalsa.a  -ldl -o tinymix
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include -fPIC -O2   -c -o tinypcminfo.o tinypcminfo.c
arm-linux-gnueabihf-gcc -L ../src -pie  tinypcminfo.o ../src/libtinyalsa.a  -ldl -o tinypcminfo
make[1]: Leaving directory '/home/feixiaoxing/Desktop/tinyalsa-master/utils'
make -C doxygen
make[1]: Entering directory '/home/feixiaoxing/Desktop/tinyalsa-master/doxygen'
Makefile:11: "doxygen is not available please install it"
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/feixiaoxing/Desktop/tinyalsa-master/doxygen'
make -C examples
make[1]: Entering directory '/home/feixiaoxing/Desktop/tinyalsa-master/examples'
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include    pcm-readi.c ../src/libtinyalsa.so  -ldl -o pcm-readi
arm-linux-gnueabihf-gcc -Wall -Wextra -Werror -Wfatal-errors -I ../include    pcm-writei.c ../src/libtinyalsa.so  -ldl -o pcm-writei
make[1]: Leaving directory '/home/feixiaoxing/Desktop/tinyalsa-master/examples'

        如何把四个文件拷贝到开发板,这个就不再赘述了。主要还是使用python http库和开发板上的wget命令来共同完成的。

5、寻找音频文件

        目前,tinyalsa的工具只能播放wav文件,所以我们还需要找一个可以下载wav文件的网站。这里推荐一个网站链接给大家,

https://www.xmwav.com/

        下载好音频文件之后,还是用同样的方法下载到开发板上面。

6、播放音频和录制音频

6.1 播放音频

        播放音频的时候,除了正常插入耳机,还有三个地方需要注意下,不然听不到音频输出。第一,就是打开播放开关;第二,设置音量;第三,确认下前面的设置有没有对。这三个步骤都做完了,就可以播放音频了。设置命令主要是tinymix,播放命令是tinyplay。

# ./tinymix set 1 40
# ./tinymix set 2 1
# ./tinymix contents
Number of controls: 13
ctl	type	num	name                                    value
0	INT	1	DAC Playback Volume                     63 (range 0->63)
1	INT	1	Headphone Playback Volume               40 (range 0->63)
2	BOOL	2	Headphone Playback Switch               On, Off
3	INT	1	Mic1 Playback Volume                    3 (range 0->7)
4	INT	1	Mic1 Boost Volume                       4 (range 0->7)
5	INT	1	ADC Gain Capture Volume                 3 (range 0->7)
6	BOOL	2	DAC Playback Switch                     Off, Off
7	BOOL	2	DAC Reversed Playback Switch            Off, Off
8	BOOL	2	Mic1 Playback Switch                    Off, Off
9	BOOL	2	Mixer Capture Switch                    Off, Off
10	BOOL	2	Mixer Reversed Capture Switch           Off, Off
11	BOOL	2	Mic1 Capture Switch                     Off, Off
12	ENUM	2	Headphone Source Playback Route         > DAC, Mixer, , > DAC, Mixer, 

        播放刚才下载的音频,

# ./tinyplay  test.wav 
playing 'test.wav': 2 ch, 44100 hz, 16-bit signed PCM

6.2 录制音频

        录制音频和播放音频差不多。第一步打开录制开关,第二步确认配置ok。前两步都做好了之后,就可以用tinycap录制音频了,结束录制用ctrl+c,

# ./tinymix set 11 1
# ./tinymix contents
Number of controls: 13
ctl	type	num	name                                    value
0	INT	1	DAC Playback Volume                     63 (range 0->63)
1	INT	1	Headphone Playback Volume               40 (range 0->63)
2	BOOL	2	Headphone Playback Switch               On, Off
3	INT	1	Mic1 Playback Volume                    3 (range 0->7)
4	INT	1	Mic1 Boost Volume                       4 (range 0->7)
5	INT	1	ADC Gain Capture Volume                 3 (range 0->7)
6	BOOL	2	DAC Playback Switch                     Off, Off
7	BOOL	2	DAC Reversed Playback Switch            Off, Off
8	BOOL	2	Mic1 Playback Switch                    Off, Off
9	BOOL	2	Mixer Capture Switch                    Off, Off
10	BOOL	2	Mixer Reversed Capture Switch           Off, Off
11	BOOL	2	Mic1 Capture Switch                     On, Off
12	ENUM	2	Headphone Source Playback Route         > DAC, Mixer, , > DAC, Mixer, 
# ./tinycap record.wav
Capturing sample: 2 ch, 48000 hz, 16 bit

        如果想要确认录制的音频有没有问题,那么直接用tinyplay播放下即可,

# ./tinyplay record.wav 
playing 'record.wav': 2 ch, 48000 hz, 16-bit signed PCM
Played 1601536 bytes. Remains 0 bytes.

相关文章:

全志V3S嵌入式驱动开发(音频输出和音频录制)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前在芯片公司的时候&#xff0c;基本没有看过音频这一块&#xff0c;只知道有个alsa框架这么个知识点。要驱动音频&#xff0c;需要两部分&#…...

使用RP2040自制的树莓派pico—— [2/100] HelloWorld! 和 点亮LED

使用RP2040自制的树莓派pico—— [2/100] HelloWorld! 和 点亮LED 开发环境HelloWorld!闪烁 LED 灯代码 由于比较简单就放在一起写了 开发环境 软件&#xff1a;Thonny HelloWorld! 要想使串口打印HelloWorld&#xff01; 只需要一行代码 print("HelloWorld!")保…...

康耐视In-Sight2800相机的使用

In-Sight2800相机注册分类程序 一、登录相机 二、图像导入 IS相机支持拍摄图像和从文件中导入图像 如选择从文件中导入图像&#xff0c;文件夹选择位置在页面左下方&#xff0c;如下图 三、注册分类器 在检查模块注册分类器&#xff0c;注册图像需要一张一张去学习&#x…...

驱动开发:内核封装WFP防火墙入门

WFP框架是微软推出来替代TDIHOOK传输层驱动接口网络通信的方案&#xff0c;其默认被设计为分层结构&#xff0c;该框架分别提供了用户态与内核态相同的AIP函数&#xff0c;在两种模式下均可以开发防火墙产品&#xff0c;以下代码我实现了一个简单的驱动过滤防火墙。 WFP 框架分…...

python+vue校园快递代取系统的设计与实现3i0v9

开发语言&#xff1a;Python 框架&#xff1a;django/flask Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm 本系统名为“基于vue快递代取系统”&#xff0c;系统主要适用于毕业设计&#xff0c;不…...

C 语言详细教程

目录 第一章 C语言基础知识 第二章 数据类型、运算符和表达式 第三章 结构化程序设计 第四章 数组 第五章 函数 第六章 指针 第七章 结构体类型和自定义类型 第八章 编译预处理 第九章 文件 说明&#xff1a;本教程中的代码除一二三个之外&#xff0c;都在https://ligh…...

函数重载与缺省参数

目录 一 缺省参数 缺省参数分半缺省和全缺省。 2&#xff0c;半缺省参数 3&#xff0c;全缺省参数 4.缺省参数的注意事项 二 函数重载 2 .函数重载参数类型不同强调 三 函数名修饰规则 一 缺省参数 1.缺省参数特性(备胎) 缺省参数是指我们定义函数时有给缺省值的参数&#xf…...

线程引入的开销

单线程程序既不存在线程调度&#xff0c;也不存在同步开销&#xff0c;而且不需要使用锁来保证数据结构的一致性。在多个线程的调度和协调过程中都需要一定的性能开销&#xff1a;对于为了提升性能而引入的线程来说&#xff0c;并行带来的性能提升必须超过并发导致的开销。 上下…...

学生成绩管理系统

基于springboot vue实现的学生成绩管理系统 主要模块&#xff1a; 1&#xff09;学生模块&#xff1a;我的成绩、成绩统计、申述管理、修改密码 2&#xff09;教师模块&#xff1a;任务管理、对学生班级任务安排、班级学生的成绩查看、申述管理 3&#xff09;管理员模块&…...

什么是关系模型? 关系模型的基本概念

关系模型由IBM公司研究员Edgar Frank Codd于1970年发表的论文中提出&#xff0c;经过多年的发展&#xff0c;已经成为目前最常用、最重要的模型之一。 在关系模型中有一些基本的概念&#xff0c;具体如下。 (1)关系(Relation)。关系一词与数学领域有关&#xff0c;它是集合基…...

shell编程-02-变量作用域

作用域 局部变量&#xff1a;变量只能在函数内部使用 全局变量&#xff1a;变量可以在当前 Shell 进程中使用 环境变量&#xff1a;变量还可以在子进程中使用 局部变量 函数中定义的变量默认是全局变量&#xff0c;在定义时加上local命令&#xff0c;此时该变量就成了局部变…...

C++服务器框架开发6——日志系统LogFormatter/size_t学习

该专栏记录了在学习一个开发项目的过程中遇到的疑惑和问题。 其教学视频见&#xff1a;[C高级教程]从零开始开发服务器框架(sylar) 上一篇&#xff1a;C服务器框架开发5——日志系统LogAppender/IO类“3种stream”/双感叹号 C服务器框架开发6——日志系统logFormatter/size_t学…...

MYSQL实战45讲笔记--深入浅出索引

深入浅出索引 索引的常见模型 索引模型&#xff1a;是哈希表、有序数组和搜索树。 区别&#xff1a; 哈希表是一种以键 - 值&#xff08;key-value&#xff09;存储数据的结构&#xff0c;我们只要输入待查找的值即 key&#xff0c;就可以找到其对应的值即 Value。哈希的思…...

SpringCloudAlibaba:分布式事务之Seata学习

目录 一、分布式事务基础 &#xff08;一&#xff09;事务 &#xff08;二&#xff09;本地事务 &#xff08;三&#xff09;分布式事务 二、Seata概述 1.Seata 的架构包含: 2.其工作原理为: 3.如果需要在 Spring Boot 应用中使用 Seata 进行分布式事务管理,主要步骤为…...

【MySQL数据库 | 第四篇】SQL通用语法及分类

目录 &#x1f914;SQL通用语法&#xff1a; &#x1f60a;语句&#xff1a; &#x1f60a;注释&#xff1a; &#x1f914;SQL语句分类&#xff1a; &#x1f60a;1.DDL语句&#xff1a; &#x1f60a;2.DML语句&#xff1a; &#x1f60a;3.DQL语言&#xff1a; &…...

Liskov替换原则:用了继承,子类就设计对了吗?

前言 上一篇&#xff0c;我们讲了开放封闭原则&#xff0c;想要让系统符合开放封闭原则&#xff0c;最重要的就是我们要构建起相应的扩展模型&#xff0c;所以&#xff0c;我们要面向接口编程。 而大部分的面向接口编程要依赖于继承实现&#xff0c;继承的重要性不如封装和多…...

腾讯云服务器SA3实例AMD处理器CPU网络带宽性能详解

腾讯云AMD服务器SA3实例CPU采用2.55GHz主频的AMD EPYCTM Milan处理器&#xff0c;睿频3.5GHz&#xff0c;搭载最新一代八通道DDR4&#xff0c;内存计算性能稳定&#xff0c;默认网络优化&#xff0c;最高内网收发能力达1900万pps&#xff0c;最高内网带宽可支持100Gbps。腾讯云…...

接口测试常用测试点

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 测试的策略&#xff1a; 接口测试也是属于功…...

Unity之OpenXR+XR Interaction Toolkit接入HTC Vive解决手柄无法使用的问题

前言 随着Unity版本的不断进化,VR的接口逐渐统一,现在大部分的VR项目都开始使用OpenXR开发了。基于OpenXR,我们可以快速适配HTC,Pico,Oculus,等等设备。 今天我们要说的问题就是,当我们按照官方的标准流程配置完OpenXR后(参考:Unity之OpenXR+XR Interaction Toolkit…...

AC变DC220V变5V小家电电源芯片-AH8652、AH8669

Q: 什么是AH8652和AH8669电源芯片? A: AH8652和AH8669都是AC变DC的电源芯片&#xff0c;适用于将输入的交流电压&#xff08;220V&#xff09;转换为5V直流电压输出&#xff0c;用于小家电的电源模块等应用。 AC变DC220V变5V小家电电源芯片-AH8669 Q: AH8652和AH8669的最大输…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇

根据 QYResearch 发布的市场报告显示&#xff0c;全球市场规模预计在 2031 年达到 9848 万美元&#xff0c;2025 - 2031 年期间年复合增长率&#xff08;CAGR&#xff09;为 3.7%。在竞争格局上&#xff0c;市场集中度较高&#xff0c;2024 年全球前十强厂商占据约 74.0% 的市场…...