Android 音频可视化

news2024/11/25 16:42:30

Android音频可视化,指的是将音频的频率绘制到屏幕上,达到一种视觉效果,使播放或录制过程更加生动形象。

Android进行视频可视化涉及的三个主要知识点,其中比较难以理解的傅里叶变换公式。

  • Android原生的Visualizer使用(获取频率数据)
  • 傅里叶变换(音频从时域到频域变换理论)
  • 自定义View(展示频率数据)
一、开发难点
  • Android原生的Visualizer限制

    • 需要录音权限(播放音乐需要录音权限?)
    • 音量为0时,获取不到数据(有可能被误认为Bug)
    • 仅支持AudioTrack,MediaPlayer

    解决方案,自定Visualizer,可以参考末尾文章。

  • 傅里叶变换的理解

    如果从数学角度去推导和验证傅里叶变换,需要学习三角函数及其正交性、微积分、欧拉定理等等。感兴趣可看文章末尾B站视频。在这里,我们暂且知道傅里叶变换可以将函数分解成正余弦函数之和。在工程上应用,可以从时域变换到频域,从而可以观察一些特性。例如在音频上,在频率可以分析大多数男生为低频,女生为高频,可以进行变音处理和声纹模仿等应用。

    通过Visualizer可以拿到傅里叶变换后的数据,或者通过第三方库区计算。

  • 自定义View

    拿到频率数据,如何处理这些数据,并在View进行绘制。

二、Visualizer

比较庆幸的,Android原生为我们提供了Visualizer类,让我们可以快速得从音频获取原始的波形数据或快速傅里叶变换后数据。下面简单介绍其使用。

我们在创建AudioTrack或者AudioRecord实例后,可以获取对应的audioSessionId,用于创建Visualizer实例。

val visualizer = Visualizer(audioTrack.audioSessionId)

通过setCaptureSize函数设置采样率大小,其大小我们一般通过getCaptureSizeRange函数来获取。getCaptureSizeRange函数返回两个int类型数组,第一个表示最小值,第二个表示最大值,用来表示采样值的范围。

 visualizer.captureSize = Visualizer.getCaptureSizeRange()[1]

接着通过setDataCaptureListener获取采样数据回调。

setDataCaptureListener(OnDataCaptureListener listener,int rate, boolean waveform, boolean fft)
  • OnDataCaptureListener 采样数据回调类,拥有onWaveFormDataCaptureonFftDataCapture两个函数,前者回调波形数据,后者回调傅里叶变换后数据。
  • rate 采样的频率,设置范围在0~Visualizer.getMaxCaptureRate()
  • waveform 是否返回波形数据,false的话,OnDataCaptureListeneronWaveFormDataCapture函数不会有回调。
  • fft 是否返回傅里叶变换后数据,false的话,OnDataCaptureListeneronFftDataCapture函数不会有回调。
visualizer.setDataCaptureListener(object : OnDataCaptureListener {
    override fun onWaveFormDataCapture(visualizer: Visualizer?, waveform: ByteArray?, samplingRate: Int) {

    }

    override fun onFftDataCapture(visualizer: Visualizer?, fft: ByteArray?, samplingRate: Int) {

    }
}, Visualizer.getMaxCaptureRate() / 2, false, true)

开始采样:

visualizer.enabled = true

退出界面或者停止,记得设置:

visualizer.enabled = false
三、自定义View

通过给Visualizer设置OnDataCaptureListener之后,可以onFftDataCapture函数中获取快速傅里叶变换后的数据,但如何处理返回后的fft数据呢?

通过FFT的数组格式,获取到每个频率点的实部和虚部。

val n = fft!!.size
val magnitudes = FloatArray(n / 2 + 1)
val phases = FloatArray(n / 2 + 1)
magnitudes[0] = Math.abs(fft[0].toInt()) as Float // DC

magnitudes[n / 2] = Math.abs(fft[1].toInt()) as Float // Nyquist

phases[0] = 0.also { phases[n / 2] = it.toFloat() }.toFloat()
for (k in 1 until n / 2) {
    val i = k * 2
    //取频率点实部与虚部的模
    magnitudes[k] = Math.hypot(fft!![i].toDouble(), fft!![i + 1].toDouble()).toFloat()
}

按照官方代码示例,我们去实数与虚数的模作为数据绘制点,模代表幅值的大小。

拿到数据magnitudes之后在View中进行绘制。

