Android audio_policy_configuration.xml加載流程

目錄

一、audio_policy_configuration.xml文件被加載流程

1、AudioPolicyService 創建階段

2、createAudioPolicyManager 實現

3、AudioPolicyManager 構造

4、配置文件解析 loadConfig

5、核心解析邏輯 PolicySerializer::deserialize

二、AudioPolicyConfig類解析

1、AudioPolicyConfig 類定義

2、module標簽

3、MixPort標簽

4、DevicePort標簽

5、route標簽


一、audio_policy_configuration.xml文件被加載流程

1、AudioPolicyService 創建階段

文件路徑:frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp

void AudioPolicyService::onFirstRef() {mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
}

系統服務啟動后,調用 createAudioPolicyManager,創建 AudioPolicyManager 對象。

2、createAudioPolicyManager 實現

extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) {AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);status_t status = apm->initialize();if (status != NO_ERROR) {delete apm;apm = nullptr;}return apm;
}

作用

  • 創建 AudioPolicyManager

  • 立即調用 initialize() 初始化流程;

  • 如果失敗,釋放資源

3、AudioPolicyManager 構造

文件
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp


AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface): AudioPolicyManager(clientInterface, false /*forTesting*/)
{loadConfig();
}void AudioPolicyManager::loadConfig() {if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {ALOGE("could not load audio policy configuration file, setting defaults");getConfig().setDefault();}
}

構造時直接調用 loadConfig(),開始讀取音頻配置文件。

4、配置文件解析 loadConfig

文件
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp

status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config) {PolicySerializer serializer;return serializer.deserialize(fileName, config);
}

調用 PolicySerializer::deserialize,使用 libxml2 解析音頻 XML 配置文件。

5、核心解析邏輯 PolicySerializer::deserialize

