Java 为什么FFT提供的可视化工具输出与Windows Media Player不同?

Java 为什么FFT提供的可视化工具输出与Windows Media Player不同?,java,android,fft,visualizer,Java,Android,Fft,Visualizer,我正试图用这个类在android中实现一个音频频谱分析仪 我在OnDataCaptureListener()事件的onFftDataCapture()方法中获取FFT数据,并使用drawLines()在画布上绘制该数据 但是光谱显示不正确。我只能在图表的左侧看到变化。但在Windows Media Player中,同一首歌的输出是不同的。我错过了什么 有人能帮我举个例子或链接吗 代码 mVisualizer.setDataCaptureListener( new Visu

我正试图用这个类在android中实现一个音频频谱分析仪

我在
OnDataCaptureListener()
事件的
onFftDataCapture()
方法中获取FFT数据,并使用
drawLines()
在画布上绘制该数据

但是光谱显示不正确。我只能在图表的左侧看到变化。但在Windows Media Player中,同一首歌的输出是不同的。我错过了什么

有人能帮我举个例子或链接吗

代码

mVisualizer.setDataCaptureListener(
            new Visualizer.OnDataCaptureListener() {

                public void onWaveFormDataCapture(Visualizer visualizer,
                        byte[] bytes, int samplingRate) {}

                public void onFftDataCapture(Visualizer visualizer,
                        byte[] bytes, int samplingRate) {
                    mVisualizerView.updateVisualizer(bytes, samplingRate);
                }
            }, Visualizer.getMaxCaptureRate() / 2, false, true);
onPaint()

for(int i=0;i
其中,
mVisualizer
是可视化工具类对象,
mBytes
是从
onFftDataCapture
事件获取的FFT数据

您可以阅读有关事件返回的FFT数据的更多信息

这是我在FFTDataCapture()上获得的值。

[90, -1, -27, 102, 13, -18, 40, 33, -7, 16, -23, -23, -2, -8, -11, -9, -8, -33, -29, 44, 4, -9, -15, -1, -2, -17, -7, 1, 1, 0, 3, -11, -5, 10, -24, -6, -23, 1, -9, -21, -2, 4, 9, -10, -14, -5, -16, 8, 6, -16, 14, 3, 7, 15, 10, -2, -15, -14, -5, 10, 8, 23, -1, -16, -2, -6, 4, 9, -1, 0, 0, 9, 1, 4, -2, 6, -6, -6, 8, -4, 6, 6, -4, -5, -5, -2, 3, 0, -1,0,-7,0,2,1,0,1,-1,0,-1,1,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,0,-1,-1]

任何想法,链接将是有益的

更新@Chris Stratton

现在我正在播放文件并拍摄了屏幕截图。你现在有什么建议

在@ruhalde建议后更新

现在我正在播放这个文件,这个文件生成了以下输出


准确地找出行为与预期的不同可能是有用的(希望能够理解原因)通过在windows参考和正在开发的android应用程序上播放已知大小的正弦信号。每次测试一个合成频率,查看它在每个屏幕上的位置、大小和特定性以及明显的大小

例如,您可能会发现覆盖频率范围中的差异,或者可能有一个版本正在对数轴(数十或八度)而不是线性轴上绘制频率

如果您的数据源是麦克风,则输入电路或设置中也可能有衰减


链接文档没有解释正在使用的窗口函数。此外,通过原始FFT输出,您可以在相邻的存储单元之间分配能量,因此可以生成更一致的结果,将每个点显示为两个或三个相邻存储单元的平均值。

我将看到您的代码中存在一些缺陷,主要是在这里>>

Visualizer.getMaxCaptureRate() / 2
无需使用最大捕获速率/2,只需将一个值置于每秒10到30次之间(根据文献记载,为毫秒,即10000到30000次之间),这对于不闪烁和不给Visualizer内的资源施加太大压力来说已经足够了。此外,只绘制20到20Khz之间的量级,即可听频谱,在代码中,您绘制的每个频率都在0和捕获速率/2之间,这是最大速率/2,谁知道哪个频率更高。。。

除此之外,你需要一个纯正弦波,不断地从0到20Khz扫描,看看它是什么样子,如果它是一个没有压缩的原始文件就更好了。我不会使用任何OGG、MP3或PCM文件,我会尝试一个未压缩的波形,也不会使用一个方波,因为它会在米内产生很多尖峰

从中获取扫描文件
您是否尝试过运行另一个线程,轮询getFft(),而不是使用OnDataCaptureListener???。我将在一个可运行的、更新的UI中尝试这种方法,并使用RunnutIthread()方法。

您是否在每次重绘频谱之前清理画布?我只是(疯狂地)猜测碎片是从以前的绘图中遗留下来的…我正在调用
updateVisualizer()
方法中的
invalidate()
。它正在执行该任务。我认为您的dB和幅值公式不正确。第一个幅值是通过与SQR(2)的多次叠加来计算的。同样,在dB中,你需要除以一个极限,因为dB始终是一个与某事物相关的度量值。你没有被你的极限跳水,所以你的极限是1 dB,这就是为什么你的图形如此怪异的原因。检查这里的公式,你不想快速扫描,因为要调试FFT分析仪,你希望它只查看一个频率存在的输入。如果该频率在操作过程中发生变化,您将得到更复杂的结果,从而更难理解问题。-如果您必须使用文件而不是活动生成器,则最好使用10个文件,每个文件具有一个频率。此外,此最新图表根本不是有效的输出-可能您的屏幕截图捕捉到了在两个不同的绘图之间重画的过程,显示两个不同频率的扫描。为了给你提供信息,我需要我的媒体播放器的频谱,我将尝试建议“已知幅值正弦”。我建议不要使用方波。你知道方波的频谱是什么样子吗?也就是说,你可以看到一些有趣的事情-第三个峰值有我提到的相邻箱子之间的能量分配问题。看起来你有一个合理的响应,高达15 KHZ,然后可能从
Visualizer.getMaxCaptureRate() / 2