I\'m trying to Frequency modulate an audio signal. I can successfuly FM a sine wave (the carrier) with another sine wave (the modulator) by using the following equation y=co
Unfortunately I haven't been able to get Paul's method to work but I have a working solution for FM synthesis of audio signals. I did a lot of testing in Excel and realized how to do it. Here's the algorithm
for (i = 0; i < N; i++) {
// increase the frequency with increasing amlitudes (fc + fm)
if (input[i] < input[i+1])
out[i] = cos(acos(input[i]) + A * sin(2 * pi * mf * i));
else //decrease the frequency with decreasing amplitudes (fc - fm)
out[i] = cos(acos(input[i]) - A * sin(2 * pi * mf * i));
}
It works well but it does generate some undesirable harmonics (possibly due to rounding errors) so you may have to use some sort of a filter (a moving average might do a good job at reducing those unwanted harmonics). When applied to an audio signal, you will probably have to take the envelope of the audio and multiply it with the modulating signal so as not to apply FM on the quiet portions of the audio etc.
You can think of FM as just dynamically varying the playback rate, where the variation in playback rate is proportional to your modulating signal. So for normal playback your playback rate is the same as the sample rate, Fs
. For an FM version of your audio signal you playback rate will be Fs * (1 + A * f(t))
, where A
is the modulation amplitude and f(t)
is the modulating signal. To implement this you will need to maintain a phase accumulator with a real and a fractional component, and then update the phase accumulator according to the current (modulated) sample rate. Use the integer part of the phase accumulator to determine the sample index, n
and use the fractional part to enable you to interpolate, e.g. between samples n
and n + 1
.
Not that this is very similar to wavetable synthesis, except that your waveform table is a sampled sound instead of a periodic waveform. See e.g. this question on dsp.stackexchange.com for further info.
Simply replace your carrier equation, cos(t), with an f(t) for your input signal, where t might be scaled by the sample rate for sampled data. Then modulate dt as before.
Note that, for sampled data and depending on the bandwidth of your input signal, to make this f(t) sound "good" you may need to use a higher order interpolation method combined with a low pass filter (such as a windowed Sinc convolution), rather than just using the nearest sample or a linear interpolation between two samples, which could alias rather badly in the frequency domain.