Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Frequency Modulation using GLSL?

1. Context

I'm using GLSL to plot the amplitude of a waveform at a given frequency like this:

GLSL plot

Displaying simple waveforms like the ones above is a trivial task, it's just a matter of using the right equations (GLSL excerpt code available here). What I'm trying to do now is to display the results of a frequency modulation between two waveforms.


2. Research

After some research I've found two possible ways to accomplish this:

  1. Using a dsp-like approach, as far as I know using phase accumulators (see first answer here) in combination with lookup tables is the suggested approach when working with signal processing. As a GLSL beginner I understood that this is not possibile with GLSL shaders because they can't store and increment variables across multiple GPU cycles.

  2. Using a pure mathematical approach, this involves equations like Chowning's simple fm formula. FM formula http://img577.imageshack.us/img577/4820/fmformula.png
    That formula works great in some situations (cosine wave modulating another cosine or cosine modulating a sawtooth) but I wasn't able to find a general equation that would work in every case (when a sawtooth wave modulates a cosine I expect the carrier frequency to be modulated by sawtooth amplitude, but all I get is the carrier wave apparently unmodulated).


3. Questions

  • What would be the best approach to solve this problem?
  • Is a dsp-like approach possible with GLSL?
  • If not, is there any general FM equation flexible enough to do all the work?

Considering my lack of skills in all the disciplines involved here (audio dsp, computer sciences, gpu programming, maths) I won't be surprised if I'm missing something really simple here. Please be patient.

like image 386
Mark Anderson Avatar asked Oct 07 '22 01:10

Mark Anderson


1 Answers

You're right that the usual dsp-like approach of phase accumulators isn't well suited to parallel computing on a GPU; the 'pure mathematical' method is therefore probably the best bet.

The generalisation of Chowning's simple FM formula to more general frequency modulation functions is given on the Wikipedia page for Frequency Modulation (the very first equation on that page). The key point is that the argument to the cos function is the phase, which, as the equation on Wikipedia indicates, is the time integral of the the frequency. In FM, the frequency is typically a carrier plus a modulation: for example, with Chowning's formula for simple sinusoidal FM, the frequency as a function of time t is

f(t) = f_c - M * f_m * sin(f_m * t)

where f_c is the carrier frequency, M is the modulation amount, and f_m is the frequency of modulation. This integrates to the phase

p(t) = f_c * t + M * cos(f_m * t)

which corresponds to phase in the equation in your question.

To modulate a cosine with a sawtooth, f(t) would be a sawtooth wave (plus a carrier frequency), and so to find p(t) you would need to find the time-integral of a sawtooth wave. This is relatively straightforward (it should be a piecewise-quadratic function), but people at math.stackexchange should be able to help if you have difficulty.

(Note: I've phrased everything here in terms of time t, but this could equally well be space, x, instead.)

like image 99
Chris Johnson Avatar answered Oct 12 '22 09:10

Chris Johnson