status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config)
{// 使用智能指針包裝 libxml2 的解析接口,解析傳入的 XML 文件auto doc = make_xmlUnique(xmlParseFile(configFile));if (doc == nullptr) {// 如果解析失敗,打印錯誤并返回 BAD_VALUEALOGE("%s: Could not parse %s document.", __func__, configFile);return BAD_VALUE;}// 獲取 XML 文檔的根節點xmlNodePtr root = xmlDocGetRootElement(doc.get());if (root == NULL) {// 如果根節點為空,打印錯誤并返回 BAD_VALUEALOGE("%s: Could not parse %s document: empty.", __func__, configFile);return BAD_VALUE;}// 處理 XInclude(XML文件可以引用其他XML文件的機制)if (xmlXIncludeProcess(doc.get()) < 0) {// 如果包含文件處理失敗,記錄錯誤,但不直接返回ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile);}// 檢查根節點名稱是否符合預期if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName)))  {ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName,reinterpret_cast<const char*>(root->name));return BAD_VALUE;}// 獲取根節點的 version 屬性std::string version = getXmlAttribute(root, versionAttribute);if (version.empty()) {// 如果 version 屬性不存在,返回錯誤ALOGE("%s: No version found in root node %s", __func__, rootName);return BAD_VALUE;}// 驗證版本是否與期望版本一致if (version != mVersion) {ALOGE("%s: Version does not match; expect %s got %s", __func__, mVersion.c_str(),version.c_str());return BAD_VALUE;}// 開始解析子節點// Step 1: 解析 Module 列表ModuleTraits::Collection modules;status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);if (status != NO_ERROR) {// 如果模塊解析失敗,直接返回錯誤狀態return status;}// 將解析到的模塊設置到 config 對象中config->setHwModules(modules);// Step 2: 解析全局配置GlobalConfigTraits::deseria

功能拆解

  • xmlParseFile:加載并解析 XML 文件。

  • xmlDocGetRootElement:獲取根節點,確保結構有效。

  • xmlXIncludeProcess:處理 XInclude,允許配置文件嵌套引用子文件。

  • 驗證 root 名稱、版本號。

如果通過校驗,進入內容解析:

deserializeCollection<ModuleTraits>(root, &modules, config);
config->setHwModules(modules);
GlobalConfigTraits::deserialize(root, config);
SurroundSoundTraits::deserialize(root, config);

經過以上代碼之后,最終audio_policy_configuration.xml配置文件會轉化為以下的C++類AudioPolicyConfig。

二、AudioPolicyConfig類解析

audio_policy_configuration.xml配置文件配置了Android Audio的設備、流以及設備和流之間的路由等相關信息。寫明了Android Audio支持哪些設備、哪些流以及它們支持的編碼格式、采樣率等信息。文件大致內容如下。

1、AudioPolicyConfig 類定義


class AudioPolicyConfig {static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";std::string mSource; //為config字符串目錄,一般在odm/etc、/vendor/etc、/system/etc下的audio_policy_configuration.xmlstd::string mEngineLibraryNameSuffix;HwModuleCollection &mHwModules; //保存了配置文件中所有的所有module標簽集合,每個module標簽對應一個HwModule類DeviceVector &mOutputDevices; //attchedDevices標簽中,設備名稱名字和devicePort標簽的tagName相同,且type中有OUT字眼的DeviceDescriptor實體類集合DeviceVector &mInputDevices; //attchedDevices標簽中,設備名稱名字和devicePort標簽的tagName相同,且type中有in字眼的DeviceDescriptor實體類集合sp<DeviceDescriptor> &mDefaultOutputDevice; //保存defaultOutputDevice標簽內名字和devicePort標簽的tagName相同// TODO: remove when legacy conf file is removed. true on devices that use DRC on the// DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.// Note: remove also speaker_drc_enabled from global configuration of XML config file.bool mIsSpeakerDrcEnabled;bool mIsCallScreenModeSupported;SurroundFormats mSurroundFormats;
};
<modules><!-- Primary Audio HAL --><module name="primary" halVersion="3.0"><attachedDevices><item>Speaker</item><item>Built-In Mic</item><item>Built-In Back Mic</item></attachedDevices><defaultOutputDevice>Speaker</defaultOutputDevice><mixPorts>……</mixPorts><devicePorts>……</devicePorts><!-- route declaration, i.e. list all available sources for a given sink --><routes>……</routes></module><!-- A2dp Input Audio HAL --><xi:include href="a2dp_in_audio_policy_configuration.xml"/>……</modules><!-- End of Modules section -->

2、module標簽

每個module標簽對應著相應的hal層實現,如primary、usb、a2dp等

<modules><!-- Primary Audio HAL --><module name="primary" halVersion="3.0"><attachedDevices><item>Speaker</item><item>Built-In Mic</item><item>Built-In Back Mic</item></attachedDevices>……</module><!-- A2dp Input Audio HAL --><xi:include href="a2dp_in_audio_policy_configuration.xml"/>……</modules><!-- End of Modules section -->

module標簽對應C++實體類HWModule。

class HwModule {const String8 mName; // hal層模塊對應的module名字(primary, a2dp ...)audio_module_handle_t mHandle;OutputProfileCollection mOutputProfiles; // mixport標簽role為source類型,對應IOProfle實體類集合InputProfileCollection mInputProfiles;  // mixport標簽role為sink的類型,對應IOProfle實體類集合uint32_t mHalVersion; // hal層模塊的版本信息DeviceVector mDeclaredDevices; // 所有的deviceport標簽,對應DeviceDescriptor實體類的集合DeviceVector mDynamicDevices; /**< devices that can be added/removed at runtime (e.g. rsbumix)*/AudioRouteVector mRoutes; // 所有的routePolicyAudioPortVector mPorts; // 所有的mixport,deviceport標簽對應的實體類,因為IOProfle和DeviceDescriptor都繼承了AudioPort,所以相當于這是一個AudioPort集合
};

3、MixPort標簽

mixport標簽可以理解為stream流,配置了相應的格式、采樣率以及mask,且分為輸出、輸入流。一個mixport標簽可能有多個profile屬性,也就是支持很多編碼格式等屬性。

<mixPort name="compressed_offload" role="source"flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING"><profile name="" format="AUDIO_FORMAT_MP3"samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/><profile name="" format="AUDIO_FORMAT_AAC"samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/><profile name="" format="AUDIO_FORMAT_AAC_LC"samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
</mixPort>

一個mixport標簽對應一個IOProfile實體類。

class IOProfile : public AudioPort, public PolicyAudioPort {// 可以同時打開的流的最大數量,默認為1。賦值為0時,表示無窮大。uint32_t     maxOpenCount;// 目前已打開的流的數量。uint32_t     curOpenCount;// 同時處于活躍狀態的流的最大數量,默認為1。賦值為0時,表示無窮大。uint32_t     maxActiveCount;// 正處于活躍狀態的流的數量。 針對于Hal層的流而言。uint32_t     curActiveCount;private:/** 當前流支持的設備集合;* 如果是sink輸入流,查找規則如下:* 1. 遍歷其父類的成員mRoutes,因為是輸入流,所以遍歷mRoute集合中sink為自己的route,也就是找有哪些源source設備把數據傳給自己。* 2. 找到route后,根據route中source保存的對象,且對象type是AUDIO_PORT_TYPE_DEVICE類型(就是devicesPort標簽對應的實體類DeviceDescriptor)* 3. 把DeviceDescriptor保存在集合中,保存在以下mSupportedDevices中,作為其支持的設備;* 輸出流,同理;最終的結果就是:* 作為輸出流source,mSupportedDevices保存此流可以輸出到對應的device,stream -> device* 作為輸入流sink,mSupportedDevices保存了其他device能輸出數據到此流,  device -> stream**/DeviceVector mSupportedDevices;
};class AudioPort : public virtual RefBase, public virtual Parcelable
{AudioGains mGains; // gain controllers
protected:std::string  mName; // 對應mixport的nameaudio_port_type_t mType; // AUDIO_PORT_TYPE_MIX (此處固定)audio_port_role_t mRole; // AUDIO_PORT_ROLE_SOURCE/AUDIO_PORT_ROLE_SINK(由mixport的role決定)AudioProfileVector mProfiles; // AudioProfile的集合,對應mixport里面的多個profile// Audio capabilities that are defined by hardware descriptors when the format is unrecognized// by the platform, e.g. short audio descriptor in EDID for HDMI.std::vector<media::ExtraAudioDescriptor> mExtraAudioDescriptors;
};class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
{uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).sp<HwModule> mModule;     // 通過attach函數與HwModule綁定AudioRouteVector mRoutes; // 相關連的route標簽集合
};

