多彩网

androids音频可视化:让歌词跟着音乐舞动

androids音频可视化:让歌词跟着音乐舞动

liwenzhen 2024-12-30 设备销售 3 次浏览 0个评论

androids音频可视化:让歌词跟着音乐舞动



/   今日科技快讯   /

近日,据外媒援引知情人士消息透露,微软计划在下个月举行的年度开发者大会上推出该公司首款专为支持人工智能(AI)而设计的芯片。此举是多年来努力的结果,可能有助于微软减少对英伟达AI芯片的依赖。

随着需求的激增,英伟达的AI芯片一直供不应求。微软的芯片类似于英伟达图形处理器(GPU),是为训练和运行大语言模型的数据中心服务器设计的,大语言模型是OpenAI的ChatGPT等对话式人工智能功能背后的软件。微软的数据中心服务器目前使用英伟达的GPU,为包括OpenAI和Intuit在内的云客户以及微软生产力应用中的人工智能功能提供支持。

/   作者简介   /

本篇文章转自却把清梅嗅的博客,文章主要分享了如何制作一个频谱特效,相信会对大家有所帮助!

原文地址:
http://juejin.cn/post/7254812719350284345

/   前言   /

音频可视化,一言以蔽之,就是声音到图像的转换。

随着视觉工业时代的到来,用户逐渐重视产品的极致体验,在市场上诸多优秀的音乐类APP中,频谱动效 是一个经典的应用场景:

图片来源:咪咕音乐

本文以 androids 端为例,从音频信号数据的获取、数据的处理、常见问题几方面进行叙述,针对androids端音频可视化的实现,提供一个通用可行的方案。

/   频谱数据的获取   /


绘制频谱动效,首先要获取歌曲对应的旋律,这里需要先对信号处理中 时域 和 频域 的概念有一个基本的认识:

时域(时间域)是描述数学函数或物理信号对时间的关系,例如一个信号的时域波形可以表达信号随着时间的变化;
频域(频率域)是描述信号在频率方面特性时用到的一种坐标系,纵轴是该频率信号的幅度,也就是通常说的频谱图。

对于我们而言,时域虽然是真实存在,但信号的表达晦涩难懂;而频域相比前者则更加简洁直观。因此,开发者需进行时域转频域的操作,这里我们借助傅里叶变换,将讯号分解成振幅分量和频率分量,将函数的时域(红色)与频域(蓝色)相关联:


借此我们达到了从频域对模拟信号观察的目的,并将频谱展现给用户,从而提升用户听歌时沉浸式的体验感。接下来,笔者针对时域转频域中使用到的FFT算法(非常重要)进行简单的介绍。


针对信号分析的最基本方法,称为离散傅里叶变换(Discrete Fourier Transform,下称DFT)傅里叶分析方法,它把信号从时域变换到频域,进而研究信号的频谱结构和变化规律。


在某些复杂场景下,比如上图对应的有限长序列,使用 DFT 计算量会很大,很难实时地处理问题,因此我们引出了快速傅里叶变换(fast Fourier transform,下称FFT)算法,其将DFT的运算量减少了几个数量级。

引入了这个概念,读者可以理解,为什么总是需要通过FFT算法,拿到对应的数据输出才能完成绘制,为了便于理解,我们将对应输出的byte[]称为FFT,就和下面androids官方的API声明的一样:

public int getFft(byte[] fft) {
  //...
}

FFT算法复杂且易出错,androids官方也提供了简单的API —— Visualizer类便于开发者调用,只需要传入audiosesession的ID,系统就可以自动捕获当前设备在播音频的信号,完成fft的转换后,再回调给开发者,开发者直接进行频谱的绘制即可。

简单概括其优势有:

  • 系统自动完成音频信号幅度的采样,无需适配,适用于任何原生和三方播放器;
  • 系统自动完成FFT转换,开发者通过回调拿到数据直接绘制,上手成本低。

因此,原生 Visualizer API 理所当然成为了实现方案的首选,但随着实现的深入,更多问题不断暴露出来:

  • 音量为0时,回调函数不会返回 fft 数据;
  • 类本身只是一个API的壳,真正实现都是在native层,难以针对性进行修改和扩展;
  • 在某些特殊机型有兼容性问题;
  • 由于Visualizer API内部是从当前系统获取音频信号,因此使用前必须授予麦克风权限,否则没有任何返回。

在实际开发开发中,上述缺陷都是产品无法接受的,尤其是3、4两条,随着近两年国家推行一系列用户隐私保护的政策,展示UI特效需要麦克风权限是无法说服任何人的,综上所述,原生Visualizer API方案被果断抛弃。


现在又回到了原点,我们需要自定义Visualizer。具体的思路是,在数字化音频时,我们会对信号幅度进行频繁的采样,这称为 脉冲编码调制(下称PCM)。正如上文对时域的描述,振幅随之被量化,但并不直观,因此,我们需要针对PCM信号进行结构,即FFT算法。

——之前这一切都是交由原生Visualizer API自动完成的,现在由我们自己控制和实现,最终,我们得到了每个时刻声音的频率,并将这些幅度在页面上展示给用户。