将每个点以条形状的形式画出:

mStrokeWidth = (mRect.width() - (mSpectrumCount - 1) * mItemMargin) / mSpectrumCount * 1.0f;
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.FILL);
for (int i = 0; i < mSpectrumCount; i++) {
    canvas.drawLine(mRect.width() * i / mSpectrumCount, mRect.height() / 2, mRect.width() * i / mSpectrumCount, 2 + mRect.height() / 2 - mRawAudioBytes[i], mPaint);
}

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

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

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

相关文章

someip 入门

什么是someip&#xff1f; SomeIP&#xff08;Scalable Service-Oriented MiddlewarE over IP&#xff09;是一种基于以太网的通信协议&#xff0c;用于汽车领域的通信。它允许不同的汽车电子控制单元&#xff08;ECUs&#xff09;之间通过网络进行通信&#xff0c;以便在车辆内…

网站的搭建与应用|企业APP软件定制开发|小程序

网站的搭建与应用|企业APP软件定制开发|小程序 网站是一种数字化媒体&#xff0c;它可以将我们的信息传递给全球的用户&#xff0c;让更多的人了解我们、了解我们的产品和服务。那么&#xff0c;如何搭建一个网站呢&#xff1f;下面&#xff0c;我将为大家介绍一下网站的建设步…

JavaScript 通过数组对JSON key字段进行排序

这里我以vue为例 不过json排序用的js方式 任何前端项目都可以通过js完成 我们组件代码现在是这样的 <template><div><div v-for "item in navCateList" :key "item.id">{{ item.name }}</div></div> </template>&…

【电源专题】电源芯片手册中的NVDC(narrow voltage DC)功能和电池充电曲线详解

