Afreet Software, Inc.
     Software created by Alex Shovkoplyas, VE3NEA

Morse Expert
for Android

Ham Cockpit

CW Skimmer

DX Atlas

RTTY Skimmer Server



CW Skimmer Server

Pileup Runner

DX Bulletin Reader

Voice Shaper

Band Master


Morse Runner



Morse Midi


Tech stuff



QRQ Profiler


SSTV Tools


Rocky 3.8

SDR software for the SoftRock radio


  Using Rocky     Advanced Topics  

Advanced Topics

Tools and components

Rocky was written in Delphi 5 Pro. The development cycle was pretty short since I used a lot of code from my weak signal decoder project. I have been working on that project for the last 5 years, and now it is very close to completion - but I am so tired of it that I am starting smaller projects, like MorseRunner and Rocky, to have an excuse for not working on the decoder ;-)

Audio I/O

Rocky talks directly to the WDM driver of the sound card. This ensures the lowest possible latency, eliminates a number of problems associated with the Windows K-Mixer, and allows smooth audio streaming between two souncards. However, the WDM-based approach has some disadvantages, too: 1) the program does not work on the old versions of Windows; 2) the sound card can be opened only at the sampling rates directly supported by the driver, since the program cannot take advantage of sampling rate conversion in K-Mixer.

Update: Rocky 3.8 and later versions use WASAPI instead of WDM.

Band Scope

The polyphase FFT algorithm is used to calculate the displayed spectrum. The screenshots below show the difference between the standard FFT and polyphase FFT: the latter has much higher resolution and does not introduce extra spectral leakage.

Standard FFT

Polyphase FFT

Non-linear filtering is applied to the power spectrum before it is displayed. This improves the signal-to-noise ratio and makes weak signals clearly visible in the noise. The filter is always turned on in the program, but I temporarily disabled it in the code to take the screenshot presented below.

Filter disabled

Filter enabled

The filter is just a 1-st order lowpass IIR filter:

      FilteredSpectrum[i] := FilteredSpectrum[i] * (1-Gain) + NewSpectrum[i] * Gain;

- except that the gain is a non-linear function of the amplitude:

      Gain := (1 - Exp(-(0.2 * NewSpectrum[i])));

Due to this non-linearity, the time constant of the filter is high for the noise but close to zero for the strong signals.

Waterfall Display

While the spectrum display has high resolution in frequency, the waterfall display is designed to have high resolution in time, so that CW signals can be copied visually at the speeds up to 40 WPM. How many callsigns can you read on the screenshot below?

A pileup on the K7C frequency

Two optional filters are available in the waterfall display mode. The filters can be enabled or disabled using the drop-down menu of the Waterfall Display button.

Key-click filter removes CW key clicks. It is implemented as spectral subtraction: the estimate of the power density of the key clicks is subtracted from the power spectrum of the signal. The filter also has some de-noising effect.

Key-click filter disabled

Key-click filter enabled

Super Resolution filter is based on the transform known as time-frequency surface re-parameterization.

Standard resolution

Super resolution

A modified version of the third party FFT unit from the DC-DSP Component Pack is used in Rocky to compute the Fast Fourier Transform. I have fixed a couple of bugs in this unit and modified it for compatibility with Delphi 5. The source code of the updated unit is available in the Programmer's Corner.

I/Q Balancing

I/Q Balancing in Rocky is fully automatic and does not require any lab equipment, all you have to do is start the program when the band is open. Rocky will use all strong stations on the band as signal generators!

The algorithm works as follows. The power spectrum is scanned for the signals that are at least 30 dB above the noise. For each signal, synchronous detection of the image is performed using the main signal as a reference oscillator. The synchronous detector has very high sensitivity and can detect the image signal even if it is below the noise. For the signal in the j-th bin of the spectrum, the normalized output Z of the syncronous detector is calculated as follows:

      Z = ComplexMul(ASpectrum[j], ASpectrum[FftSize-j])
      Pwr = Sqr(ASpectrum[j].Re) + Sqr(ASpectrum[j].Im) +
            Sqr(ASpectrum[FftSize-j].Re) + Sqr(ASpectrum[FftSize-j].Im)
      Z.Re = Z.Re / Pwr
      Z.Im = Z.Im / Pwr

Z is a complex value that contains information about the amplitude and phase of the image in respect to the main signal. The program averages Z over the time and calculates the amplitude and phase error as a function of frequency:

      tmp = Sqrt(1 - Sqr(2*Z.Re))
      Phase = ArcSin(2*Z.Im / tmp)
      Gain = tmp / (1 - 2*Z.Re)

I have derived these equations using the Maxima tool.

Rocky interpolates the error estimates by fitting a polynomial to them, and constructs a frequency-domain error function, H[w]:

      H[w].Re = Gain[i] * Cos(Phase[i])
      H[w].Im = Gain[i] * Sin(Phase[i])

