Search code examples
mathformulatrigonometrygodotgdscript

I've figured out how to program a basic sine wave, but I'm struggling with AM/FM (Amplitude/Frequency Modulation)


I've been following this guide, but I'm having trouble understanding/implementing the formula for AM/FM (Amplitude/Frequency Modulation) in my code. This is how they appear:

f(t) = A(t) * sin(2pi * f * t)

f(t) = sin(2pi * ((f + A(t)) * t))

According to the guide/wiki, A(t) is the "message signal" and if I'm increasing the amplitude/frequency linearly, then A(t) = t, where t is just the time, so my code looks like this:

var time: float = 0.0
var frequency: float = 4.0
var amplitude: float = 200.0
var point = Vector2(50.0, 200.0)

func _physics_process(delta):
    time += delta
    point.y += amplitude * time * cos(frequency * time) * delta
    point.x += 100.0 * delta
    $Line2D.add_point(point)

AM:

AM

I'm able to get the amplitude to increase, however, the frequency increases too. Am I doing this wrong? (I use cos() instead of sin() so I don't have to do 2 * pi)

Similarly, I tried doing Frequency Modulation:

func _physics_process(delta):
    time += delta
    point.y += amplitude * cos((frequency + time) * time) * delta
    point.x += 100.0 * delta
    $Line2D.add_point(point)

FM:

FM

The frequency increases, but the amplitude decreases.

I've seen other posts that describe the frequency increase as a "chirp", which has the same function as the Frequency Modulation. For reference, this was programmed with GDScript in Godot, which has the (0,0) in the top left, so +X is right and +Y is down.


Solution

  • AM Modulation Example

    extends Control
    
    var time: float = 0.0
    var frequency: float = 4.0
    
    var carrier_amplitude : float = 1.0
    var carrier_frequency : float = 0.2
    
    const pixels_per_x = 100; # zoom on x
    const pixels_per_y = 100; # zoom on y
    
    func _physics_process(delta):
        var point : Vector2
    
        time += delta
    
        var _signal = cos(2 * PI * frequency * time)
        var modulating_signal = carrier_amplitude * cos(2 * PI * carrier_frequency * time)
    
        point.y = pixels_per_y * (_signal * modulating_signal)
        point.x = pixels_per_x * (time)
    
        $Line2D.add_point(point)
    

    AM Modulation

    FM Modulation Example

    extends Control
    
    var time: float = 0.0
    var frequency: float = 2
    
    var modulation_index : float = 4
    var modulation_frequency : float = 0.2
    
    const pixels_per_x = 100; # zoom on x
    const pixels_per_y = 100; # zoom on y
    
    func _physics_process(delta):
        var point : Vector2
    
        time += delta
    
        var fm_signal = cos( (2 * PI * frequency * time) + modulation_index*sin(2 * PI * modulation_frequency * time) ) # this is another method that adds offset onto phase
        
        point.y = pixels_per_y * (fm_signal)
        point.x = pixels_per_x * (time)
    
        $Line2D.add_point(point)
    

    FM modulation