在查看一些充电芯片的规格书时,会发现有一个NVDC功能。其中NVDC的全称是narrow voltage DC ,直译过来是窄电压DC电源架构。此外在规格书里还会发现NVDC Power Path Management字样,也就浊NVDC电源路径管理。 那么什么是NVDC电源路径管理? 如下所示当VIN有输入时(如适配器U…

【LeetCode】剑指 Offer Ⅱ 第7章:队列(6道题) -- Java Version

题库链接&#xff1a;https://leetcode.cn/problem-list/e8X3pBZi/ 类型题目解决方案滑动窗口剑指 Offer II 041. 滑动窗口的平均值队列&#xff1a;滑动窗口 ⭐剑指 Offer II 042. 最近请求次数队列&#xff1a;滑动窗口 ⭐二叉树宽搜剑指 Offer II 043. 在完全二叉树中添加节…

【软件设计师-从小白到大牛】上午题基础篇:第七章 程序设计语言与语言处理程序基础

文章目录 前言章节提要一、编译过程真题链接解释器与编译器特点与区别真题链接 二、文法的定义以及语法推导树真题链接 三、有限自动机与正规式四、表达式真题链接 五、函数调用&#xff08;传值与传址&#xff09;传值调用与传址调用真题链接 六、各种程序语言的特点真题链接 …

ubuntu下yolov7 tensorrt模型部署

文章目录 ubuntu下yolov7 tensorrt模型部署一、Ubuntu18.04环境配置1.1 安装工具链和opencv1.2 安装Nvidia相关库1.2.1 安装Nvidia显卡驱动1.2.2 安装 cuda11.31.2.3 安装 cudnn8.21.2.4 下载 tensorrt8.4.2.41.2.5 下载仓库TensorRT-Alpha并设置 二、从yolov7源码中导出onnx文…

【招招制敌】修改element-ui中el-image 预览图大小的默认尺寸,让展示效果更加有呼吸感

【招招制敌】修改element-ui中el-image 预览图大小的默认尺寸&#xff0c;让展示效果更加有呼吸感 1、问题&#xff08;需求&#xff09;2、解决2.1 深度修改不起效2.2 修改全局样式 3、效果 1、问题&#xff08;需求&#xff09; 在未修改前&#xff0c;el-image 预览图大小的…

Element学习使用

引入: npm方式: npm i element-ui -S 或: cnpm install element-ui --save 要先整合cnpm 在项目中引入: 1.main.js import element-ui/lib/theme-chalk/index.css; import ElementUI from element-ui;Vue.use(ElementUI)引入网址组件方式: <!-- 引入样式 --> <lin…

AI智能助理系统在线提问系统 轻松解答,快速解决问题

今天给大家分享一款AI智能助理系统在线提问系统&#xff0c;也就是人工智能对话系统&#xff0c;&#xff0c;它可以陪你聊天&#xff0c;帮你写文章&#xff0c;帮你写论文&#xff0c;帮你写代码&#xff0c;帮你写小说&#xff0c;帮你创意策划&#xff0c;帮你做Excel表格&…

联合和枚举!!详解

目录 1. 1联合体类型的声明 1.2. 联合体的特点 1.3. 联合体⼤⼩的计算 1.4联合体有什么用&#xff1f; 1.5用联合体判断机器大小端。 2.1枚举类型 2.1.1枚举类型的声明 2.2枚举类型的优点 1. 1联合体类型的声明 和结构体类似&#xff0c;联合体也由成员变量组成&#x…

《UnityShader入门精要》学习4

一个最简单的顶点/片元着色器 一个最简单的顶点/片元着色器 Unity Shader的基本结构。它包含了Shader、Properties、SubShader、Fallback等语义块。顶点/片元着色器的结构与之大体类似 Shader "MyShaderName" {Properties {// 属性}SubShader {// 针对显卡A的S…

安全隐患随手拍小程序搭建-人人都是安全员活动

各生产型企业都会组织开展“安全隐患随手拍”活动&#xff0c;目的就是使广大职工积极发现身边的安全隐患&#xff0c;从而提高自身安全意识&#xff0c;重视安全生产&#xff0c;营造“人人查安全、人人保安全”的良好氛围。 可传统靠微信群组或QQ邮箱上报隐患方式&#xff0c…

Linux服务器快速搭建pytorch

Linux服务器搭建pytorch 文章目录 Linux服务器搭建pytorch一、使用FileZilla传输Anaconda二、激活Anaconda环境1.创建一个虚拟环境2.使用已有项目生成requirements.txt3.在虚拟环境中使用requirements.txt安装其他项目相关库 总结 一、使用FileZilla传输Anaconda 提示&#xf…

微信小程序获取当前日期时间

一、直接使用方式 在小程序中获取当前系统日期和时间&#xff0c;可直接拿来使用的常用的日期格式 //1. 当前日期 YYYY-MM-DDnew Date().toISOString().substring(0, 10)new Date().toJSON().substring(0, 10)//2. 当前日期 YYYY/MM/DDnew Date().toLocaleDateString()//3.…

计算机图形学(有效边表算法)用知识,改变命运的秘密【Morty深度干货】视频学习

目录 1.你所身处的世界&#xff0c;其实并非是一个真实的世界 3、哪些知识&#xff0c;会真正影响到我们的人生 你要用大量的精力去学习对于你的人生能产生实际价值的领域的知识 历史 经济学 金融与投资 心理学 永远不要去相信人&#xff0c;而是要去相信人性 成长的路…

2023年中国禽流感疫苗产量、需求量及市场规模分析[图]

禽流感疫苗是以甲型流行性感冒病毒H5N1、H9N2等毒株经处理后制备的灭活疫苗。用于预防人感染高致病性禽流感病毒感染&#xff0c;控制禽流感的流行。 从产业链来看&#xff0c;禽流感疫苗行业上游为原材料市场&#xff0c;主要有非免蛋、血清、佐剂等。禽流感疫苗行业下游主要为…

博客系统(java,MySQL,HTML)

项目展示&#xff1a; 1.输入 http://127.0.0.1:8080/blog_system/login.html 即可进入登录页面 2.输入正确的用户名和密码后进入博客列表页 要是用户名或密码输入错误&#xff0c;会弹出错误提示框 3.点击查看全文&#xff0c;可以进入博客详情页查看详细信息 4.点击写博客&a…

Studio One6.5中文版本下载安装步骤

在唱歌效果调试当中&#xff0c;我们经常给客户安装的几款音频工作站。第一&#xff0c;Studio One 6是PreSonus公司开发的一款功能强大的音频工作平台&#xff0c;具有丰富的音频处理功能和灵活的工作流程。以下是Studio One6的一些主要特点&#xff1a; 1.多轨录音和编辑&…

树模型(三)决策树

决策树是什么&#xff1f;决策树(decision tree)是一种基本的分类与回归方法。 长方形代表判断模块 (decision block)&#xff0c;椭圆形成代表终止模块(terminating block)&#xff0c;表示已经得出结论&#xff0c;可以终止运行。从判断模块引出的左右箭头称作为分支(branch)…