Nothern Utah WebSDR Logo - A skep with a Yagi Northern Utah WebSDR
Receiving on multiple bands with the SDRPlay RSP1a and "csdr" and stream splitting

Preliminary Version

What is this?

There may be instances where it is desirable to recieve on multiple bands at once using a single SDR receiver - and what is described here is a fairly simple way to accomplish this.

For this example, we will be using an SDRPlay RSP1a and HA7ILM's "csdr" software (See: ) .  Also, we will be using a modified version of the "sdrplayalsa" utility developed by the Northern Utah WebSDR folks that has been tweaked to allow any arbitrary sample rate.  If you are interested in any bit of software feel free to make contact using the information found at the bottom of this page.  We will also use the "fplay" utility - a version of "aplay" modified to remove sample rate restrictions - and we will also use "fastloop", another modified Linux utility.

See the bottom of this page for links referring to "sdrplayalsa", "fplay", "fastloop" and configuration for duplicated audio streams.

PLEASE NOTE:  This technique may be used for any receiver from which the raw I/Q stream is available in STDOUT and is not limited to just SDRPlay devices!

Example - Receiving both 80 and 60 meters using one receiver:

Let us suppose that we wish to receive both the 80 and 60 meter band on the same receiver.  The useful frequencies on these bands are 3500-4000 kHz for 80 meters and 5200-5500 kHz for 60 - the precise frequencies are unimportant.  To make this work, we need to pick a frequency that is approximately midway between these two bands, so a nice, even frequency of 4500 kHz was used as this is (4500-3500)= 1 MHz above the bottom of 80 meters.  Similarly, if we presume 5500 kHz to be comfortably above all of the 60 meter frequencies, being (5500-4500)= 1 MHz above the center frequency.

Sample rate and filter selection:

Normally, we would pick a sample rate that would comfortably cover both frequency ranges.  According to the SDRPlay RSP1a data, the lowest sample rate allowed is 2 MSP.  For reasons of CPU utilization in the decimation process we should pick a sample frequency that is an integer multiple of our sample rate - and for this, let's pick the highest rate that an unmodified ALSA kernel on modern Ubuntu can support - 768 kHz - which means that we could use 2304 kHz, which is exactly three times our output sample rate.

Except that we can't!

Looking at the RSP specifications, we see that we have several choices of filters built into the hardware - namely 200, 300, 600, 1536, 5000, 6000, 7000 and 8000 kHz.  Because the bottom of 80 meters and top of 60 meters are about 2 MHz apart, we can't use the 1536 kHz filter as that would cut off too much of the desired frequency range.

Conversely, if we pick the the next-wider filter, 5000 kHz, we will be too wide for a 2304 kHz sample rate and we'll end up with aliasing/images across our receive bandwidth (e.g. signals where they shouldn't be!) which means that we must set our sample rate higher than that of the filter bandwidth so that we can remove these unwanted signals via software filtering.

What this means is that we will pick a sample rate higher than 5000 kHz, so we'll use (768 * 7) = 5376 kHz - which is exactly 7 times the 768 sample rate that we ultimately need:  This will put the image/aliases comfortably outside our hardware bandwidth so that we can remove them in software later on.

Converting to 80 meters:

We now know that we can tune our receiver to 4500 kHz, select a hardware filter bandwidth to 5000 kHz and a sample rate of 5376 kHz - covering approximately 2000-7000 kHz, wholly including the 80 and 60 meter bands.

For this, we'll use "sdrplayalsa" which can output the raw I/Q samples from the RSP1a and SDRPlay's API to STDOUT which we can then pipe to "csdr" for frequency conversion and decimation/filtering - again, any software that will output raw I/Q data from an SDR to STDOUT will work.  The "csdr" utility can be used with a number of data formats from floating point to signed or unsigned 8, 16 and 24 bit sources making it usable with a wide variety of data sources.

Consider the following line which yields 80 meters, a bandwidth of about 768 kHz, centered at 3700 kHz:

./sdrplayalsa/sdrplayalsa -i 1897 -r 5376000 -f 4500000 -B 5000 -g 30 -l 2 -q -R 0 \ | csdr convert_s16_f | csdr shift_addition_cc 0.148809523 | csdr fir_decimate_cc 7 0.1 HAMMING | csdr convert_f_s16 | ./fplay1 -c 2 -D plug:rx_ch1 -r 768000 -f s16_le --disable-softvol -B 40000  &

Disassembling this:

Converting to 60 meters:

