使用FFT(快速傅里叶变换)和/或DSP的帮助

4
我正在尝试制作一个屏幕闪烁的应用程序,根据音乐(例如治愈音频等)来闪烁屏幕。我已经制作了播放器,并知道如何让屏幕闪烁,但我需要根据音乐使屏幕闪烁非常快,例如如果音乐加速,屏幕闪烁将会更快。我理解我可以通过FFT或DSP来实现这一点(因为我只需要知道当频率从某个赫兹数上升时,比如20,改变颜色,使屏幕闪烁)。
但我发现我什么也不懂,甚至不知道如何将其实现到我的应用程序中。
有人能帮我学习其中任何一种吗?我的电子邮件是sismetic_chaos@hotmail.com。我真的需要帮助,我已经困在那里三天了,没有编码或做任何事情,试图理解,但我不行。
PS:我的应用程序是用C++和Qt编写的。
PS:感谢您花时间阅读此内容并愿意提供帮助。
编辑:感谢所有回答,问题还没有得到解决,但我感谢所有回答和信息。谢谢大家。

2
如果你没有任何DSP经验,那么这可能会非常困难。我建议去dspguide.com查看免费在线书籍。这是我几年前开始接触DSP时的起点,当时我没有任何经验。然而,如果你没有数学背景来理解它,那么你需要先学习数学。 - Justin Peel
我不明白你所说的“音乐(它将是频率……”是什么意思。你是否指有一个主导频率,你想要确定那个主导频率是多少? - mtrw
嗯,我不知道该怎么说,因为英语不是我的母语,我的意思是这样的:http://www.youtube.com/watch?v=5tJGS2WKidY&feature=related - Sismetic
我不认为我有足够的数学背景,但我擅长并喜欢数学,但我只有17岁,除了“数字”之外,我最后一次接触与数学相关的东西已经是2-3年前的事情了,所以我可能有点生疏。 - Sismetic
5个回答

3

FFT的输出可以给出音频样本的频谱,但从FFT输出中提取节奏可能不是您想要的方法。

您可以使用峰值检测来识别通常在音乐的“下拍”上发生的音量“峰值”。如果您可以识别出下拍,则可以使用类似bpmdatabase.com这样的资源找到歌曲的节奏。 节奏将告诉您闪烁的速度,而您检测到的峰值将告诉您何时开始闪烁。让您的应用程序监视闪烁,以确保它们通常与峰值同时发生(如果两者开始分歧,则节奏可能在歌曲中改变)。

听起来很简单,但实际上这是一件非常复杂的事情。您可能需要阅读this SO question以获取更多信息。那里的答案中有一些优质链接。

如果我完全误解了你的意图,你需要做FFT以完成其他任务,那么你可能想要考虑使用现有的FFT库来为你完成繁重的工作。一些例子包括 FFTWKissFFT

@Sismetic- 如果你只是想做这个,那就不用担心FFT了。看看我在其他SO问题中链接的一些链接,了解如何解决这个问题(特别是GameDev文章)。 - bta
我不是,我的父亲是,在已经生成的音调上,这个应用程序是为我执行的,我猜我需要获取音调的频率。 - Sismetic
每次它们都会不同。你知道一个测量频率的工具吗?如果你知道,能否向我解释如何在应用程序上使用它(我不知道如何使用插件或任何东西,我从未这样做过)?对于我回复不及时感到抱歉 :( - Sismetic
在你的应用程序中,没有简单的方法来解释如何做到这一点。我是在大学的DSP课程中学会的,但根据你的承认,我不认为你现在具备足够的数学背景来做到这一点。这就是为什么我试图找到一个不涉及任何DSP工作的不同方法来解决这个问题。尝试通过dspguide.com上的书籍来解决,并看看你是否有足够的数学经验至少完成“基础”和“基本原理”部分(大约13章)。如果你能理解那本书中的数学内容,你应该能学到你所需要知道的一切。 - bta
好的,我会尝试在线阅读它,因为它看起来非常重要。我曾尝试打印它,但它是按章节划分的,我认为它并不是很重要,我错了。感谢你的所有帮助。 - Sismetic
显示剩余6条评论

3
这是一个比FFT更难的问题。我将简要描述我在为专业DJ设备编写软件时如何实现节拍检测。
首先,您需要减少处理的数据量,因为每秒只有两三个节拍,但有成千上万个样本。您还需要查看不同的频率范围,因为某些类型的音乐在低音线中携带节奏,而其他音乐则在打击乐器或其他乐器中携带节奏。因此,将信号通过几个带通滤波器(我选择了8个滤波器,每个滤波器覆盖一个八度音程,从低音到高音)并对每个频段进行降采样,通过平均几百个样本来降低每个频段的数据量。
每隔几秒钟,您将在每个频段中获得大约一千个样本。下一个工具是自相关,用于识别音乐中的重复模式。自相关的峰值告诉您可能的节拍是什么;但是,您需要制定一些启发式算法来比较所有频率段以找到可以确信的节拍,并避免误导性的重音。如果您能做到这一点,那么您就可以合理猜测节奏,但无法确定相位(即何时闪烁屏幕)。
现在,您可以查看音频数据的平滑版本以查找峰值,其中一些可能对应于节拍。最初,寻找几秒钟内最强的峰值,并将其作为下行拍。结合第一阶段估计的节奏,您可以预测下一个节拍的到来时间,并测量您实际看到类似节拍的地方,并调整您的估计以更接近数据。您还可以基于预测节拍与测量峰值匹配程度的好坏维护置信度水平;如果置信度过低,则重新从头开始进行节拍检测。
这有很多琐碎的细节,我花了几周时间才使其正常工作。这是一个困难的问题。
或者,对于简单的可视化效果,您可以仅检测峰值并为每个峰值闪烁屏幕;这可能已经足够好了。

我该如何检测峰值? - Sismetic
@Sismetic:一种简单的方法是跟踪平均振幅,并查找明显大于平均值且在其小范围内(例如100毫秒)所有其他样本中最大的样本。您可以通过整流信号(使负样本变为正样本),平滑信号(使用低通滤波器)并寻找攻击(振幅突然增加)来获得更好的结果,但这更加复杂。 - Mike Seymour
我该如何获取样例?抱歉,我真正的新手。 - Sismetic
@Sismetic:抱歉,我不知道如何获取音频流;这完全取决于您用来播放音频的工具。您说您制作了播放器-您能以某种方式从中获取音频数据吗? - Mike Seymour
我不知道怎么做。 - Sismetic

0

听起来你可能想让你的可视化器与音乐一起闪烁屏幕。我不认为计算FFT会对你有所帮助。在任何时刻,都会有许多同时存在的频率成分,遍布整个音频频谱(大约20 Hz到20 kHz)。但你可能更感兴趣的是音乐节奏(每分钟节拍数——更像是5 Hz或以下),这在原始音频信号的FFT中不会出现。

你可能需要更简单的东西——某种实时峰值检测。每当你看到一个峰值高于平均音量的某个阈值时,让你的屏幕闪烁。

当然,更复杂的可视化可能会充分利用FFT,但你所描述的不是其中之一。


我该如何进行实时峰值检测? - Sismetic
2
@Sismetic:请不要误解我的意思,但我认为你可能需要一份基础音频处理教程,而不是适用于 Stack Overflow 的简单答案或代码片段。bta 发布了一些不错的链接——从那里深入挖掘,你会找到一些不错的信息,尽管不一定是 C++ 的。对于初学者的编程项目来说,你正在尝试做的事情有点困难……祝你好运! - Jim Lewis
谢谢Jim,我知道这有点难,但是这是我父亲留下的,这真的是我的第一个项目,在学习C++三个月后,但我很自信,这是我认为我会遇到的最后一个问题,因为我已经解决了其他所有问题(显然)。感谢您的回答,我很感激。 - Sismetic

0

我的建议是找一个可以为您完成此操作的库。除非您有大量数学支持,否则我认为您将浪费大量时间尝试学习FFT,而您真正想要的只是一些“每分钟基本命中率”数字,以便您可以相应地调整图形。

请查看这篇类似的帖子: 这里

我花了大约三个星期的时间理解FFT背后的数学知识,然后又花了一个星期的时间使用这些概念在Matlab中编写了一些东西。如果您在三天后感到沮丧,请不要尝试自己编写。

我希望这是有用的建议,而不是令人泄气的。

-Brian J. Stinar-


你能给我一个实际的例子来说明如何实现它吗? - Sismetic
如果我处在你的位置,我会开始尝试使用“Vamp插件”系统。从我的了解来看,它们有一种方法可以将音频轨道和采样方法作为输入,并向您返回一个节奏数据结构,其中包括每分钟的节拍数以及一些时间机制来将节奏与音频轨道中的时间点相对应。然而,很抱歉我没有准备好可工作的示例。 - Brian Stinar
谢谢,我会研究一下Vamp插件。 - Sismetic

0

正如之前的回答所指出的那样,FFT 可能不是您需要解决问题的工具,因为它需要节奏检测而不是频谱分析。

关于使用 FFT 可以做什么 - 以及如何将特定的 FFT 实现集成到 Qt 应用程序中,请参阅这篇博客文章,其中描述了我开发的频谱分析器演示。演示的代码随 Qt 本身一起提供,在demos/spectrum目录中。


我看到了,右侧的红色条正是我想要的,我正在查看代码以了解它们是如何实现的:P 谢谢你的提示。 - Sismetic
右侧的红色条由LevelMeter类渲染。它显示两个信号:RMS信号电平,应用了少量平滑处理;以及最近的峰值信号电平,随时间衰减。请注意,此信号将无法为您提供准确的节奏速度测量,因为通常包含太多噪音。如其他回答所指出的那样,您需要进行更复杂的处理来检测音乐的节奏。 - Gareth Stockwell
哦,谢谢你告诉我在哪里找到那个特定的部分。非常感谢,就今天而言,你的帖子是我发现的最有用的(尽管每个人的帖子都非常有用)。 - Sismetic

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