医院网站建设方案书/个人网站建设

医院网站建设方案书,个人网站建设,wordpress整站无刷新,广东深广东深圳网站建设在 Android 平台上,音频混合器 AudioMixer 主要用在 AudioFlinger 里,将多路音频源数据混音(包括混音、音量处理、重采样及处理声道等)。位于 framework 的音频处理模库 libaudioprocessing(frameworks/av/media/libau…

在 Android 平台上,音频混合器 AudioMixer 主要用在 AudioFlinger 里,将多路音频源数据混音(包括混音、音量处理、重采样及处理声道等)。位于 framework 的音频处理模库 libaudioprocessing(frameworks/av/media/libaudioprocessing)中。

一、音频混合器

混音器(AudioMixer)是在混音回放线程类(MixerThread)中的构造函数内创建。

1、混合器创建

源码位置:/frameworks/av/services/audioflinger/Threads.cpp

AudioFlinger::MixerThread::MixerThread(……) 
{……// 往hal层一次写数据的大小。hal层设备的采样率。mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);……
}

这说明了一个 MixerThread 对应一个 AudioMixer,而且 MixerThread 传了两个参数给AudioMixer:
mNormalFrameCount:一次输送数据的长度,把源 buffer 的音频数据写入目的 buffer。
mSampleRate:音频数据输出的采样率。

2、功能接口

AudioMixer源码位置:/frameworks/av/media/libaudioprocessing/AudioMixer.cpp

void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)

此方法允许用户根据给定的索引设置一个音频缓冲区提供者,name 作为索引,bufferProvider由 mActiveTracks 取出来的 Track 对象提供。这样audiomixer混音时就从track对应的IFFO取数据。

void AudioMixer::setParameter(int name, int target, int param, void *value)

该函数主要用于设置特定参数值,涉及到了音频处理中多种参数的设置,包括通道掩码、缓冲区指针、格式、重采样、音量衰减、时间拉伸等。

这里我们主要看一下 target 和 param 的不同参数所对应实现的相关功能:

在这里插入图片描述
标注基类是直接透传调用 AudioMixerBase.cpp 中的对应函数。AudioMixer 继承自 AudioMixerBase,同时基类中也有几个比较重要的函数。这里我们需要关注的是参数MAIN_BUFFER。audiomixer会将从track获取的FIFO数据和MAIN_BUFFER混音后存入MAIN_BUFFER。

AudioMixerBase

源码位置:/frameworks/av/media/libaudioprocessing/AudioMixerBase.cpp

// 启用指定的音频轨道
void AudioMixerBase::enable(int name)
// 禁用指定的音频轨道
void AudioMixerBase::disable(int name)
// 销毁指定的音频轨道
void AudioMixerBase::destroy(int name)

这几个函数主要是用于音频轨道的控制功能,确保了轨道能够在不同状态下正确工作。

刷新函数

上面的接口中大量调用 invalidate() 函数,该函数的主要作用就是刷新 Track。源码位置:/frameworks/av/media/libaudioprocessing/include/media/AudioMixerBase.h

// 当轨道信息改变,需要确定一个新的进程钩子时调用下面的函数
void invalidate() {mHook = &AudioMixerBase::process__validate;
}

可以看到该函数用于当轨道信息发生变化时,重新确定一个新的进程钩子。这个钩子通常用于验证和处理轨道信息的变化,调用 AudioMixerBase 中的 process__validate() 函数。