The following line will take our raw I/Q samples and convert to a center frequency of 5300 kHz:

./sdrplayalsa/sdrplayalsa -i 1897 -r 5376000 -f 4500000 -B 5000 -g 30 -l 2 -q -R 0 \ | csdr convert_s16_f | csdr shift_addition_cc -0.148809523 | csdr fir_decimate_cc 7 0.1 HAMMING | csdr convert_f_s16 | ./fplay1 -c 2 -D plug:rx_ch1 -r 768000 -f s16_le --disable-softvol -B 40000  &

Looking carefully you'll noticed that the only difference is this statement:  csdr shift_addition_cc -0.148809523 which is now negative to yield a center frequency of 5300 using the same formula as above:
Instead of converting down in frequency, we are converting up by the same proportion as the center frequency of 5300 kHz is the same distance from our receiver center frequency of 4500 as the 3700 kHz center frequency of our 80 meter receiver, hence the difference being the sign.  Everything else is the same.

Receiving two bands at once:

Above we showed how to produce 80 meters and 60 meters - but not at the same time - but you probably noticed that the center frequency of the receiver (4500 kHz) and the sample rate (5376 kHz) was the same for both examples.  This was purposely done as we could use the same raw I/Q output from our receiver to yield both bands by splitting the STDOUT stream.  Fortunately, there is a utility called "pee" (yes, the name is intentional!) that is designed to take a stream like this and split it into as many instances as you like.  This utility is not native to Linux, but is contained in the "moreutils" package that may be installed (e.g. "sudo apt install moreutils").

With "moreutils" installed, you can invoke it as follows to spawn two separate conversions - one to 80 and the other to 60 meters - as follows:

./sdrplayalsa/sdrplayalsa -i 1897 -r 5376000 -f 4500000 -B 5000 -g 30 -l 2 -q -R 0 \ |
csdr convert_s16_f | pee 'csdr shift_addition_cc 0.148809523 | csdr fir_decimate_cc 7 0.1 HAMMING | csdr convert_f_s16 | ./fplay1 -c 2 -D plug:rx_ch0 -r 768000 -f s16_le --disable-softvol -B 40000' 'csdr shift_addition_cc -0.148809523 | csdr fir_decimate_cc 7 0.1 HAMMING | csdr convert_f_s16 | ./fplay1 -c 2 -D plug:rx_ch1 -r 768000 -f s16_le --disable-softvol -B 40000' &

Note also that immediately after the "sdrplayalsa" portion, we have moved the statement "csdr convert_s16_f" - which converts the raw samples to floating point - so that is followed by the use of the "pee" utility:  Because we need floating point for all instances of csdr, we can convert the STDOUT stream to floating point first and thensplit the stream - which now conveys floating point - with "pee", saving a reasonable amount of CPU power by having only one instance where we convert from S16 to float.  Following the "pee" utility, you can see the two separate csdr and fplay instances, each one contained within single quotes ( ' ).

Finally, looking carefully and you'll also notice that for the first invocation which gives us 80 meters (with the "csdr shift_addition_cc 0.148809523" statement) the "fplay" is output to a device called "rx_ch0" while the second invocation
(with the "csdr shift_addition_cc 0.148809523" statement) which gives us 60 meters goes to a different device called "rx_ch1".  

CPU Utilization:

While this is purely subjective, knowing the relative CPU utilization of the various aspects of the signal processing can give a general idea as to how much CPU "power" each tasks take.  The system in question is an Intel i7-7700 (3.6 GHz) with eight cores.   The values below are from "htop" which can be somewhat inscrutible in terms of how things are calculated as the total may span multiple cores and the percentages may exceed 100%, but they are useful in the sense of relative usage.

Examples of relative utilization:

Comments and warnings:


The fairly-high sample rate of an inexpensive receiver such as the RSP1a can be easily used to provide multiple receivers.  In the example above, a "several MHz sample rate" is used to produce two 768 kHz streams to cover the 80 and 60 meter bands in their entirety - or even other band combinations.  If this is done, CPU utilization naturally increases as does the likelihood of receiver overload as more total signal power impinges on the A/D converter.

With the above in mind, it is possible to leverage receiver hardware to allow multiple "virtual" receivers to provide a wide variety of signal sources for WebSDRs or other applications.


You can find out more about many of the utilities mentioned above on this page: - Specifically, look at the bottom half for details on these topics.

Other related pages:

Additional information:
 Back to the Northern Utah WebSDR landing page