Pointers for digital FM synthesis I am working on a digital synthesis project, in python and c currently. I have made a Sine and Saw wave generator and have now been working on FM between the two wave types. I have successfully made FM work with a Sine wave as both carrier and modulator, but whenever I add a Saw wave into the mix, The carrier frequency increase indefinitely. After a lot of research and trying to understand some more complex DSP concepts (instantaneous phase and frequency), I am feeling a bit lost, and hoping for some pointers to resources where I can learn more at a more basic level of understanding.
Essentially, the goal right now is to modulate the frequency of any wave shape with any other wave shape given only the amplitude of the modulator signal. This would in essence be a VCO emulation or a pitch envelope capable of audio rate modulation.
The code below is currently what I have come up with, which works, but only as intended when the modulator frequency is greater than the carrier frequency (I am assuming because this is phase modulation, not FM).

# self.count == the current sample 
# self.fs == 48000 
# fmcv == the amplitude value for the given sample number, between -1 and 1, of the modulator 

pos = self.count / self.fs
value = math.sin(self.freq * 2 * math.pi * pos + math.pi * 2 * fmcv)
value = value * self.gain + self.offset
self.count = self.count + 1
return value  

I have also tried the following which gives similar results.
pos = self.count / self.fs
value = math.sin((self.freq * (1 + (0.9 * fmcv))) * 2 * math.pi * pos)
value = value * self.gain + self.offset
self.count = self.count + 1
return value

Any help and pointers towards good resources where I can understand the concepts better are greatly appreciated.
If the case with two sines is clear (sine wave modulation of a sine wave carrier) then consider expanding any other shape (such as the ramp) into its Fourier components and then superimposing the result of each.
Any waveform with sharp transitions (such as a ramp) requires an infinite number of frequency components, so better to work with smoothed waveforms where the higher frequency components are essentially filtered out.
Another tip when simulating carrier modulation is to not actually simulate the carrier but use a complex baseband signal instead (what you simulate their will match what would occur at any carrier frequency and doesn't require as high of a sampling rate to simulate). This requires understanding the baseband equivalent analytic signal, but would be the recommended next step regarding understanding DSP concepts.