void AudioMixerBase::process__validate()
{……// 遍历轨道for (const auto &pair : mTracks) {const int name = pair.first;const std::shared_ptr<TrackBase> &t = pair.second;// 判断该track是否需要混音if (!t->enabled) continue;// 将启用的轨道添加到 mEnabled 和 mGroups 中mEnabled.emplace_back(name);mGroups[t->mainBuffer].emplace_back(name);// 计算每个轨道的需求 (needs) 并设置相应的处理钩子 (hook)uint32_t n = 0;// 可以溢出(掩码只有3位)n |= NEEDS_CHANNEL_1 + t->channelCount - 1;// 设置重采样 NEEDS_RESAMPLE 标志位if (t->doesResample()) {n |= NEEDS_RESAMPLE;}// 设置辅助通道 NEEDS_AUX 标志位if (t->auxLevel != 0 && t->auxBuffer != NULL) {n |= NEEDS_AUX;}if (t->volumeInc[0]|t->volumeInc[1]) {// 增益正在变化volumeRamp = true;} else if (!t->doesResample() && t->volumeRL == 0) {// 不需要重采样且增益为零n |= NEEDS_MUTE;}// 将所有设置好的标志位保存到 t->needs 中t->needs = n;if (n & NEEDS_MUTE) { // 需要静音t->hook = &TrackBase::track__nop;} else {if (n & NEEDS_AUX) { // 处理辅助通道all16BitsStereoNoResample = false;}if (n & NEEDS_RESAMPLE) { // 处理重采样all16BitsStereoNoResample = false;resampling = true;if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1&& t->channelMask == AUDIO_CHANNEL_OUT_MONO // MONO_HACK&& isAudioChannelPositionMask(t->mMixerChannelMask)) { // 重采样单声道t->hook = TrackBase::getTrackHook(TRACKTYPE_RESAMPLEMONO, t->mMixerChannelCount,t->mMixerInFormat, t->mMixerFormat);} else if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2&& t->useStereoVolume()) { // 重采样立体声t->hook = TrackBase::getTrackHook(TRACKTYPE_RESAMPLESTEREO, t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);} else { // 其他情况t->hook = TrackBase::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount,t->mMixerInFormat, t->mMixerFormat);}ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,"Track %d needs downmix + resample", name);} else { // 处理无需重采样的情况……}}}// 根据条件选择合适的处理钩子mHook = &AudioMixerBase::process__nop;if (mEnabled.size() > 0) {if (resampling) {if (mOutputTemp.get() == nullptr) {mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);}if (mResampleTemp.get() == nullptr) {mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);}mHook = &AudioMixerBase::process__genericResampling;} else {mHook = &AudioMixerBase::process__genericNoResampling;if (all16BitsStereoNoResample && !volumeRamp) {if (mEnabled.size() == 1) {const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];if ((t->needs & NEEDS_MUTE) == 0) {mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK, t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat, t->useStereoVolume());}}}}}……process();// 处理音量渐变,设置最优状态和轨道处理钩子if (mEnabled.size() > 0) {bool allMuted = true;for (const int name : mEnabled) {const std::shared_ptr<TrackBase> &t = mTracks[name];if (!t->doesResample() && t->volumeRL == 0) {t->needs |= NEEDS_MUTE;t->hook = &TrackBase::track__nop;} else {allMuted = false;}}if (allMuted) {mHook = &AudioMixerBase::process__nop;} else if (all16BitsStereoNoResample) {if (mEnabled.size() == 1) {const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK, t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat, t->useStereoVolume());}}}
}

这些步骤确保了音频轨道信息变化时能够正确选择合理的钩子函数处理各种情况,包括重采样、音量渐变等。

二、AudioMixer混音

  关于混音,我们已经知道:混音以 track 为源,mainBuffer 为目标,frameCount 为一次混音长度。AudioMixer 最多能维护 32 个 track。track 可以对应不同 mainBuffer,尽管一般情况下他们的 mainBuffer 都是同一个。

在这里插入图片描述

调用 AudioMixer 的 process 方法进行混音的,实际上混音的方法是调用 AudioMixerBase 内的 process_xxx 方法,各个 process 方法大同小异。下面来分析 process__genericResampling 这个方法。
1、AudioMixerBase.cppp
rocess__genericResampling

void AudioMixerBase::process__genericResampling()
{ALOGVV("process__genericResampling\n");// 初始化 outTemp 指针int32_t * const outTemp = mOutputTemp.get(); // 获取当前帧数 numFramessize_t numFrames = mFrameCount;// 遍历每个音频组 mGroupsfor (const auto &pair : mGroups) {const auto &group = pair.second;// 获取第一个轨道 t1const std::shared_ptr<TrackBase> &t1 = mTracks[group[0]];// 清除了临时缓冲区 outTempmemset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);// 处理每个轨道for (const int name : group) {const std::shared_ptr<TrackBase> &t = mTracks[name];int32_t *aux = NULL;if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {aux = t->auxBuffer;}// 如果轨道需要重采样,则直接调用重采样钩子if (t->needs & NEEDS_RESAMPLE) {(t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);} else { // 逐帧获取数据并调用处理钩子// 清除临时缓冲区size_t outFrames = 0;// 获取每个轨道的数据并调用相应的处理钩子while (outFrames < numFrames) {t->buffer.frameCount = numFrames - outFrames;t->bufferProvider->getNextBuffer(&t->buffer);t->mIn = t->buffer.raw;// t->mIn == nullptr:启用混音后刚刚刷新音轨if (t->mIn == nullptr) break;(t.get()->*t->hook)(outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,mResampleTemp.get() /* naked ptr */, aux != nullptr ? aux + outFrames : nullptr);outFrames += t->buffer.frameCount;t->bufferProvider->releaseBuffer(&t->buffer);}}}// 将处理后的数据转换为混音器所需的格式convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);}
}

