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

audio policy config xml解析过程

一、获取xml文件1.启动audioserviceframeworks/av/media/audioserver/main_audioserver.cpp //main函数中定义一个对象 const auto aps spAudioPolicyService::make();2.执行构造函数并mCreateAudioPolicyManager(createAudioPolicyManager)进行初始化frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp AudioPolicyService::AudioPolicyService()3.调用void AudioPolicyService::onFirstRef()函数void AudioPolicyService::onFirstRef() { ...... mAudioPolicyManager mCreateAudioPolicyManager(mAudioPolicyClient); ...... }4.解析配置文件audio policy config xmlstatic AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) { AudioPolicyManager *apm nullptr; media::AudioPolicyConfig apmConfig; if (status_t status clientInterface-getAudioPolicyConfig(apmConfig); status OK) { ...... } else { auto config AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This cant fail.解析配置文件audio policy config xml ...... } }spconst AudioPolicyConfig AudioPolicyConfig::loadFromApmXmlConfigWithFallback( const std::string xmlFilePath) { const std::string filePath xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;//获取xml文件 auto config spAudioPolicyConfig::make(); if (status_t status config-loadFromXml(filePath, false /*forVts*/); status NO_ERROR) { return config; } return createDefault(); }static inline std::string audio_get_audio_policy_config_file() { static constexpr const char *apmXmlConfigFileName audio_policy_configuration.xml; static constexpr const char *apmA2dpOffloadDisabledXmlConfigFileName audio_policy_configuration_a2dp_offload_disabled.xml; static constexpr const char *apmLeOffloadDisabledXmlConfigFileName audio_policy_configuration_le_offload_disabled.xml; static constexpr const char *apmBluetoothLegacyHalXmlConfigFileName audio_policy_configuration_bluetooth_legacy_hal.xml; std::string audioPolicyXmlConfigFile; // First try alternative files if needed if (property_get_bool(ro.bluetooth.a2dp_offload.supported, false)) { if (property_get_bool(persist.bluetooth.bluetooth_audio_hal.disabled, false) property_get_bool(persist.bluetooth.a2dp_offload.disabled, false)) { // Both BluetoothAudio2.0 and BluetoothA2dp1.0 (Offload) are disabled, and uses // the legacy hardware module for A2DP and hearing aid. audioPolicyXmlConfigFile audio_find_readable_configuration_file( apmBluetoothLegacyHalXmlConfigFileName); } else if (property_get_bool(persist.bluetooth.a2dp_offload.disabled, false)) { // A2DP offload supported but disabled: try to use special XML file // assume that if a2dp offload is not supported, le offload is not supported as well audioPolicyXmlConfigFile audio_find_readable_configuration_file( apmA2dpOffloadDisabledXmlConfigFileName); } else if (!property_get_bool(ro.bluetooth.leaudio_offload.supported, false) || property_get_bool(persist.bluetooth.leaudio_offload.disabled, false)) { // A2DP offload supported but LE offload disabled: try to use special XML file audioPolicyXmlConfigFile audio_find_readable_configuration_file( apmLeOffloadDisabledXmlConfigFileName); } } else if (property_get_bool(persist.bluetooth.bluetooth_audio_hal.disabled, false)) { audioPolicyXmlConfigFile audio_find_readable_configuration_file( apmBluetoothLegacyHalXmlConfigFileName); } else { audioPolicyXmlConfigFile audio_find_readable_configuration_file( apmA2dpOffloadDisabledXmlConfigFileName); } return audioPolicyXmlConfigFile.empty() ? audio_find_readable_configuration_file(apmXmlConfigFileName) : audioPolicyXmlConfigFile; } }static inline std::string audio_find_readable_configuration_file(const char* fileName) { for (const auto path : audio_get_configuration_paths()) { std::string tryPath path / fileName; if (audio_is_readable_configuration_file(tryPath.c_str())) { return tryPath; } } return {}; }//最后加载vendor/etc/audio_policy_configuration.xml,具体是哪个路径根据代码而定5.回到createAudioPolicyManager函数apm new AudioPolicyManager(config, loadApmEngineLibraryAndCreateEngine(config-getEngineLibraryNameSuffix()), clientInterface);//最终加载/vendor/etc/audio_policy_engine_configuration.xml有的平台会客制化这部分二、解析xml1.入口deserializeAudioPolicyFile函数此时的filename为audio_policy_configuration.xml//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config) { PolicySerializer serializer; status_t status serializer.deserialize(fileName, config); return status; }2.调用deserialize解析xml把xml的节点都解析出来auto doc make_xmlUnique(xmlParseFile(configFile));//解析 XML 文件 (libxml2)3. 获取xml根节点xmlNodePtr root xmlDocGetRootElement(doc.get());4.解析include xml文件xmlXIncludeProcess(doc.get())//比如xi:include hrefprimary_audio_policy_configuration.xml/5.验证根元素和版本xmlStrcmp(root-name, reinterpret_castconst xmlChar*(rootName));//rootname audioPolicyConfiguration std::string version getXmlAttribute(root, versionAttribute);//versionAttribute version6.开始解析modulesstatus_t status deserializeCollectionModuleTraits(root, modules, config);//传入的是modules7.看deserializeCollection函数for (cur cur-xmlChildrenNode; cur ! NULL; cur cur-next) {//遍历之前解析xml的节点比如modulesglobalConfiguration等 const xmlNode *child NULL; if (!xmlStrcmp(cur-name, reinterpret_castconst xmlChar*(Trait::collectionTag))) {//与collectionTag相比较判断是否是modules child cur-xmlChildrenNode; } else if (!xmlStrcmp(cur-name, reinterpret_castconst xmlChar*(Trait::tag))) { child cur; } for (; child ! NULL; child child-next) {//遍历modules下的节点 if (!xmlStrcmp(child-name, reinterpret_castconst xmlChar*(Trait::tag))) {//与tag相比较即判断是否是module如果是则继续往下走 auto maybeElement deserializeTrait(child, serializingContext); if (maybeElement.index() 1) { status_t status Trait::addElementToCollection( std::get1(maybeElement), collection); if (status ! NO_ERROR) { ALOGE(%s: could not add element to %s collection, __func__, Trait::collectionTag); return status; } } else if (mIgnoreVendorExtensions std::getstatus_t(maybeElement) NO_INIT) { // Skip a vendor extension element. } else { return BAD_VALUE; } } }8.继续看deserialize文件此时是module模块的则调用module模块的deserialize函数template std::variantstatus_t, ModuleTraits::Element PolicySerializer::deserializeModuleTraits( const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx) { using Attributes ModuleTraits::Attributes; auto tag ModuleTraits::tag; auto childAttachedDevicesTag ModuleTraits::childAttachedDevicesTag; auto childAttachedDeviceTag ModuleTraits::childAttachedDeviceTag; auto childDefaultOutputDeviceTag ModuleTraits::childDefaultOutputDeviceTag; std::string name getXmlAttribute(cur, Attributes::name);//获取属性name的值即为primary if (name.empty()) { ALOGE(%s: No %s found, __func__, Attributes::name); return BAD_VALUE; } uint32_t versionMajor 0, versionMinor 0; std::string versionLiteral getXmlAttribute(cur, Attributes::version);//获取属性halVersion的值即为2.0 if (!versionLiteral.empty()) { sscanf(versionLiteral.c_str(), %u.%u, versionMajor, versionMinor); ALOGV(%s: mHalVersion major %u minor %u, __func__, versionMajor, versionMajor); } ALOGD(%s: %s %s%s, __func__, ModuleTraits::tag, Attributes::name, name.c_str()); ModuleTraits::Element module new HwModule(name.c_str(), versionMajor, versionMinor); // Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes MixPortTraits::Collection mixPorts; status_t status deserializeCollectionMixPortTraits(cur, mixPorts, NULL);//解析mixPorts参数 if (status ! NO_ERROR) { return status; } module-setProfiles(mixPorts); DevicePortTraits::Collection devicePorts; status deserializeCollectionDevicePortTraits(cur, devicePorts, NULL); if (status ! NO_ERROR) { return status; } module-setDeclaredDevices(devicePorts); RouteTraits::Collection routes; status deserializeCollectionRouteTraits(cur, routes, module.get()); if (status ! NO_ERROR) { return status; } module-setRoutes(routes); for (const xmlNode *children cur-xmlChildrenNode; children ! NULL; children children-next) { if (!xmlStrcmp(children-name, reinterpret_castconst xmlChar*(childAttachedDevicesTag))) { ALOGD(%s: %s %s found, __func__, tag, childAttachedDevicesTag); for (const xmlNode *child children-xmlChildrenNode; child ! NULL; child child-next) { if (!xmlStrcmp(child-name, reinterpret_castconst xmlChar*(childAttachedDeviceTag))) { //MIUI ADD: Audio_DecoupledMtk #ifdef XIAOMI_PLATFORM_MTK if (xmlNodeListGetString(child-doc, child-xmlChildrenNode, 1) nullptr) { //MTK_AUDIO ALOGW(%s: 1.Get Null string, __func__); continue; } #endif //END Audio_DecoupledMtk auto attachedDevice make_xmlUnique(xmlNodeListGetString( child-doc, child-xmlChildrenNode, 1)); if (attachedDevice ! nullptr) { ALOGD(%s: %s %s%s, __func__, tag, childAttachedDeviceTag, reinterpret_castconst char*(attachedDevice.get())); spDeviceDescriptor device module-getDeclaredDevices(). getDeviceFromTagName(std::string(reinterpret_castconst char*( attachedDevice.get()))); if (device NULL) { if (mIgnoreVendorExtensions) { ALOGD(%s: skipped attached device \%s\ because it likely uses a vendor extension type, __func__, reinterpret_castconst char*(attachedDevice.get())); } else { ALOGE(%s: got null device in %s, \%s\, __func__, child-name, reinterpret_castconst char*(attachedDevice.get())); } continue; } ctx-addDevice(device); } } } } if (!xmlStrcmp(children-name, reinterpret_castconst xmlChar*(childDefaultOutputDeviceTag))) { //MIUI ADD: Audio_DecoupledMtk #ifdef XIAOMI_PLATFORM_MTK if (xmlNodeListGetString(children-doc, children-xmlChildrenNode, 1) nullptr) { //MTK_AUDIO ALOGW(%s: 2.Get Null string, __func__); continue; } #endif //END Audio_DecoupledMtk auto defaultOutputDevice make_xmlUnique(xmlNodeListGetString( children-doc, children-xmlChildrenNode, 1)); if (defaultOutputDevice ! nullptr) { ALOGD(%s: %s %s%s, __func__, tag, childDefaultOutputDeviceTag, reinterpret_castconst char*(defaultOutputDevice.get())); spDeviceDescriptor device module-getDeclaredDevices().getDeviceFromTagName( std::string(reinterpret_castconst char*(defaultOutputDevice.get()))); if (device ! 0 ctx-getDefaultOutputDevice() 0) { ctx-setDefaultOutputDevice(device); ALOGD(%s: default is %08x, __func__, ctx-getDefaultOutputDevice()-type()); } } } } return module; }9.看deserializeCollection函数此时解析的是mixportsmixPorts mixPort nameprimary output rolesource flagsAUDIO_OUTPUT_FLAG_PRIMARY profile name formatAUDIO_FORMAT_PCM_16_BIT samplingRates48000 channelMasksAUDIO_CHANNEL_OUT_STEREO/ /mixPort mixPortsfor (cur cur-xmlChildrenNode; cur ! NULL; cur cur-next) {//遍历mixports const xmlNode *child NULL; if (!xmlStrcmp(cur-name, reinterpret_castconst xmlChar*(Trait::collectionTag))) {//与collectionTag相比较判断是否是mixports child cur-xmlChildrenNode; } else if (!xmlStrcmp(cur-name, reinterpret_castconst xmlChar*(Trait::tag))) { child cur; } for (; child ! NULL; child child-next) {//遍历mixports下的节点 if (!xmlStrcmp(child-name, reinterpret_castconst xmlChar*(Trait::tag))) {//与tag相比较即判断是否是mixport如果是则继续往下走 auto maybeElement deserializeTrait(child, serializingContext); if (maybeElement.index() 1) { status_t status Trait::addElementToCollection( std::get1(maybeElement), collection); if (status ! NO_ERROR) { ALOGE(%s: could not add element to %s collection, __func__, Trait::collectionTag); return status; } } else if (mIgnoreVendorExtensions std::getstatus_t(maybeElement) NO_INIT) { // Skip a vendor extension element. } else { return BAD_VALUE; } } }

