- Home /
Math - Changing the frequency of a sine wave in real-time
I need an algorithm that can output a sine wave of varying frequency, with this frequency being changed dynamically. I started with this:
public void Update()
{
time += Time.deltaTime;
float sine = Mathf.Sin(time * frequency);
}
The problem occurs when the frequency is changed. Normally as the time variable increases, the sine wave is advanced by that amount, and multiplied by the frequency variable. But when the frequency is reduced while the sine wave is being generated, the wave is temporarily "brought back in time" because the time variable is being multiplied by a smaller number.
So is there an algorithm that can change the frequency of a sine wave in real-time?
Your function does change the frequency of the sine wave. So it seems the problem here isn't actually in changing the frequency, but maintaining the phase of the sine wave at point time.
That's what I meant to say, but I wasn't farmiliar with the terms.
I think what you are looking for is this:
float sine = $$anonymous$$athf.Sin(time * frequency + phase);
How to set the phase so that the waves don't advance/retreat will depend on your anchor point. I'd have to see more of your code and/or a better description of the anchor. In order to get a higher frequency, you will have more waves in the same amount of space, so you can only anchor at one point.
The only other code would be adding the given value to the x/y/z position of a transform. Is that enough to go off of?
Answer by robertbu · Sep 20, 2013 at 11:02 AM
I made an assumption on how you were going to use this function, but as I read, there is no specification. So here is a bit of code that demonstrates how you can modify the phase to keep the sine in-sync. Create an game object at the origin and attach the following script. While the script is running, change the frequency in the inspector. The game object will move back and forth. When the frequency is changed, the game object will not jump.
using UnityEngine;
using System.Collections;
public class SinePhase : MonoBehaviour {
public float amplitude = 2.0f;
public float frequency = 0.5f;
private float _frequency;
private float phase = 0.0f;
private Transform trans;
void Start () {
_frequency = frequency;
trans = transform;
}
void Update () {
if (frequency != _frequency)
CalcNewFreq();
Vector3 v3 = trans.position;
v3.x = Mathf.Sin (Time.time * _frequency + phase) * amplitude;
trans.position = v3;
}
void CalcNewFreq() {
float curr = (Time.time * _frequency + phase) % (2.0f * Mathf.PI);
float next = (Time.time * frequency) % (2.0f * Mathf.PI);
phase = curr - next;
_frequency = frequency;
}
}
although this post was since last year, I'd just like to give a thumbs up, as this is perfect for what I'm working on right now. Cheers to you, 'bert!
I'm here a bit late, but how would I add an offset to the wave without messing up the frequency again? I'm looping through a mesh's vertices and want it to make a wave (like kelp in the ocean) so I want to offset the wave's calculation based on the vertice's y-height.
Thank you very much!! I use this with Cinemachine to improve the noise for walk, run and idle.
I would love to find out how this works someday, but for now, this is nothing short of amazing. Thank you very much for sharing.