you can generate IQ WAV file with required FM modulation signal and play it with sound card into IQ input
FM modulation is pretty easy, you can do it in the following way:
var iq = new complexd[audio.Length];
for (int i = 0; i < iq.Length; i++)
{
// calculate phase increment based on input audio signal
var phaseIncrement = audio[i] * scale;
// update current phase
phasePrev += phaseIncrement;
// calculate IQ stream
var re = Math.Cos(phasePrev);
var im = Math.Sin(phasePrev);
iq[i] = new complexd(re, im);
}
if you don't familiar with programming, I've implemented a little console application which can process signal in WAV file. It allows to perform FM modulation into IQ stream based on audio taken from another WAV file. Also it allows to perform FM demodulation from a WAV file with IQ stream. And in addition it allows to perform frequency shift for a WAV file with IQ stream.
here is example on how to use it:
IQDSP.exe fmmod 100000 input.wav output.wav
where 100000 is FM deviation, input.wav is a WAV file with audio signal and output.wav is a file which will contains IQ stream with FM modulated signal at 0 Hz carrier.
if you're don't like 0 Hz carrier (many soundcard cannot play DC signal due to capacitors on the output) you can also use it to perform frequency shift. For example in order to shift 0 Hz carrier to 20000 Hz carrier use the following:
IQDSP.exe fqshift 20000 iqfmdc.wav output.wav
It supports uncompressed PCM and IEEE FLOAT WAV formats.
Preffered input format is IEEE FLOAT32 or IEEE FLOAT64. Probably it can eat any format but I didn't tested it deep.
Output WAV file has IEEE FLOAT32 format and the same sample rate as input file.
Note that FM modulated signal requires more wide bandwidth than audio signal.
It is recommended to use input file with sample rate which is about 12 times more wide than audio signal bandwidth.
For example 240 kHz sample rate is recommended for 20 kHz signal bandwidth.