使用 GLSL 进行频率调制?

Mar*_*son 5 audio signal-processing glsl

1. 背景

我使用GLSL绘制给定频率下波形的幅度,如下所示:

GLSL 图

显示像上面这样的简单波形是一项微不足道的任务,只需使用正确的方程即可(此处提供 GLSL 摘录代码)。我现在想做的是显示两个波形之间的频率调制的结果。


2. 研究

经过一些研究,我发现了两种可能的方法来实现这一目标:

  1. 据我所知,使用类似 DSP 的方法,在进行信号处理时建议使用相位累加器(请参阅此处的第一个答案)与查找表相结合。作为一名 GLSL 初学者,我知道这对于 GLSL 着色器来说是不可能的,因为它们无法跨多个 GPU 周期存储和递增变量。

  2. 使用纯数学方法,这涉及诸如 Chowning 的简单 fm 公式之类的方程。 FM 公式 http://img577.imageshack.us/img577/4820/fmformula.png
    该公式在某些情况下效果很好(余弦波调制另一个余弦余弦调制锯齿),但我无法找到一个通用方程在每种情况下都有效(当锯齿波调制余弦时,我希望载波频率由锯齿波幅度调制,但我得到的只是显然未调制的载波)。


3. 问题

  • 解决这个问题的最佳方法是什么?
  • GLSL 是否可以实现类似 dsp 的方法?
  • 如果没有,是否有足够灵活的通用 FM 方程可以完成所有工作?

考虑到我缺乏这里涉及的所有学科(音频 DSP、计算机科学、GPU 编程、数学)的技能,如果我在这里遗漏了一些非常简单的东西,我不会感到惊讶。请耐心等待。

Chr*_*son 4

你是对的,通常的类似 DSP 的相位累加器方法不太适合 GPU 上的并行计算;因此,“纯数学”方法可能是最好的选择。

维基百科频率调制页面(该页面的第一个方程)给出了乔宁的简单 FM 公式到更一般的频率调制函数的推广。关键点是 cos 函数的参数是相位正如维基百科上的方程所示,它是频率的时间积分。在 FM 中,频率通常是载波加调制:例如,根据简单正弦 FM 的乔宁公式,频率作为时间的函数t

f(t) = f_c - M * f_m * sin(f_m * t)
Run Code Online (Sandbox Code Playgroud)

其中f_c是载波频率,M是调制量,f_m是调制频率。这集成到阶段

p(t) = f_c * t + M * cos(f_m * t)
Run Code Online (Sandbox Code Playgroud)

这对应于你的问题方程中的相位。

用锯齿波调制余弦,f(t)将是锯齿波(加上载波频率),因此要找到p(t)锯齿波的时间积分,您需要找到锯齿波的时间积分。这相对简单(它应该是分段二次函数),但是如果您遇到困难,math.stackexchange 的人员应该能够提供帮助。

(注:我在这里用时间来表达一切t,但这同样可以用空间x来代替。)