# Help with algorithm for modulating oscillator pitch using LFO

I am developing a software emulation of an analog synthesizer. I am trying to modulate the pitch of an oscillator using an LFO. For each sample fed to the computer's sound system, I am calculating the frequency to be input into the main oscillator like this (pseudocode):

osc_frequency = note_frequency * (1 + tuning) * (1 + lfo_y * lfo_mod_depth)


The variables in this statement are described as follows:

• note_frequency = frequency of note to be played in Hz
• tuning = oscillator fine-tuning in percent of played pitch (ex: -0.02 = detune by 2%)
• lfo_y = current y value of lfo waveform (ranges from -1 to 1)
• lfo_mod_depth = depth/intensity of effect to apply to oscillator in percent

However, this computation does not yield the desired result. I expect to hear the pitch modulate up and down, locked around the center frequency (note being played). What I am getting is a modulation effect that causes the pitch to "run away"; I can't tell exactly what is happening, but it sounds like one of these:

1. The modulation intensity increases over time (the high/low frequency mark reached by the modulation grows higher/lower the longer the note is held)
2. While the modulation intensity remains constant over time, the center frequency increases while the modulation oscillates around it

Am I using the correct approach or not? If not, what should the correct approach be? Any help with this is much appreciated.

• What's most important is what you do with the desired oscillator frequency. You might be running into a similar problem to this question. You should have a phase accumulator that keeps track of the phase of the output signal at each time step, updating it according to the desired frequency at each output sample. More info can be found here. – Jason R May 13 '12 at 20:13
• Your reference to a phase accumulator led me to look into using wavetable synthesis instead of the more naive approach I was using in my oscillator. Once I reworked my design (also incorporating the tips outlined by @pichenettes answer), I got the results I was looking for. Thanks! – Gary DeReese May 15 '12 at 18:08

As said by Jason, this might simply be that you are not implementing your oscillator correctly - for example by multiplying the frequency by time instead of integrating it.

Note also - and this is unrelated to your topic but really worth observing - that your formula for frequency modulation implements a behavior very different to that of most synthesizers, and will sound uncanny to a musician.

For example, if lfo_y oscillates between -1 and 1 ; lfo_mod_depth is 0.5 ; and if note_frequency is equal to 220 Hz, osc_frequency will sweep between 110 and 330 - that is to say between -1 octave and +1 fifth around the note. So the pitch modulation will appear to be centered in the hertz scale, but will not be centered in the perceptual musical scale.

The correct behaviour is to have something like:

osc_frequency = note_frequency * 2 ** (tuning / 1200.0 + lfo_y * lfo_mod_depth)


Then:

• tuning is expressed in cents, a musically relevant unit (100 cents = 1 semitone).
• your pitch modulation is "musically centered", and lfo_mod_depth is expressed in octaves.

This is called "exponential FM", and this is the norm on synthesizers. On analog synthesizers, this is implemented by summing the LFO signal to the CV that hits the exponential converter of the VCO. On digital synthesizers, this is implemented by applying the modulations on a high-resolution internal representation of pitch which is still on a musical scale - before converting to a frequency or a phase increment.

• Thanks. While this wasn't at the heart of my problem, this is indeed a more sensible way to express and calculate the oscillator frequency for my application, and after implementing it, seems to work fine. – Gary DeReese May 15 '12 at 18:04
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.657692551612854, "perplexity": 1335.8120604680998}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2020-34/segments/1596439738944.95/warc/CC-MAIN-20200812200445-20200812230445-00147.warc.gz"}