相关文章:

audio policy config xml解析过程

一、获取xml文件1.启动audioserviceframeworks/av/media/audioserver/main_audioserver.cpp //main函数中定义一个对象&#xff1a; const auto aps sp<AudioPolicyService>::make();2.执行构造函数并mCreateAudioPolicyManager(createAudioPolicyManager)进行初始化fra…...

《AI Agent生产力部署指南:OpenClaw + vLLM 本地化实战——(三)OpenClaw与LLM工具链适配》

上一章节中我们完整介绍了如何在服务器中配置vLLM服务,如何运行vLLM,以及如何搭建本地机器作为中间跳转连接虚拟机与服务器的通信。 本章第五节完成最后一个步骤对openclaw的相关配置,让本地能成功对话虚拟机,虚拟机成功调用服务器模型。 下面直接开始吧! (五)配置ope…...

PRD文档模板

xxxxxx 需求规格说明书 南京市xxx信息服务有限公司 修订记录 版本号 修订日期 修订人 修订描述 V1.0 20190203 xxxxx 初稿 一、概述 1.1需求背景 说明需求背景&#xff0c;为什么要做该需求&#xff0c;主要是为了解决什么问题等 背景举例&#xff1a;目前…...

需求用例的写法

一、为什么写需求用例 流程图为需求用例提供了关键路径&#xff0c;而需求用例则是对业务场景的全面还原。本文将从以下四个方面阐述用例的信息&#xff1a; 用例的定义用例的粒度用例的例子用例的关键点解释 我写需求文档有几大准则&#xff0c;是需要时刻铭记和实践的&…...