这些步骤确保了在需要重采样的情况下,能够正确处理每个轨道的数据,并将其转换为所需的格式。

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

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

相关文章

Matlab教程001:软件介绍和界面使用

1.1 软件介绍 1.1.1 Matlab的介绍 MATLAB&#xff08;MATrix LABoratory&#xff09;是一款由 MathWorks 公司开发的高级编程语言和交互式环境&#xff0c;广泛用于 科学计算、数据分析、机器学习、工程建模、仿真和信号处理 等领域。 1.1.2 主要应用领域 数据分析与可视化…

毫米波雷达标定(2)

1. 前言 前面文章中介绍了产线上毫米波雷达的标定原理和流程,这篇文章则主要介绍其在线标定方法。相对于产线标定,在线标定具备使用自然场景而不是依赖特定标靶的优点,但因此其标定精度会相对差一点。在线标定一般应用于售出产品的维护场景,如果其标定结果精度可以满足使用…

Linux fority source和__builtin_xxx

这段代码是用于启用和配置 GCC/Clang 的 Fortify Source 安全机制的预处理指令。Fortify Source 主要用于在编译时增强对缓冲区溢出等内存安全问题的检查。以下是对每一部分的详细解释&#xff1a; 1. 最外层条件编译 # if CONFIG_FORTIFY_SOURCE > 0目的&#xff1a;检查…

语言模型理论基础-持续更新-思路清晰

1.预训练 相似的任务A、B&#xff0c;任务A已经用大数据完成了训练&#xff0c;得到模型A。 我们利用-特征提取模型的-“浅层参数通用”的特性&#xff0c;使用模型A的浅层参数&#xff0c;其他参数再通过任务B去训练&#xff08;微调&#xff09;。 2.统计语言模型 通过条件…

ResNet与注意力机制:深度学习中的强强联合

引言 在深度学习领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;一直是图像处理任务的主流架构。然而&#xff0c;随着网络深度的增加&#xff0c;梯度消失和梯度爆炸问题逐渐显现&#xff0c;限制了网络的性能。为了解决这一问题&#xff0c;ResNet&#xff08;残差…

【C++】——C++11新特性

目录 前言 1.初始化列表 2.std::initializer_list 3.auto 4.decltype 5.nullptr 6.左值引用和右值引用 6.1右值引用的真面目 6.2左值引用和右值引用比较 6.3右值引用的意义 6.3.1移动构造 6.4万能引用 6.5完美转发——forward 结语 前言 C&#xff0c;这门在系统…

【C++网络编程】第5篇:UDP与广播通信

一、UDP协议核心特性 1. UDP vs TCP ​特性 ​UDP​TCP连接方式无连接面向连接&#xff08;三次握手&#xff09;可靠性不保证数据到达或顺序可靠传输&#xff08;超时重传、顺序控制&#xff09;传输效率低延迟&#xff0c;高吞吐相对较低&#xff08;因握手和确认机制&…

ffmpeg+QOpenGLWidget显示视频

​一个基于 ‌FFmpeg 4.x‌ 和 QOpenGLWidget的简单视频播放器代码示例&#xff0c;实现视频解码和渲染到 Qt 窗口的功能。 1&#xff09;ffmpeg库界面&#xff0c;视频解码支持软解和硬解方式。 硬解后&#xff0c;硬件解码完成需要将数据从GPU复制到CPU。优先采用av_hwf…

20250324-使用 `nltk` 的 `sent_tokenize`, `word_tokenize、WordNetLemmatizer` 方法时报错

解决使用 nltk 的 sent_tokenize, word_tokenize、WordNetLemmatizer 方法时报错问题 第 2 节的手动方法的法1可解决大部分问题&#xff0c;可首先尝试章节 2 的方法 1. nltk.download(‘punkt_tab’) LookupError: *******************************************************…