mixport內部的Profile標簽對應的C++類AudioProfile 如下。在解析以上標簽至profile時,會單獨創建AudioProfile。

class AudioProfile final : public RefBase, public Parcelable
{std::string  mName; // profile的name// 以下三個變量對應配置文件中profile中的置,由初始化時進行賦值audio_format_t mFormat; // The format for an audio profile should only be set when initialized.ChannelMaskSet mChannelMasks;SampleRateSet mSamplingRates;// 以下三個對應上面三位,如果三位都有值,則為false固定的,如果xml沒有指定值,則為true表示是動態的值bool mIsDynamicFormat = false;bool mIsDynamicChannels = false;bool mIsDynamicRate = false;audio_encapsulation_type_t mEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE;AudioProfile() = default;AudioProfile& operator=(const AudioProfile& other);
};

4、DevicePort標簽

devicePort標簽可以理解為一個device設備,設備也分output和input,以type中的關鍵字“IN”和“OUT”進行區分。

<devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address=""><profile name="" format="AUDIO_FORMAT_PCM_16_BIT"samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/><gains><gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"minValueMB="-8400"maxValueMB="4000"defaultValueMB="0"stepValueMB="100"/></gains>
</devicePort>

一個devicePort對應一個C++類DeviceDescriptor。