Windows下OpenClaw全攻略:Qwen3-14B镜像接入与自动化测试

Windows下OpenClaw全攻略&#xff1a;Qwen3-14B镜像接入与自动化测试 1. 为什么选择WindowsOpenClaw组合 去年我在尝试自动化办公流程时&#xff0c;发现Mac环境下的OpenClaw虽然安装便捷&#xff0c;但团队里多数同事仍在使用Windows系统。为了让这套工具真正落地&#xff0…...

这个免费AI工具太狠了:我每周省下10小时学习时间

这个免费AI工具太狠了&#xff1a;我每周省下10小时学习时间 改写自 The PyCoach 于 2026 年 3 月 20 日发布的文章《NotebookLM: The Best AI Tool to Learn Any Topic Faster》&#xff0c;并参考 Diana Dovgopol 的共同观点。 很多人以为&#xff0c;学习慢&#xff0c;是因…...

WiFiEspAT:基于AT指令的嵌入式Wi-Fi协处理器适配库

1. 项目概述WiFiEspAT 是一个面向嵌入式系统的轻量级、高可靠性网络适配层库&#xff0c;其核心目标是将 ESP8266 或 ESP32 模块作为独立的 Wi-Fi 网络协处理器&#xff08;Network Coprocessor&#xff09;&#xff0c;通过标准 AT 指令集与主控 MCU&#xff08;如 AVR、ARM C…...

