Wavetables and Frequency Modulation - I am missing something.

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I am trying to do some simple frequency modulation using wavetables, and i think there is something about FM that I don't understand.

I got two 2048 element size wavetables. Carrier is a pure square wave. Modulator is a sine wave.

I have a function where I get a sample from one of these wavetable, where it also interpolates, and advances delta.

So to get a sample from the any wavetable, here for the carrier (oscillator[0]),I do;
sampleValue = getSampleAndInterpolate (oscillator[0], phaseAngle[oscillator[0]]);

So to do some simple FM I tried this, where oscillator[1] is the sine wave table and modulator, and keep in mind I can set frequency of each "oscillator" to be different, including modulator fixed or note frequency;
sampleValue = getSampleAndInterpolate (oscillator[0], phaseAngle[oscillator[0] + getSampleAndInterpolate (oscillator[1], phaseAngle[oscillator[1]]);

So what happens above is that oscillator[0] phaseAngle gets added a tiny fluctuating float value of between -1 and 1, which is pretty much to insignificant to be heard. Sure I can try and scale up the modulator value so the effect can be better heard, but then it sounds glitchy.

So what am I missing here?
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

There's probably something wrong with your getSampleAndInterpolate() function - it's possible that it doesn't wrap around the waveform correctly (not only does it have to generate correct result for phase 0...1, but also below 0 or above 1).

One trick is that FM synthesis is often easier to implement in integer math than in floating point.

Post

MadBrain wrote: Tue Mar 03, 2020 11:14 pm There's probably something wrong with your getSampleAndInterpolate() function - it's possible that it doesn't wrap around the waveform correctly (not only does it have to generate correct result for phase 0...1, but also below 0 or above 1).

One trick is that FM synthesis is often easier to implement in integer math than in floating point.
I appreciate the help, however I have used that function for months unchanged with 8 oscillators (tone generators), and 5 different wave tables (different analog type osc's).

Anyways I did get some improvement, very interesting and useful results when I used a multiplier equivalent to modulator oscillator's (wavetable's) phase angle.
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

Dunno details of how your getSampleAndInterpolate() works. But for instance one way to set frequency and run an oscillator, one might have a current phase angle var or property which increments after (or before) each new sample is generated, and wraps intelligently as required to stay in-bounds of the lookup table And you have a phase angle increment var or property, which actually sets the running frequency of the oscillator.

So if the table length is 4096 (and the table contains exactly 1 wave cycle) and TableIncrement = 1, then a waveform would have PERIOD of 4096 / SampleRate and Fundamental Frequency of SampleRate / 4096.

If TableIncrement = 2 the wave table is read out twice as fast, runs an octave higher, [SampleRate * TableIncrement / TableSize]. If TableIncrement = 0.5 then the table runs out at half normal rate and runs an octave lower than "normal". Yadda yadda.

So I think to wide-range frequency modulate you would want to use modulator oscillator output to modulate the carrier oscillator TableIncrement, not the carrier oscillator's CurrentPhaseAngle. The test of this would be to set the frequency of the modulator oscillator to LFO range, maybe 1 to 10 Hz. This slow sine wave modulator should make clean pitch vibrato in the carrier oscillator, and strong modulation of the TableIncrement would cause very strong pitch mod. You can check that it is working correct with LFO frequencies, before you get into audio band FM.

There are many ways you could map the modulator oscillator output into appropriately changing the carrier oscillator TableIncrement to get nice-sounding musical FM. One good way, easy on the brain but a little CPU intensive, is to adopt the digital equivalent of analog synth 1 volt per octave. I think a lot of people manage the modulation thataway, and I think it is one reason people seem so interested in fast EXP2 and fast LOG2.

The beauty of 1 volt per octave or a digital equivalent, adding log control signals then converting them back to linear to calculate the instantaneous TableIncrement value, is that it tracks symmetrically sharp and flat in cents, and you only have to scale and add control signals usually, rather than having to multiply and add and worry more about edge cases where maybe your TableIncrement value might decide to become zero or negative. :)

But the FM can be done without "simulated 1 volt per octave" as well. That is just a possible refinement.

Post

JCJR wrote: Thu Mar 05, 2020 5:38 pm Dunno details of how your getSampleAndInterpolate() works. But for instance one way to set frequency and run an oscillator, one might have a current phase angle var or property which increments after (or before) each new sample is generated, and wraps intelligently as required to stay in-bounds of the lookup table And you have a phase angle increment var or property, which actually sets the running frequency of the oscillator.

So if the table length is 4096 (and the table contains exactly 1 wave cycle) and TableIncrement = 1, then a waveform would have PERIOD of 4096 / SampleRate and Fundamental Frequency of SampleRate / 4096.

If TableIncrement = 2 the wave table is read out twice as fast, runs an octave higher, [SampleRate * TableIncrement / TableSize]. If TableIncrement = 0.5 then the table runs out at half normal rate and runs an octave lower than "normal". Yadda yadda.

So I think to wide-range frequency modulate you would want to use modulator oscillator output to modulate the carrier oscillator TableIncrement, not the carrier oscillator's CurrentPhaseAngle. The test of this would be to set the frequency of the modulator oscillator to LFO range, maybe 1 to 10 Hz. This slow sine wave modulator should make clean pitch vibrato in the carrier oscillator, and strong modulation of the TableIncrement would cause very strong pitch mod. You can check that it is working correct with LFO frequencies, before you get into audio band FM.

There are many ways you could map the modulator oscillator output into appropriately changing the carrier oscillator TableIncrement to get nice-sounding musical FM. One good way, easy on the brain but a little CPU intensive, is to adopt the digital equivalent of analog synth 1 volt per octave. I think a lot of people manage the modulation thataway, and I think it is one reason people seem so interested in fast EXP2 and fast LOG2.

The beauty of 1 volt per octave or a digital equivalent, adding log control signals then converting them back to linear to calculate the instantaneous TableIncrement value, is that it tracks symmetrically sharp and flat in cents, and you only have to scale and add control signals usually, rather than having to multiply and add and worry more about edge cases where maybe your TableIncrement value might decide to become zero or negative. :)