【VolView】纯前端实现CT三维重建-CBCT

文章目录 什么是CBCTCBCT技术路线使用第三方工具使用Python实现使用前端实现 纯前端实现方案优缺点使用VolView实现CBCT VolView的使用1.克隆代码2.配置依赖3.运行4.效果 进阶&#xff1a;VolView配合Python解决卡顿1.修改VtkThreeView.vue2.新增Custom3DView.vue3.Python生成s…

debug - 安装.msi时,为所有用户安装程序

文章目录 debug - 安装.msi时&#xff0c;为所有用户安装程序概述笔记试试在目标.msi后面直接加参数的测试 备注备注END debug - 安装.msi时&#xff0c;为所有用户安装程序 概述 为了测试&#xff0c;装了一个test.msi. 安装时&#xff0c;只有安装路径的选择&#xff0c;没…

Java Stream两种list判断字符串是否存在方案

这里写自定义目录标题 背景初始化方法一、filter过滤方法二、anyMatch匹配 背景 在项目开发中&#xff0c;经常遇到筛选list中是否包含某个子字符串&#xff0c;有多种方式&#xff0c;本篇主要介绍stream流的filter和anyMatch两种方案&#xff0c;记录下来&#xff0c;方便备…

3. 轴指令(omron 机器自动化控制器)——>MC_SetOverride

机器自动化控制器——第三章 轴指令 12 MC_SetOverride变量▶输入变量▶输出变量▶输入输出变量 功能说明▶时序图▶重启运动指令▶多重启动运动指令▶异常 MC_SetOverride 变更轴的目标速度。 指令名称FB/FUN图形表现ST表现MC_SetOverride超调值设定FBMC_SetOverride_instan…

VLAN章节学习

为什么会有vlan这个技术&#xff1f; 1.通过划分广播域来降低广播风暴导致的设备性能下降&#xff1b; 2.提高网络管理的灵活性和通过隔离网络带来的安全性&#xff1b; 3.在成本不变的情况下增加更多的功能性&#xff1b; VLAN又称虚拟局域网&#xff08;再此扩展&#xf…

FPGA时钟约束

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、Create_clock 前言 时钟周期约束&#xff0c;就是对时钟进行约束。 一、Create_clock create_clock -name <name> -period <period> -waveform …

spring-security原理与应用系列:建造者

目录 1.构建过程 AbstractSecurityBuilder AbstractConfiguredSecurityBuilder WebSecurity 2.建造者类图 SecurityBuilder ​​​​​​​AbstractSecurityBuilder ​​​​​​​AbstractConfiguredSecurityBuilder ​​​​​​​WebSecurity 3.小结 紧接上一篇文…

OpenHarmony子系统开发 - 电池管理(二)

OpenHarmony子系统开发 - 电池管理&#xff08;二&#xff09; 五、充电限流限压定制开发指导 概述 简介 OpenHarmony默认提供了充电限流限压的特性。在对终端设备进行充电时&#xff0c;由于环境影响&#xff0c;可能会导致电池温度过高&#xff0c;因此需要对充电电流或电…

xy轴不等比缩放问题——AUTOCAD c#二次开发

在 AutoCAD .net api里&#xff0c;部分实体&#xff0c;像文字、属性、插入块等&#xff0c;是不支持非等比缩放的。 如需对AutoCAD中图形进行xyz方向不等比缩放&#xff0c;则需进行额外的函数封装。 选择图元&#xff0c;指定缩放基准点&#xff0c;scaleX 0.5, scaleY …

如何在 HTML 中创建一个有序列表和无序列表,它们的语义有何不同?

大白话如何在 HTML 中创建一个有序列表和无序列表&#xff0c;它们的语义有何不同&#xff1f; 1. HTML 中有序列表和无序列表的基本概念 在 HTML 里&#xff0c;列表是一种用来组织信息的方式。有序列表就是带有编号的列表&#xff0c;它可以让内容按照一定的顺序呈现&#…

Postman最新详细安装及使用教程【附安装包】

一、Postman介绍 ‌Postman是一个功能强大的API测试工具&#xff0c;主要用于模拟和测试各种HTTP请求&#xff0c;支持GET、POST、PUT、DELETE等多种请求方法。‌通过Postman&#xff0c;用户可以发送请求并查看返回的响应&#xff0c;检查响应的内容和状态&#xff0c;从而验…