IEEE/ASME Transactions on Mechatronics | 院士团队让移动机器人在复杂环境中学会主动避障

论文信息 英文题目&#xff1a; Vector Field Augmented Reinforcement Learning for Adaptive Motion Planning of Mobile Robots 中文题目&#xff1a;面向移动机器人自适应运动规划的向量场增强强化学习 作者&#xff1a; Yang Lu, Weijia Yao, Cong Li, Yongqian Xia…...

DigitLed72xx库:工业级MAX7219/7221数码管驱动方案

1. DigitLed72xx 库概述&#xff1a;面向工业级 LED 显示控制的嵌入式驱动框架DigitLed72xx 是一款专为 MAX7219 和 MAX7221 七段数码管显示驱动芯片设计的轻量级、高可靠性嵌入式 C 库。该库并非简单的 Arduino 封装&#xff0c;其底层架构深度适配硬件 SPI 外设&#xff0c;支…...

【2026年最新600套毕设项目分享】基于微信小程序的科创微应用平台(30012)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告/任务书&#xff09;远程调试控屏包运行一键启动项目&…...

【2026年最新600套毕设项目分享】微信小程序的医院核酸检测服务系统(30011)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告/任务书&#xff09;远程调试控屏包运行一键启动项目&…...

2025_NIPS_CRRL: Learning Channel-invariant Neural Representations for High-performance Cross-day ...