class DeviceDescriptor : public DeviceDescriptorBase,public PolicyAudioPort, public PolicyAudioPortConfig
{std::string mTagName; // 對應的tagName字段FormatVector        mEncodedFormats; // encodedFormats轉換的枚舉值audio_format_t      mCurrentEncodedFormat;bool                mIsDynamic = false;const std::string   mDeclaredAddress; // address字段對應的地址
};class DeviceDescriptorBase : public AudioPort, public AudioPortConfig
{AudioDeviceTypeAddr mDeviceTypeAddr;uint32_t mEncapsulationModes = 0;uint32_t mEncapsulationMetadataTypes = 0;
};class AudioPort : public virtual RefBase, public virtual Parcelable
{AudioGains mGains; // gain controllers
protected:std::string  mName; // 對應devicePort的nameaudio_port_type_t mType; // AUDIO_PORT_TYPE_DEVICE(此處固定)audio_port_role_t mRole; // AUDIO_PORT_ROLE_SOURCE/AUDIO_PORT_ROLE_SINK(由mixport的role決定)AudioProfileVector mProfiles; // AudioProfile的集合,對應devicePort里面的多個profile// Audio capabilities that are defined by hardware descriptors when the format is unrecognized// by the platform, e.g. short audio descriptor in EDID for HDMI.std::vector<media::ExtraAudioDescriptor> mExtraAudioDescriptors;
};

同MixPort一樣,devicePort也會解析內部的profile標簽,創建新的AudioProfile。

class AudioProfile final : public RefBase, public Parcelable
{std::string  mName; // profile的name// 以下三個變量對應配置文件中profile中的置,由初始化時進行賦值audio_format_t mFormat; // The format for an audio profile should only be set when initialized.ChannelMaskSet mChannelMasks;SampleRateSet mSamplingRates;// 以下三個對應上面三位,如果三位都有值,則為false固定的,如果xml沒有指定值,則為true表示是動態的值bool mIsDynamicFormat = false;bool mIsDynamicChannels = false;bool mIsDynamicRate = false;audio_encapsulation_type_t mEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE;AudioProfile() = default;AudioProfile& operator=(const AudioProfile& other);
};

5、route標簽

route是把deviceport和mixport連接起來的路由,數據由一個stream輸出到另一個device,或者從一個device輸出到另一個stream。

<route type="mix" sink="Speaker"sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>

route標簽對應C++的AudioRoute類。

class AudioRoute  : public virtual RefBase
{PolicyAudioPortVector mSources; //所有的deviceport、mixport標簽轉化的實體類都保存到HwModule的mPorts成員了,所以是用name去mPorts里面查找,只是source可能是多個,這里用集合保存sp<PolicyAudioPort> mSink; //同上audio_route_type_t mType; //AUDIO_ROUTE_MIX/AUDIO_ROUTE_MUX:根據type而定是互斥還是可融合
};

在Primary的module配置文件中通過如下語句去配置a2dp、usb的module。

<!-- A2dp Input Audio HAL --><xi:include href="a2dp_in_audio_policy_configuration.xml"/>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77789.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用 Docker 安裝 Elastic Stack 并重置本地密碼

Elastic Stack&#xff08;也被稱為 ELK Stack&#xff09;是一個非常強大的工具套件&#xff0c;用于實時搜索、分析和可視化大量數據。Elastic Stack 包括 Elasticsearch、Logstash、Kibana 等組件。本文將展示如何使用 Docker 安裝 Elasticsearch 并重置本地用戶密碼。 ###…

Unitest和pytest使用方法

