Android 2.3 可视化器 - 理解 getFft() 方法存在问题

15

第一次来这里,提前对任何破碎的格式表示歉意。

我对DSP完全是新手,只有非常普通的对傅里叶变换的理解。我正在尝试为Android SDK 9构建一个可视化器应用程序,其中包括android.media.audiofx.Visualizer中的Visualizer类。 http://developer.android.com/reference/android/media/audiofx/Visualizer.html

我正在使用的方法getFft()的javadoc如下:

“返回当前播放音频内容的频率捕获。 捕获是8位幅度FFT。请注意,FFT的大小是指定捕获大小的一半,但是返回频谱的两侧,产生与捕获大小相等的字节数。”

首先,“spectrum”的“both sides”是什么意思?此输出与标准FFT有何不同?

这是byte数组的一些示例输出,getFft()被赋予了124个点以使其简单,并且我抓取了前31个bin。以下是前31个bin的振幅:

{123, -2, -23, -3, 6, -16, 15, -10, -8, -12, 9, -9, 17, -6, -18, -22, -8, 4, -5, -2, 10, -3, -11, 3, -4, -11, -8, 15, 16, 11, -12, 12}

非常感谢任何帮助或解释!

编辑:看了一堆图表之后,我发现我的问题之一是Google没有指定使用的单位。几乎所有其他测量都是以mHz为单位进行的,那么假设FFT输出也是以mHz为单位,这样公平吗?有没有可以查看Visualizer类源代码的地方,这样我就可以弄清楚内部实际发生了什么?

我继续获取了getFft()的所有输出。

93, -2, -28, -16, -21, 19, 44, -16, 3, 16, -9, -4, 0, -2, 21, 16, -3, 1, 2, 4, -3, 5, 5, 10, 6, 4, -9, 7, -2, -1, 2, 11, -1, 5, -8, -2, -1, 4, -5, 5, 1, 3, -6, -1, -5, 0, 0, 0, -3, 5, -4, -6, -2, -2, -1, 2, -3, 0, 1, -3, -4, -3, 1, 1, 0, -2, -1, -1, 0, -5, 0, 4, -1, 1, 1, -1, 1, -1, -3, 2, 1, 2, -2, 1, 0, -1, -2, 2, -3, 4, -2, -2, 0, 1, -4, 0, -4, 2, -1, 0, -3, -1, -1, -1, -5, 2, -2, -2, 0, -3, -2, 1, -5, -2, 0, 0, 0, -2, -2, -1, -1, -1, -2, 0, 3, -3, -1, 0

如果我理解正确的话,我的输出应该是从-N到0到N。-N到0应该看起来和0到N一样。但是当我查看这些幅度时,我没有看到任何镜像数据。谷歌似乎表明输出应该在频谱的两侧都从0到N。因此,我应该能够从(output.length-1)/2到output.length-1获取数据。负振幅比采样率快,正振幅比采样率慢。我理解正确吗?


非常感谢您提供的所有信息,我感觉有点不好意思,因为我无法为您的评论做更多的事情,除了给它们投票支持。 - ebolyen
编辑原帖并附上完整输出,尽管数据应该来自光谱的两侧,但似乎不对称。 - ebolyen
是的,我所做的是使用 getCaptureSizeRange()[0],它返回范围内最低的捕获大小。 - ebolyen
幅度与每个频率区间内的声音大小有关系吗?如果有,那么上述方法就不起作用了。 - ebolyen
我已经将一些测试用mp3文件通过它,这些文件覆盖了从16赫兹到20千赫兹的范围,但是并没有看到原始数据和声音或修改后的数据和声音之间有任何相关性。我开始认为这可能是个无望的事情。 - ebolyen
显示剩余3条评论
2个回答

9
如果有需要的话,我创建了一个可视化工具。它可以接收MediaPlayer的输出并显示出可视化效果。无论是正常波形还是FFT数据都可以使用它: https://github.com/felixpalmer/android-visualizer 它包含将getFft()输出转换为有意义的可视化内容的代码。

谢谢分享,非常有帮助!关于你如何处理FFT...你计算分贝值的方式是否有任何规律,还是只是随意缩放到看起来不错的数值?我看过一个FFT教程,它说要根据测量到的最高幅度对每个频率进行归一化,但我觉得这样会让高音看起来很刺耳。也许可以基于A加权来缩放这些分贝值,以获得每个频率上的真实比例尺度。 - Tenfour04
说实话,已经有一段时间了 - 但我认为我刚刚按照你的建议将其缩放到了一个看起来不错的大小。如果你真的在意的话,那么我想你可以每次达到新的最大值时重新缩放,甚至可以包括基于时间的衰减到最大值,这样一个响亮的部分就不会扭曲其他部分。 - pheelicks

8

FFT 输出样本 k 的频率由以下公式给出:

Fk = k * Fs / N,    k = 0,1,...,N-1 

where

  • Fs 是时间序列输入的采样频率
  • N 是用于计算FFT的样本数

频谱的两侧指的是FFT输出中的正频率和负频率。 FFT强制频率输出成周期为Fs。 如果您查看FFT输出,它覆盖了从0到Fs的频率。 通常通过将FFT输出从0.5 * Fs -> Fs移动到-0.5 * Fs -> 0来查看范围为-0.5 * Fs到0.5 * Fs的频谱,因为它们由于周期性而相等。

对于音频处理中所使用的实值信号,负频率输出将是正频率的镜像。 因此,在分析实际信号时,通常仅使用频谱的一侧。

另一个重要的点是0.5 * Fs的显着性,它被称为奈奎斯特频率。 信号只能准确表示高达Nyquist频率的频率,而超过该频率的任何内容都将回折(折叠)回频谱,导致失真。

因此,仅应关注可视化目的下对应于从0到Fs / 2的频率范围的FFT输出样本,因为它们是具有采样率Fs的实际信号的有意义的样本。


非常感谢您!这篇文章非常简洁明了,正是我过去一周一直在寻找的! - ebolyen
那么,在我的情况下,FFT幅度的输出只有0和1.414214,基本上只是给我最小值和最大值? - Big Money

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接