文章核心总结 本文提出CRRL(Channel Rearrangement and Reconstruction Learning)框架,用于解决脑机接口(BCI)跨天解码中神经信号的通道级变异性问题,实现长期稳定解码。核心创新在于通过两个专用模块分别处理神经元丢失/新增、电极漂移两类变异,在多数据集上达成超两个…...

AI+声学:当物理规律遇见神经网络,如何颠覆传统模拟?

AI声学&#xff1a;当物理规律遇见神经网络&#xff0c;如何颠覆传统模拟&#xff1f; 引言 想象一下&#xff0c;模拟一个大型音乐厅的声场分布&#xff0c;传统方法可能需要超级计算机数小时的计算&#xff0c;而AI模型仅需秒级响应。这并非科幻&#xff0c;而是“AI for Sci…...

AI+电磁:当计算电磁学遇上人工智能,一场效率革命正在发生

AI电磁&#xff1a;当计算电磁学遇上人工智能&#xff0c;一场效率革命正在发生 引言 在6G通信、新能源汽车与高端芯片设计等领域&#xff0c;电磁仿真已成为不可或缺的“数字试验场”。然而&#xff0c;传统基于有限元&#xff08;FEM&#xff09;、时域有限差分&#xff08…...

软件系统规划步骤和可行性研究步骤

前者是系统开发初始阶段的宏观活动序列,后者则是规划阶段中的一项核心子任务。 一、软件系统规划步骤(典型过程) 系统规划通常属于软件生命周期的“项目立项与计划”阶段,常见步骤如下: 初步调查 识别项目机会、用户需求、业务痛点,明确系统建设的初步目标与范围。 问题…...

AI群演请就位—个人博客(一)

项目背景随着大语言模型能力的提升&#xff0c;AI在内容生成与互动体验中的应用日益广泛。传统互动叙事类产品&#xff08;如互动小说、角色扮演游戏&#xff09;主要依赖预设脚本与有限分支选择&#xff0c;存在剧情固化、重复体验感强、角色缺乏真实感等问题。大语言模型的出…...

C++零基础到工程实战(3.1):if语句、bool类型、算数逻辑比较运算符深入解析

目录 一、本节学习内容概要图 二、前言 三、if语句与逻辑判断 3.1 基础语法 &#xff08;1&#xff09;if 条件语句 &#xff08;2&#xff09;else if 与 else 3.2 常见错误 &#xff08;1&#xff09;多余分号导致逻辑块独立 &#xff08;2&#xff09;判断时误写赋…...

C++头文件详解:<iomanip> 头文件使用详解

目录 一、前言 二、浮点数精度控制 2.1 fixed 与 setprecision() &#xff08;1&#xff09;fixed 的作用 &#xff08;2&#xff09;setprecision(n) 的作用 &#xff08;3&#xff09;示例&#xff1a;RGB 转 YUV 计算 2.2 scientific 科学计数法 三、设置输出宽度与…...

CP880显示驱动库:车规级TFT-LCD底层控制与零拷贝实现

1. CP880显示驱动库深度解析&#xff1a;面向CARIAD车载信息娱乐系统的TFT-LCD底层控制方案1.1 库定位与工程背景CP880是专为大众集团CARIAD软件平台定制的嵌入式图形显示驱动库&#xff0c;核心目标是为车载信息娱乐系统&#xff08;IVI&#xff09;提供高可靠性、低延迟的TFT…...

OpenClaw+SecGPT-14B成本对比:自建模型比SaaS省下80%费用

OpenClawSecGPT-14B成本对比&#xff1a;自建模型比SaaS省下80%费用 1. 为什么我要做这个成本对比实验 去年我开始使用OpenClaw自动化处理日常安全扫描任务时&#xff0c;发现一个令人头疼的问题&#xff1a;每次调用商业安全API的费用高得惊人。作为一个独立安全研究员&…...

OpenClaw压力测试:百川2-13B-4bits连续处理1000个文件的稳定性