The spectrum S'[w] of the input signal is transformed to obtain the corrected spectrum S[w] using the following equations:

      S[w].Re = S'[w].Re + S'[-w].Re 
        - (S'[w].Im + S'[-w].Im) * H[w].Im 
        + (S'[w].Re - S'[-w].Re) * H[w].Re
      S[w].Im = S'[w].Im - S'[-w].Im 
        + (S'[w].Im + S'[-w].Im) * H[w].Re 
        + (S'[w].Re - S'[-w].Re) * H[w].Im

Click on View / IQ Balance in the menu to see the plots of the phase and amplitude errors vs. frequency. They should look like this:

15 min. after start

Next day

I have an old version of SoftRock40, the one without the mod to the Johnson counter. The new versions probably have much smaller errors due to better timing of the LO signal.

Multirate filtering

The main filter in Rocky is a classical windowed-sinc filter. Since the bandwidth of the filtered signal never exceeds 3 KHz, it makes sense to do filtering at a lower sampling rate: this saves a lot of CPU cycles. The desired segment of the spectrum is mixed down to baseband and re-sampled at 6 KHz, the filter is applied, and the filtered signal is mixed with a complex sinusoid to produce the desired pitch. Mixing, re-sampling and filtering are performed in the frequency domain. The program tries to open the sound card for output at the 6 KHz sampling rate. If this fails, it up-samples the signal to whatever sampling rate is supported by the sound card.

Filter parameters


The bandwidth of the main filter is adjustable between 20 Hz and 600 Hz. What bandwidth should you use? In the classical, all-hardware CW receivers, the 500 Hz bandwidth is the standard: a narrower filter would make it difficult to find stations on the band and tune precisely at the signal. This is not a limitation in a software-defined radio: all stations, even the weakest ones, are clearly visible on the spectrum and waterfall displays, and precise tuning at the station can be performed with a single mouse click. Now you can use very narrow filters with ease. For a CW signal, the optimal bandwidth in terms of SNR in white noise is 1.5 * WPM - e.g., 45 Hz for a 30 WPM. Under heavy QRM, even narrower filters should be used: you will have a bit lower signal-to-noise ratio but much better signal-to-interference ratio.

When you start using narrowband filters in Rocky, you will appreciate the Snap function. Tuning at a signal manually with a 20-Hz filter is a nightmare!

Shape factor

The shape factor is a ratio of the filter bandwidth at -60dB and -6dB. One might think that the closer the shape factor to 1 the better. Wrong! Filters with very small shape factors inevitably ring - not because of poor design, but due to the Gibbs phenomenon. The only way to eliminate ringing is to increase the shape factor.

The shape factor can be calculated from the transition bandwidth of the filter as follows:

ShapeFactor = (TransitionBW + Bandwidth + TransitionBW) / Bandwidth.

Rocky allows you to select one of several pre-defined transition bandwidths, the choice is presented as a shape factor at the 500 Hz bandwidth. This feature was added only for experimentation. For everyday operation, use the Auto Select option - this tells Rocky to maintain the optimal shape factor at any filter bandwidth.

Exercise. Select the filter shape factor of 1.02, disable AGC, and set the 500 Hz bandwidth. Tune at a strong, high-speed CW signal so that its frequency is close to the filter cutoff frequency. You will hear strong ringing that starts a fraction of a second before the main signal, and gradually fades out after the end of the signal.


The AGC algorithm in Rocky maintains the optimal dynamic range of the output signal. This is different form the classical AGC systems that care only about the upper end of the dynamic range. Such 'two-sided' AGC has the right gain both during and in between the strong signals and allows the operator to hear weak stations between the dots and dashes of the strong ones.

The algorithm estimates the input noise r.m.s. from the spectrum of the unfiltered signal, and computes the envelope of the total (signal + noise) signal. These two values define the input dynamic range. AGC maps this range to the desired output dynamic range with an exponential function:

  Out = MaxOut * (1 - Exp(-In / Beta))

The output signal of the AGC unit is a product of the input signal and the AGC gain as a function of time. In the frequency domain, this is equivalent to the convolution of the input spectrum and the spectrum of the gain function. Therefore, AGC adds sidebands to the spectral peaks of the signal - this effect is known as intermodulation. Since the sidebands are just copies of the gain spectrum, intermodulation can be minimized by ensuring that the gain function is as narrowband as possible. This is acheived by lowpass-filtering the gain.

The gain filter consists of a sliding minimum filter followed by the Blackman FIR filter. The length of both filters is the same, this ensures that the filtered gain does not exceed the instant gain calculated from the mapping function, and thus clipping never occurs.


The S-meter in Rocky is an attempt to see if SDR software can do better than just simulate the behavior of a hardware device. An analog S-meter is usually based on a peak detector with exponential decay. The S-meter in Rocky works differently: it tracks the envelope of the signal using the sliding minimum algorithm, and displays the true signal strength with a 0.3 s resolution in time. As a result, the indicator does not jump at each dot and dash or voice burst, and the reading changes only when the signal strength actually changes.

The variations of instant power under the envelope are shown on the S-meter with white dots around the marker, each dot is 6 dB or 1 S unit. In the SSB mode, you can estimate the peak factor of the signal by looking at those dots; for a CW signal the dots show the difference in power between Morse elements and spaces between them (that is, the true SNR).