unittest 是 Python 自帶的單元測試框架&#xff0c;用于編寫和運行可重復的測試用例。它的核心思想是通過斷言&#xff08;assertions&#xff09;驗證代碼的行為是否符合預期。以下是 unittest 的基本使用方法&#xff1a; 1. 基本結構 1.1 創建測試類 繼承 unittest.TestC…

git 版本提交規范

Git 提交規范&#xff08;Git Commit Message Convention&#xff09;是為了讓項目的提交歷史更加清晰、可讀、便于追蹤和自動化工具解析。常見的規范之一是 Conventional Commits&#xff0c;下面是一個推薦的格式規范&#xff1a; &#x1f31f; 提交信息格式&#xff08;Con…

stat判斷路徑

int stat(const char *pathname, struct stat *buf); pathname&#xff1a;用于指定一個需要查看屬性的文件路徑。 buf&#xff1a;struct stat 類型指針&#xff0c;用于指向一個 struct stat 結構體變量。調用 stat 函數的時候需要傳入一個 struct stat 變量的指針&#xff0…

學習Docker遇到的問題

目錄 1、拉取hello-world鏡像報錯 1. 檢查網絡連接 排查: 2. 配置 Docker 鏡像加速器(推薦) 具體解決步驟: 1.在服務器上創建并修改配置文件,添加Docker鏡像加速器地址: 2. 重啟Docker 3. 拉取hello-world鏡像 2、刪除鏡像出現異常 3、 容器內部不能運行ping命令 …

安寶特案例 | AR如何大幅提升IC封裝廠檢測效率?

前言&#xff1a;如何提升IC封裝廠檢測效率&#xff1f; 在現代電子產品的制造過程中&#xff0c;IC封裝作為核心環節&#xff0c;涉及到復雜處理流程和嚴格質量檢測。這是一家專注于IC封裝的廠商&#xff0c;負責將來自IC制造商的晶圓進行保護、散熱和導通處理。整個制程繁瑣…

【Linux網絡與網絡編程】07.應用層協議HTTPS

HTTP 協議內容都是按照文本的方式明文傳輸的&#xff0c;這就導致在傳輸過程中出現一些被篡改的情況。HTTPS 就是在 HTTP 協議的基礎上引入了一個加密層的應用層協議。 1. 基礎概念 1.1 加密與解密 加密就是把明文&#xff08;要傳輸的信息&#xff09;進行一系列變換&#x…

【k8s】PV,PVC的回收策略——return、recycle、delete

PV 和 PVC 的回收策略主要用于管理存儲資源的生命周期&#xff0c;特別是當 PVC 被刪除時&#xff0c;PV 的處理方式。回收策略決定了 PV 在 PVC 被刪除后的行為。 回收策略的類型 Kubernetes 提供了三種主要的回收策略&#xff0c;用于管理 PV 的生命周期&#xff1a; Reta…

2023藍帽杯初賽內存取證-2

直接使用mimikatz插件來獲取用戶密碼&#xff1a; vol.py --plugin/opt/volatility/plugins -f memdump.mem --profile Win7SP1x64 mimikatz 答案&#xff1a;3w.qax.com

使用dompurify修復XSS跨站腳本缺陷

1. 問題描述 漏洞掃描說有一個低危漏洞&#xff0c;容易被跨站腳本攻擊XSS。 2. 使用dompurify修復 DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. 簡單來說&#xff0c;我們可以使用 dompurify 處理xss跨站腳本攻擊。 2.…

【c語言】指針和數組筆試題解析

一維數組: //數組名a如果既不單獨放在sizeof()中&#xff0c;也不與&結合&#xff0c;那么就表示數組首元素的大小 //a一般表示數組首元素地址&#xff0c;只有兩種情況表示整個數組&#xff0c;sizeof(arr)表示整個數組的大小&#xff0c;&arr表示數組的地址 int a[]…

機器人進階---視覺算法(六)傅里葉變換在圖像處理中怎么用

