2
$\begingroup$

I want to know how I could implement a Low Frequency Oscilator on a simple synth I've coded in C. First in order to understand how to make this happen I would like just to modulate a sine wave by a sine LFO, and then I would adapt this to other oscilators and so on.

I tried adapting to adapt this LFO formula I found on my sine oscilator:

dLFOAmplitude * dHertz * (sin(w(dLFOHertz) * dTime

But I didn't found a correct way to do this. Here's my sinewave generator function:

static void build_sine_table(int16_t *data, int wave_length) {

    double phase_increment = (2.0f * pi) / (double)wave_length;
    double current_phase = 0;

    for(int i = 0; i < wave_length; i++) {
      int sample = (int) (sin(current_phase) * INT16_MAX);     
        data[i] = (int16_t)sample;
        current_phase += phase_increment;
    }
}

EDIT: I tried again to multiply my lfo signal with my oscilator. Each time I'm doing it I got no sound released. Same by divinding. When I sum up the two signal I got sound but no modulation. Here's what I tried in order to follow advices from the comment:

static void build_sine_table(int16_t *data, int wave_length) {

    double phase_increment = (2.0f * pi) / (double)wave_length;
    int lfo_phase = (2.0f * pi) / 20 / 44100;
    double lfo = 0;
    double current_phase = 0;

    for(int i = 0; i < wave_length; i++) {
      int sample = (int) (0.5 * sin(current_phase) * INT16_MAX + 0.5 * sin(lfo) * INT16_MAX);

        data[i] = (int16_t)sample;
        current_phase += phase_increment;
        lfo += lfo_phase;
    }
}

I tried many other thing, and the "best result" I got was a wave looking like this : enter image description here

I've spent a lot of time trying to figure out a to make it work, and the more I looking into it, the less I'm confident to be able of coding it.

$\endgroup$
4
  • $\begingroup$ Your sine table function seems correct to me. For the amplitude modulation, you just need to multiply the two signals together. Since your sine table goes from -INT16_MAX to INT16_MAX, passing through 0, there will be a point where your audio signal will disappear. You might want to scale the amplitude of your sine table before multiplying it and maybe add an offset so your signal never disappears. As for the formula, it's just a matter of skipping ahead in the sine table based on the sample rate and the frequency you want (f/Fs). $\endgroup$
    – Signal
    Jun 12, 2020 at 18:37
  • $\begingroup$ Thanks for the answer. What I want to know is how to generate my lfo signal. I tried something like this " double lfo_phase = (2.0f * pi) / (44100/20);" and the processing the lfo phase like I'm doing for my oscilators. Each time a tried to multiply the signal with my oscilator I got a modulation of th esine, but it gives something sounding like a square wave. I think scaling my amplitude would maybe fix things but not I'm not sure how to do this. $\endgroup$ Jun 12, 2020 at 19:05
  • $\begingroup$ May I suggest keeping floating-point values for your sine table? This way you would have values between -1 and 1 and could scale the weight much more easily. You could also convert your signal to floating-point value by dividing by INT16_MAX (assuming your signal is 16-bit signed integer), and then multiply the two floating-point values, then convert back to 16-bit signed integer (by multiplying back by INT16_MAX). If you want to avoid floating-point values, you can use fixed-point math for that and keep everything with integers. There are a few tutorials out there for fixed-point math. $\endgroup$
    – Signal
    Jun 12, 2020 at 19:31
  • $\begingroup$ Well I see wht to do in theory to sccale, unfortunatley I still struggle to get the lfo working. $\endgroup$ Jun 12, 2020 at 19:41

1 Answer 1

1
$\begingroup$

Thanks a lot to TehWan ! Well I'm not quite sure if I succeded into building a proper LFO, but at least I've got a wave modulation function with interesting sound. Check this out:result of my wave modulation

In order to achieve this I implemented a very small part of the code provided by TehWan and try different approach and got the best result with this code:


static void build_sine_table(int16_t *data, int wave_length) {

    const double LFO_FREQUENCY = 5; // LFO frequency [Hz]
    const double SAMPLE_RATE = 44100; // Sample rate [Hz]
    const double CONVERSION_FACTOR = 32768.0;
    double phase_increment = (2 * pi) / (double)wave_length;
    double current_phase = 0;  // Initial phase [rad]
    double dphase = ((2 * pi * LFO_FREQUENCY) / SAMPLE_RATE); // Phase rate of change [rad/sample]
    double lfo = 0;



    for(int i = 0; i < wave_length; i++) {

      (int)(sin(lfo) * INT16_MAX);
      int sample = (int)((sin(current_phase) * INT16_MAX));
      lfo += dphase;
      current_phase += phase_increment + (0.2 * lfo);

      data[i] =  (data[i] / CONVERSION_FACTOR) + (int16_t)sample;


}

If someone sees something wrong here I'm reading to correct it. Anyway for the time being I will consider this my "LFO".

EDIT: TehWan thank you once again, well I didn't used much your code but at least it did help find out how to change my function.

$\endgroup$
3
  • $\begingroup$ Glad it worked out for you. The LFO I sent you modulates the amplitude of the signal using a constant frequency, but if you want to modulate the frequency of the input signal, it's best to use complex numbers and a slightly different mixing function. What you have created is a chirp by varying the rate of change of the phase (lfo variable in your case), i.e. not using a constant step for your phase increment. $\endgroup$
    – Signal
    Jun 13, 2020 at 6:41
  • $\begingroup$ Ok, since I will implement that to a a sequencer I made I could use this to otjer feature to my chirp $\endgroup$ Jun 13, 2020 at 12:16
  • $\begingroup$ @valentindiverchy If you are happy with TehWan answer, would you mark it as accepted? $\endgroup$
    – jojeck
    Jul 15, 2020 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.