But the FM can be done without "simulated 1 volt per octave" as well. That is just a possible refinement.
I did attempt to modulate the delta ("TableIncrement"), but it produced effects more similar to vibrato or tremolo, even though the modulator's frequency was well into audible range.
Last edited by DKDiveDude on Thu Mar 05, 2020 7:01 pm, edited 1 time in total.
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

Oops double post
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

JCJR wrote: Thu Mar 05, 2020 5:38 pm Dunno details of how your getSampleAndInterpolate() works. But for instance one way to set frequency and run an oscillator, one might have a current phase angle var or property which increments after (or before) each new sample is generated, and wraps intelligently as required to stay in-bounds of the lookup table And you have a phase angle increment var or property, which actually sets the running frequency of the oscillator.

So if the table length is 4096 (and the table contains exactly 1 wave cycle) and TableIncrement = 1, then a waveform would have PERIOD of 4096 / SampleRate and Fundamental Frequency of SampleRate / 4096.

If TableIncrement = 2 the wave table is read out twice as fast, runs an octave higher, [SampleRate * TableIncrement / TableSize]. If TableIncrement = 0.5 then the table runs out at half normal rate and runs an octave lower than "normal". Yadda yadda.

So I think to wide-range frequency modulate you would want to use modulator oscillator output to modulate the carrier oscillator TableIncrement, not the carrier oscillator's CurrentPhaseAngle. The test of this would be to set the frequency of the modulator oscillator to LFO range, maybe 1 to 10 Hz. This slow sine wave modulator should make clean pitch vibrato in the carrier oscillator, and strong modulation of the TableIncrement would cause very strong pitch mod. You can check that it is working correct with LFO frequencies, before you get into audio band FM.

There are many ways you could map the modulator oscillator output into appropriately changing the carrier oscillator TableIncrement to get nice-sounding musical FM. One good way, easy on the brain but a little CPU intensive, is to adopt the digital equivalent of analog synth 1 volt per octave. I think a lot of people manage the modulation thataway, and I think it is one reason people seem so interested in fast EXP2 and fast LOG2.

The beauty of 1 volt per octave or a digital equivalent, adding log control signals then converting them back to linear to calculate the instantaneous TableIncrement value, is that it tracks symmetrically sharp and flat in cents, and you only have to scale and add control signals usually, rather than having to multiply and add and worry more about edge cases where maybe your TableIncrement value might decide to become zero or negative. :)