OpenClaw压力测试&#xff1a;百川2-13B-4bits连续处理1000个文件的稳定性 1. 测试背景与目标 去年冬天的一个深夜&#xff0c;我正被堆积如山的PDF合同审核工作折磨得焦头烂额。当时突发奇想&#xff1a;如果用AI自动处理这些文件会怎样&#xff1f;这个念头直接促成了本次压…...

JIT启用后CPU飙升200%?PHP 8.9生产环境避坑指南,含8类典型误配置清单

第一章&#xff1a;PHP 8.9 JIT 的核心机制与性能悖论PHP 8.9 并非官方发布的正式版本&#xff08;截至 PHP 官方最新稳定版为 8.3&#xff09;&#xff0c;该标题中的 “8.9” 是一个假设性技术前瞻设定&#xff0c;用于探讨 JIT 编译器在 PHP 生态中持续演进所引发的底层机制…...

【单片机0.2】

文章目录六个9第一位和第六位亮六个灯亮轮播0-9中间两个灯亮轮播0-9亮灯123456小数点13.14.15六个9 #include<reg52.h> // 头文件// 定义锁存器控制引脚 sbit dulaP3^4; // 锁存器U2&#xff08;段选&#xff09; sbit welaP1^6; // 锁存器U2&#xff08;位选&#xff0…...

作业二6位数码管显示

文章目录1.效果图:显示6个91.代码2.效果图&#xff1a;第1、6位显示72.代码3.效果图&#xff1a;6位0到9轮流显示3.代码4.效果图&#xff1a;中间两位0到9轮流显示4.代码5.效果图&#xff08;显示1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff…...

Keep平台API开发实战指南:从设计理念到生产落地

Keep平台API开发实战指南&#xff1a;从设计理念到生产落地 【免费下载链接】keep The open-source AIOps and alert management platform 项目地址: https://gitcode.com/GitHub_Trending/kee/keep 一、API设计理念&#xff1a;构建灵活的告警管理生态 在现代运维体系…...

账号没有明显违规却突然受限很多时候问题藏在哪些地方

无声的雷区&#xff1a;当你的账号悄然“触线”在数字生活的日常中&#xff0c;或许你曾经历过这样的瞬间&#xff1a;登录熟悉的平台&#xff0c;却收到一条冰冷提示——“账号功能受限”。你反复检查&#xff0c;确信自己没有发布违规内容、没有恶意刷屏、没有触及那些明晃晃…...

AccelStepper:Arduino步进电机精准控制与多轴协同解决方案

AccelStepper&#xff1a;Arduino步进电机精准控制与多轴协同解决方案 【免费下载链接】AccelStepper Fork of AccelStepper 项目地址: https://gitcode.com/gh_mirrors/acc/AccelStepper 在自动化控制领域&#xff0c;步进电机的精准驱动是实现精密运动的核心。AccelSt…...

HarmonyOS-ArkTS-新手完整复现-含环境配置

HarmonyOS ArkTS 新手完整复现&#xff1a;从环境配置到网络列表 App&#xff08;超细步骤&#xff09; 欢迎访问开源鸿蒙 PC 开发者社区&#xff08;https://harmonypc.csdn.net/&#xff09;。 摘要 本文面向零基础/初学者&#xff0c;完整讲清&#xff1a; 如何在 Window…...

MDCL:不换设备,不降功率,电费减少三分之一——发射机技术内核(二)

上一篇讲了固态发射机的模块级效率已经到了90%——硬件层面的省电空间接近极限。但AM调制本身还藏着一个巨大的效率漏洞&#xff1a;载波。 载波的浪费 AM调制有一个教科书级别的效率缺陷&#xff1a;载波本身不携带任何信息。 在标准双边带AM中&#xff0c;所有音频信息都在…...

25套HTML数据可视化大屏模板|覆盖智慧交通、医疗、城市、政务等11大行业应用

温馨提示&#xff1a;文末有联系方式25套行业级HTML可视化大屏源码合集 本提供25套高还原度、响应式设计的HTML数据可视化大屏源码&#xff0c;全部基于纯前端技术&#xff08;HTML/CSS/JS&#xff09;构建&#xff0c;无需后端依赖&#xff0c;可快速部署至各类内网或公有云环…...