如何获取当前音频的PCM数据?这里可以让底层播放器提供,社区比较完善的三方播放器(ijkplayer、ExoPlayer)等都提供了对应支持,开发者可以根据自身业务调用API或修改源码。

我们不断获得一帧帧的PCM数据,通常这是一个ByteBuffer,这些byte可能来自多个channel,简化处理可以取所有channel的平均值,这之后拿到这些数据进行傅里叶变换。

宏观上理解傅立叶变换,即N个时域点变换为N个频域点,瓜分采样频率Fs,频率间隔为△f=Fs / N,根据奈奎斯特采样定理,采样频率是信号最高频率的2倍以上,故有效频点数为N / 2,函数如下:


如上文所说,计算机直接进行傅立叶变换复杂度为O(N^2),一般是采用快速FFT算法,复杂度降低为O(N*LogN),我们无需手动实现,社区中已有成熟稳定的三方库提供这样的支持。此外,傅立叶变换后的频域点为复数域,不方便做可视化,处理方式是忽略相位信息,仅取(实数)幅度信息。


即使FFT算法相比较DFT有一定的优化,但实际执行的性能消耗依然不能忽视,如何针对这一点进行优化?

网易云音乐讲的这篇文章,文章地址如下:
http://juejin.cn/post/6873253309944168456

提到这个思路:首先,将FFT算法执行放在播放进程的native层中,通过JNI调用回调给java层后,再将结果数据跨进程传输给主进程,再进行后续的绘制操作:


除此之外,由于PCM每一帧都包含大量的数据,最初单次的结果FFT是一个长度为4096的float[]——我们可使用这些频率立即绘制4096个条形图,但实际中根本没有这样的场景。因此,在FFT算法执行前,我们可以对不同频段进行初始数据的二次采样。

根据声学,人耳能容易的分辨出100hz和200hz的音调不同,但是很难分辨出8100hz和8200hz的音调不同,尽管它们各自都是相差100hz,可以说频率和音调之间的变化并不是呈线性关系,而是某种对数的关系。因此,我们音频的采样以低频段为主,高频段为辅,详细可参考维基百科。

这样,在FFT算法执行时,单次输入的数据源的大小从初始的4096降低到了64或128,算法执行速度大幅提升。

/   数据的处理与绘制   /

拿到FFT数据后,接下来针对数据各个阶段遇到的问题,分步进行处理。


首先,因为数据是从不同频段的不同采样点进行获取,因此单个连续数据区间内会存在若干个数据突然很高或很低的情况,这里对数据进行简单的处理,进行 加权平均:



对于某一帧的数据而言,即使经过简单的加权平均处理,对文章开头中间的柱状特效而言,展示效果依然不佳,如何将参差不齐的数据经过平滑处理,形成视觉上的包络效果?这里我们引入曲线拟合,顾名思义,就是用连续曲线近似地刻画或比拟平面上离散点组所表示的坐标之间的函数关系的一种数据处理方法。

最小二乘法是解决曲线拟合问题最常用的方法。其一般形式是:


引入之后,离散化的数据点形成一条光滑的曲线,能明显的提升用户的观感体验。


经过以上几步处理,单帧效果得到明显改善,但随着划入时间维度之后,相邻两帧的展示效果有明显的跳跃性,对于用户而言就好像掉帧一样。这里我们引入衰减系数,每一帧数据绘制前,与上一帧数据进行对比,当单个频率点数据发生较高的抖动,通过衰减系数对抖动进行抑制。

/   其他问题   /

这个问题通过gif图是无法体现的,但用户在听音乐时会立即注意到:频谱特效跳跃的太早了,总是比我们实际听到的音乐节奏快了一步。

导致这个现象是因为自定义的播放器在数据传递给androids系统的AudioTrack之前,我们已经在拿处理好的FFT进行绘制了,而播放器内部有自定义的缓冲区,这会导致视觉效果领先于音频效果,导致延迟输出。

解决这个问题也非常简单,只需针对PCM数据,参考缓冲区相关源码,再定义一份对应的ByteBuffer即可。


对于频谱绘制的技术方案,可以选择系统的Canvas API进行自定义View,将数据的相关运算处理在CPU中执行。

考虑到频谱动效本身偏UI的展示,且与用户没有直接、复杂的交互,以及性能方面的思量,最终使用了OpenGL ,并将数据运算相关处理通过矩阵变换,直接交给GPU计算并渲染。

/   小结   /

本文针对androids端频谱特效实现的整体流程进行概括性的描述,由于频谱动画属于定制化较高的效果,读者无需纠缠于细节,而是将目光聚焦在实际问题的解决思路上。实际开发中,可根据自身产品的需求,灵活运用开发。

推荐阅读:
我的新书,《第一行代码 第3版》已出版!
原创:写给初学者的Jetpack Compose教程,Modifier
100行代码实现androids与Windows局域网文件夹同步

欢迎关注我的公众号
学习技术或投稿

androids音频可视化:让歌词跟着音乐舞动


长按上图,识别图中二维码即可关注


转载请注明来自常州多彩网超声波设备有限公司,本文标题:《androids音频可视化:让歌词跟着音乐舞动》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!
Top
多彩网