But the FM can be done without "simulated 1 volt per octave" as well. That is just a possible refinement.
Ok your reply made me reconsider my previous approach of modulating the delta (TableIncrement). So I moved that modulation to a different place in my code, another function, and I got something, definitely very useful and musical. Whether it's true FM or not, I am still not 100% sure, but it sounds great, and thank you very much btw!

But I am actually glad I got it wrong at first, because on my journey toward "Proper" FM I stumbled upon six other musical useful ways to frequency modulate, so now I have 7 FM variations for fixed frequency modulator and another 7 variations for note frequency modulator, all 14 variations which I can adjust exact frequency via octave, semi, and fine knobs!
"Scuba divers work best under pressure!"

https://www.youtube.com/user/DKDiveDude (Original music and hardware videos)

Post

Perhaps of historical note if nothing else, in the 1970's mono analog synthesis one of the more "famous" uses for audio rate FM was rather specialized. To make good snappy note-attack on mono analog synth jazz/fusion/rock lead lines. An audio-rate modulation oscillator would be fed thru a VCA on the way to the destination carrier oscillator(s). This mod amount VCA would be typically driven by a "Blip" fast attack fast decay/release envelope. So that only the brief period after each note-on would get the audio-rate FM. This would be adjusted in frequency and intensity to make a good percussive enharmonic "Blat" attack sound at each note-on, maybe like guitar-picking or sax-tongueing.

So the sustained part of the sound would not have much or any FM enharmonics. Only the "blat" at the note attack. THis tended to be lots more aggressive and noticeable than what you could get just with clean envelope mods without enharmonic note attack. Better note separation for scalding lead lines.

I don't know a lot about audio-rate FM and haven't considered it lately but there are a couple of common flavors of frequency control. It is ambiguous what to call them. In analog one kind uses exponential control voltage driving a "linear responding" oscillator. The other kind uses a linear (often 1 volt per octave) control voltage driving an "exponential responding" oscillator.

The 1 V per octave oscillators were simply the linear responding oscillators with an additional anti-log CV converter circuit on the oscillator CV input.

For example if a linear-responding oscillator is calibrated to run at 100 Hz with 1 volt input, then 200 Hz with 2 volts input, then 400 Hz with 4 volts input, 800 Hz with 8 volt input, etc.

OTOH the exponential responding osc might be calibrated to run at 100 Hz with 1 volt input, 200 Hz with 2 volt input, 400 Hz with 3 volts input, 800 Hz with 4 volts input.

The exponential response is most convenient for symmetrical "musical interval modulation" without going crazy. But so far as I recall, it is claimed that the linear response is better for some kinds of audio rate FM. I don't remember why if I ever knew.

The table increment of a wavetable oscillator seems to work like a simple linear-response analog oscillator. If a wavetable increment of 1 results in 100 Hz, then wavetable index increment of 2 results in 200 Hz, increment of 4 results in 400 Hz, etc.

If, like the analog oscillator, you add an "antilog converter" software couple of lines to the frequency-setting input of the wavetable oscillator, EXP2(input) then if the oscillator is calibrated to run at 100 Hz with a control input of 1, then an input of 2 would yield 200 Hz, input of 3 yields 400 Hz, etc.

For instance if the max peak-to-peak of the modulator oscillator = +/- 1.0, and if the "keyboard tracking" input is 2 for 200 Hz sans modulation.

With an exponential responding oscillator, max frequency would be keyboard tracking input + 1 = 3, and min frequency would be keyboard tracking input - 1 = 1. So the max frequency would be 400 Hz and the min instantaneous frequency would be 100 Hz. The bipolat +/- 1 control signal modulates exactly 1 octave up and 1 octave down.

With a linear-responding oscillator, max frequency would be keyboard tracking input + 1 = 3 = 300 Hz and min instantaneous frequency would be keyboard tracking input - 1 = 1 = 100 Hz. So the linear-responding oscillator would be modulated one octave down, but only about a fifth interval up ( 1200 Cents * Log2(3/2) = 702 Cents )

Which, for some reason is said to be better for some kinds of audio-rate FM. But possibly harder on the brain for proper scaling and avoiding zero or negative WaveTable Index Increments with some combinations of values, at least if using bipolar modulation sources. And not good for tasks such as LFO vibrato, because the "perceived center pitch" would change along with vibrato mod amount.

Post Reply

Return to “DSP and Plugin Development”