傅里葉變換在圖像處理中怎么用 傅里葉變換的基本原理應用場景Python代碼示例逐行解釋總結傅里葉變換在圖像處理中是一種重要的工具,它將圖像從空間域轉換到頻域,從而可以對圖像的頻率特性進行分析和處理。傅里葉變換在圖像濾波、圖像增強、圖像壓縮和圖像分析等方面都有廣泛應…

深度學習與總結JVM專輯(七):垃圾回收器—CMS(圖文+代碼)

CMS垃圾收集器深度解析教程 1. 前言&#xff1a;為什么需要CMS&#xff1f;2. CMS 工作原理&#xff1a;一場與時間的賽跑2.1. 初始標記&#xff08;Initial Mark&#xff09;2.2. 并發標記&#xff08;Concurrent Mark&#xff09;2.3. 重新標記&#xff08;Remark&#xff09…

數據采集:AI 發展的基石與驅動力

人工智能&#xff08;AI&#xff09;無疑是最具變革性的技術力量之一&#xff0c;正以驚人的速度重塑著各行各業的格局。從智能語音助手到自動駕駛汽車&#xff0c;從精準的醫療診斷到個性化的推薦系統&#xff0c;AI 的廣泛應用已深刻融入人們的日常生活與工作的各個層面。而在…

從信息泄露到內網控制

0x01 背景 之前常見用rce、文件上傳等漏洞獲取webshell&#xff0c;偶然遇到一次敏感信息泄露獲取權限的滲透&#xff0c;簡單記錄一下過程。 0x02 信息泄露 發現系統某端口部署了minio服務&#xff0c;經過探測發現存在minio存儲桶遍歷 使用利用工具把泄露的文件全部整理一…

《門》凡是過往,皆為序曲。我們的愛,和最初一樣

《門》凡是過往&#xff0c;皆為序曲。我們的愛&#xff0c;和最初一樣 夏目漱石&#xff0c;本名夏目金之助&#xff0c;筆名漱石&#xff0c;日本近代作家&#xff0c;代表作有《三四郎》《門》《從此以后》《我是貓》《心》《明暗》等。 竺家榮 譯 文章目錄 《門》凡是過往&…

衡石ChatBI:依托開放架構構建技術驅動的差異化數據服務

在當今數字化浪潮中&#xff0c;企業對數據價值的挖掘和利用需求日益增長。BI&#xff08;商業智能&#xff09;工具作為企業獲取數據洞察的關鍵手段&#xff0c;其技術架構的創新與發展至關重要。衡石科技的Chat BI憑借其獨特的開放架構&#xff0c;在BI領域脫穎而出&#xff…

oracle中錯誤總結

oracle中給表起別名不能用as&#xff0c;用as報錯 在 Oracle 數據庫中&#xff0c;??WITH 子句&#xff08;即 CTE&#xff0c;公共表表達式&#xff09;允許后續定義的子查詢引用前面已經定義的 CTE??&#xff0c;但 ??前面的 CTE 無法引用后面的 CTE??。這種設計類似…

NLP高頻面試題(五十)——大模型(LLMs)分詞(Tokenizer)詳解

在自然語言處理(NLP)任務中,將文本轉換為模型可處理的數字序列是必不可少的一步。這一步通常稱為分詞(tokenization),即把原始文本拆分成一個個詞元(token)。對于**大型語言模型(LLM,Large Language Model,大型語言模型)**而言,選擇合適的分詞方案至關重要:分詞的…

優化WAV音頻文件

優化 WAV 音頻文件通常涉及 減小文件體積、提升音質 或 適配特定用途&#xff08;如流媒體、廣播等&#xff09;。以下是分場景的優化方法&#xff0c;涵蓋工具和操作步驟&#xff1a; 一、減小文件體積&#xff08;無損/有損壓縮&#xff09; 1. 無損壓縮 轉換格式&#xff1…