CW Transmitter

The CW signal is generated in the time domain as a complex sinusoid multiplied by the keying envelope. The algorithm of the envelope generation is described in my article, CW Shaping in DSP Software, QEX May/June 2006. The rise and fall time of the envelope is 5 ms; the algorithm ensures that the keying sidebands are suppressed by more than 100 dB{!} at +/-280Hz from the carrier. The spectrum of the I/Q output signal is shown below:

The SSB TX mode is work in progress. The speech pre-processing module is ready for testing, it is currently available as a stand alone program.

BPSK31 unit


The input to the BPSK31 receiver is a complex baseband signal sampled at 3000 Hz. This is the same signal that is used in the CW and SSB filters, see Multirate Filtering above for details. The receiver consists of the following modules.

LO / Mixer multiplies the input signal by a complex sinusoid to cancel the frequency error. On startup, the frequency of the LO is zero.

LPF / Resampler performs lowpass filtering and downsampling. Filtering is done in the frequency domain. The filter has two bandwidth settings, 30 Hz and 17 Hz. The wider filter is a standard Blackman-Sinc FIR filter, the narrow one is a custom filter optimized for minimum ISI, designed in SciLab. The wide filter is used for frequency acquisition. Once the frequency lock is achieved, the narrowband filter is switched in.

Downsampling is also performed in the frequency domain, by aliasing the spectrum onto itself. The output sampling rate is 375 Hz.

Frequency Detector multiplies the current audio sample by the complex conjugate of the previous sample. The argument of the product is the frequency error, is radians per sampling interval, and the magnitude is the instant power of the signal.

Frequency tracker is a 1-st order Kalman filter. Its inputs, the observation value and variance, are computed from the argument and magnitude of the frequency detector output. The frequency estimated by the Kalman filter is negated and assigned to the LO.

Sybmol Timing Tracker estimates the period and time offset of the symbols. The instant power of the BPSK signal is a constant (subject to fadings), with occasional nulls occurring when the signal phase is reversed. These nulls occur at the sybmol boundaries and have a cosine shape. The symbol tracker computes a complex correlation of the signal power with one period of the cosine, the phase of the result is the time offset of the null from the origin of the cosine. A second order Kalman filter tracks the timing error and provides an estimate of the symbol transition time.

Symbol Sampler / Phase Corrector uses the timing information from the symbol tracker to sample the data at the symbol centers. DPSK demodulation is performed by computing the phase difference between two successive samples. Ideally, the result should be either 180 or 0. If it is different from those values, a Kalman filter tracks the error and subtracts it from the output.

Varicode Decoder accumulates the bits coming from the symbol sampler in the buffer until a 00 combination is received, then it decodes the bits into a character by table lookup and dumps the buffer.


The BPSK31 transmitter consists of the PSK Keyer and a mixer.

PSK Keyer receives characters to be transmitted, encodes them using the Varicode table, and generates the baseband BPSK31 signal. It also gnerates the preamble, post-amble, and nulls (when idle).

The Mixer multiplies the baseband signal by a complex sinusoid to shift it to the desired frequency.

Error correction in BPSK31

The QPSK31 mode has an error correction mechanism that improves the accuracy of message decoding in the receiver. The input message is encoded in the transmitter in a special way, and the transmitted sequence has twice as many bits as the original message (50% redundancy). This redundancy is then used in the decoder to correct the errors.

In the BPSK31 mode, no coding is performed at the transmit side. The Varicode character codes are transmitted in their original form and decoded in the receiver by simple table lookup.

Since all error correcting algorithms require redundancy, one might think that error correction in BPSK31 is impossible. This is not true. There is a certain amount of 'natural' redundancy in the messages typically sent by hams, due to the fact that some combinations of characters occur more ofthen than the others. I recorded a number of BPSK31 messages off the air (about 130,000 characters in total) and computed the redundancy for the pairs of characters. To my surprise, the redundancy level was over 30%, more than enough to justify an attempt to correct at least some errors.

Rocky 3.2 includes a BPSK31 error correction function based on the character pair statistics. This function can be turned on and off in the popup menu of the text display. When error correction is enabled, the signal is first decoded with the standard decoder, and the ouput text is printed in balck or gray, depending on the signal quality. About 1.5 seconds later this text is replaced with the output of the error-correcting decoder, and the characters, if corrected, change their color to pink.

Vector Network Analyzer

Paul N2PK, the author of N2PK Vector Network Analyzer (VNA), has discovered that SoftRock RXTX could be used to measure the complex impedance, reflection coefficient and VSWR of the device connected to its antenna terminals since all components that comprise a VNA were already present in the radio. He sent me his equations, and I implemented them in Rocky under his guidance.

Using this software-defined VNA, you can measure the parameters of your antenna and view their charts vs. frequency in real time.

Paul has written an excellent tutorial tha covers all aspects of VNA calibration and measurements, and describes the minor modifications in SoftRock requred to turn it into a VNA.

Screenshot by Bodo DJ9CS:
the VSWR chart of his short dipole for 80 m

Copyright © 1998-2020 Afreet Software, Inc.




Author's e-mail