I'm using GLSL to plot the amplitude of a waveform at a given frequency like this:
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.
After some research I've found two possible ways to accomplish this:
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.
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).
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.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With