Android 音频可视化

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

相关推荐
2501_944525541 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
松☆3 小时前
Dart 核心语法精讲:从空安全到流程控制(3)
android·java·开发语言
_李小白4 小时前
【Android 美颜相机】第二十三天:GPUImageDarkenBlendFilter(变暗混合滤镜)
android·数码相机
colicode6 小时前
语音消息接口应用开发:如何通过API发送个性化音频或TTS语音内容
音视频
小天源7 小时前
银河麒麟 V10(x86_64)离线安装 MySQL 8.0
android·mysql·adb·麒麟v10
2501_915921437 小时前
傻瓜式 HTTPS 抓包,简单抓取iOS设备数据
android·网络协议·ios·小程序·https·uni-app·iphone
kirk_wang7 小时前
Flutter艺术探索-Flutter三方库鸿蒙适配实战:从原理到实践
flutter·移动开发·flutter教程·移动开发教程
美狐美颜sdk7 小时前
直播美颜sdk与智能美妆技术解析:实时人脸算法如何驱动新一代互动体验
人工智能·音视频·美颜sdk·视频美颜sdk·美狐美颜sdk
csj508 小时前
安卓基础之《(20)—高级控件(2)列表类视图》
android
JMchen1238 小时前
Android计算摄影实战:多帧合成、HDR+与夜景算法深度剖析
android·经验分享·数码相机·算法·移动开发·android-studio