A splatter killer for wideband FM. Using Linrad to build new functions into Linrad.
(March 25 2010)

About this page.

Here some experiments with wideband FM modulation are demonstrated. I make this page mostly to remember myself, but some of the findings might be interesting to DXers and others who have an interest in receiving FM without spillover from strong stations on the adjacent channel.

The purpose of this page is partly to show how one can build new functions into Linrad by using another instance of Linrad as an analyzing tool. It also shows step by step how an FM decoder for stereo as well as an RDS decoder is built. Some perhaps unknown characteristics of wideband FM are also demonstrated. It is obvious that one can build an entirely analog radio that is capable of separating a weak signal from a much stronger signal in the neighbouring channel just use simple analog circuits in a new way.

As a test case a file recorded by Jurgen Bartels has been used. The recording is centered at 95.4 MHz where there is a strong local station. There are weak signals at both sides.

The functions described on this page will be available in Linrad-03.12 and later.

The recording.

This file fmqrm.zip (73582558 bytes) is a packed version ot the slightly larger fmqrm.wav. The file was originally recorded in 24 bit format with a Perseus, a part of the file was then saved as a .raw file with Linrad in 18 bit format and subsequently converted to a standard 16 bit .wav file with Linrads raw to wav converter (that automatically shifted 2 bits to the left to not degrade the noise floor. The headroom in the original file allowed that.

Figure 1 is a screen dump showing a waterfall graph of the entire file and an averaged power spectrum.

Fig 1.The whole fmqrm file.

The channel at the low frequency side, 95.3 is about 60 dB weaker than the local station and strong enough to be reasonably well received by use of an appropriate filter followed by a conventional FM detector. The optimum filter bandwidth is about 50 kHz. The spectrum in figure 2 shows why. The frequency swing for the low frequencies peaks at plus/minus nearly 20 kHz. The RDS signal which is always 55 to 59 kHz away from the carrier will thus come as close as about 22 kHz from the 95.3 MHz channel and therefore the filter has to cut there. The second order sideband caused by the 19 kHz pilot tone and the RDS signal is 73 to 78 kHz from the carrier and it may also be a good idea to keep it outside of the desired passband when the frequency swing at 95.4 is small. On the low frequency side there is no punishment for extra bandwidth, but going further than shown in figure 2 does not bring any advantages.

Fig 2.Listening with optimum filter settings and a conventional FM detector.

The loudspeaker output when listening to 95.3 with the settings shown in figure 2 is of course a bit distorted. That is unavoidable in FM when the filter is set too narow. Despite the narrow filter there is also some splatter from 95.4. Listen here: normal-bw50.mp3 (315648 bytes)

Target for the build project.

The strong signal has an extremely good S/N. It should be possible to use that to extract the modulation waveform with extreme precision. The side channels will degrade S/N for the RDS signal, but since that is a digital channel it should be possible to restore it exactly as it was transmitted. The audio channel and the stereo channel should not be affected by the neighbouring channels so they should be detectable with very high accuracy.

Once the modulation waveform is known it should be possible to generate an identical FM signal and to subtract it. That should remove the splatter and allow normal bandwidth and full sound quality even in stereo on the 94.3 channel.


Linrad can send and receive data over the network to another instance of Linrad or to any software that understands the Linrad UDP packages. Data can be received in the same computer or in another computer provided that there is a network connection with appropriate capacity.

The file options.h has a group of defines like this:
// *************************************************************
//               ----   Baseband via network  ----
// For development purposes Linrad can send various signals via the
// network for analysis in another instance of Linrad on se the same
// computer or on another computer. The default is tond BASEBAND_IQ,
// the baseband signal that has passed through the filter that is 
// shown in the baseband graph. 

#define BASEBAND_IQ 1


These defines affect the code in fm.c, baseb_graph.c and rxout.c causing one of the signals to be sent over the network so it can be analyzed by another instance of Linrad.

In fm.c the different defines enable or disable computations as they are needed or not needed to compute the desired signal, but only when the network is set to transmit baseband data in 24 bit format. The normal processing is disabled to the extent it is not needed to compute the desired signal.

In baseb_graph.c the needed arrays are set up. Filter coefficients are also computes and the appropriate speed, number of channels etc are defined for the signal to be transmitted.

rxout.c transfers the appropriate signal to the network buffer. It is another thread that can be set to distribute the data streem evenly in time for future projects where the baseband signal might be computed in very big blocks.

The baseband signal.

The option BASEBAND_IQ will send the filtered baseband signal just as it is. The format is 24 bit integers so it might be appropriate th change the scale factor in rxout.c

1:  int *ntbuf;
2:  while(baseb_pn != baseb_pa && 
3:         ((basebrawnet_px-basebrawnet_pa+basebrawnet_mask)&basebrawnet_mask) >16)
4:    {
5:    ntbuf=(void*)&basebraw_netsend_buffer[basebrawnet_pa];
6:    for(i=0; I < basebraw_ad_channels; i++)
7:      {
8:      ntbuf[i]=floor(0.05*baseb_raw[basebraw_ad_channels*baseb_pn+i]);
9:      }
10:   baseb_pn=(baseb_pn+1)&baseband_mask;
11:   basebrawnet_pa=(basebrawnet_pa+4*basebraw_ad_channels)&basebrawnet_mask;

baseb_raw is a circular buffer of size baseband_mask+1. The size is a power of two so the statement on line 10 will increment the pointer in a circular fashion. The statement on line 8 has a scale factor 0.05 to prevent the integers that are stored in the output buffer ntbuf to overflow. One can use the 'A' command on the receiving instance of Linrad to see how much margin there is to "A/D" saturation which with network input means network saturation. Figure 3 shows one instance of Linrad reading the fmqrm.wav file and sending the baseband over the network while another instance of Linrad receives the data and displays it as a waterfall and a power spectrum.

Fig 3.The left hand side instance of Linrad is transmitting the baseband signal to the right hand side instance that just displays it. It is obvious that the signal has passed through the baseband filter.

The conventional FM detector.

f6 The frequency is the derivative of the phase. For each baseband sample the phase is computed with atan2 and after that the derivative is taken as the difference between sucessive samples. The derivative has to be small because the frequency is changing slowly, but the difference can be wrong by 2*PI so it is necessary to add or subtract 2*PI sometimes to get the correct frequency.

The option WFM_FM_FULL_BANDWIDTH sends the output from the FM detector to the network without any further processing. This is displayed in figure 4.

Fig 4.The left hand side instance of Linrad is transmitting the full bandwidth output from a conventional FM detector to the right hand side instance that receives the intermodulation product at 100 kHz in FM mode.

A very interesting property of the wideband FM signal is that the intermodulation product at 100 kHz is an FM signal that is mudulated with the audio signal from both of the stations. Listen to the audio output produced by the right hand instance of Linrad in figure 4. fm-fm-fmdet.mp3 (316032 bytes) Both stations can be heard with a surprisignly good audio quality. It is obvious that the low frequency part, the pure audio of the strong station can be used to cancel the audio from that station and leave a reasonably good quality for the sound from the weaker signal. It is pretty obvious that it would be an advantage to prevent the signal at 94.6 MHz from reaching the FM detector. It would be fairly straightforward to filter out a 60 kHz passband around 100 kHz from the FM detector in a conventional analog radio and to add a second FM detector. An appropriate balance control should allow cancellation of the strong signal.

The AM detector.

The option WFM_FM_FULL_BANDWIDTH sends the full bandwidth output from an AM detector over the network. See figure 5.

Fig 5.The left hand side instance of Linrad is transmitting the full bandwidth output from an AM to the right hand side instance that receives the intermodulation product at 100 kHz in FM mode.

The intermodulation product produced by an AM detector at 100 kHz is similar to the intermodulation produced by an FM detector. It also contains the modulation of both stations with a surprisingly good sound quality. Listen here: fm-am-fmdet.mp3 (315840 bytes) It is obvious that an alternative modification of an analog receiver is possible. Add an AM detector at the full bandwidth, filter out the region around 100 kHz with a bandwidth of about 100 kHz and route the signal to the FM detector. (Maybe an upconversion would be needed.)

The first filter.

it is pretty obvious from figures 4 and 5 that it will be a good idea to use a filter that cuts relatively sharply above the RDS signal which is centered at 57 kHz and extends about 2 kHz on each side of the suppressed carrier at 57 kHz. The sampling speed has to be very high however since we want two or even three FM channel simultaneously. The best I can do on a Compaq 6510b laptop is illustrated in figures 6 and 7. The options to get those signals over the network are: WFM_FM_FIRST_LOWPASS and WFM_AM_FIRST_LOWPASS respectively.

Fig 6.The output of the FM detector after the first lowpass filter.

Fig 7.The output of the AM detector after the first lowpass filter.

The low pass filters would npormally resample by a factor of 3 and that would ease the cpu load by a factor of three. There are two signals with about 18 kHz bandwidth plus the RDS signal at a bandwidth of about 3 kHz. More filters with further decimation would allow a complete recovery of the RDS signal and a 3 dB improvement of S/N for the stereo channel. One could construct a better FM signal by removing some of the noise this way. It will require a fair amount of programming.

Synthetized FM from the first lowpass signals.

It is of course possible to use the AM and FM components to generate an FM signal. The AM component should have been further filtered down to 500 Hz or so, but already the removal of the strong intermodulation products at 100 kHz should give an interesting FM signal. The intermodulation products extend below 57 kHz but with this simplified approach they can not be removed below about 65 kHz.

The option WFM_SYNTHETIZED_FROM_FIRST_LOWPASS generates an FM signal with the same modulation as the FM station at 95.4 MHz. It is displayed in figure 8.

Fig 8.An FM signal generated from the low pass filtered FM and AM from the dominating station at 85.4 MHz.

Subtracting the synthetized signal.

The purpose of generating the "true" signal from the station at 95.4 MHz is to subtract it from the baseband signal. The result of the subtraction is shown in figure 9 which is generated with the option WFM_SUBTRACT_FROM_FIRST_LOWPASS.

Fig 9.The right hand side shows what remains when the synthetized signal is subtracted.

The cancellation is very good at the center where the signal is reduced by more than 40 dB. The pilot tone is reduced by about 30 dB while the RDS signal is reduced by about 20 dB. The second order signal, RDS+pilot tone at 76 kHz is reduced only by about 10 dB.

When clicking the signal at 95.3 MHz on the right hand screen one can get a very good reception of the previously disturbed channel. Listen here: desplat.mp3 (315456 bytes)

It is even possible to hear a little at 95.5. There seems to be two stations on the frequency. Listen here: fm95_5.mp3 (316032 bytes)