Higher Fidelity OpenWebRX 1.0.0

The following details an attempt to increase bandwidth of OpenWebRx web SDR software to make it compatible with American modulation standards… namely +/- 10 kHz on American AM broadcast stations and the typical 16K0F3E FM modulation typically found on the FM amateur bands as well as government broadcasts such as NOAA weather transmitters.  This effort began early 2021…

TL;DR – The short answer is the instructions below provide clear improvement in AM reception, but not so much for FM.

AM Wide Mode for OpenWebRx SDR Server
AM Wide Mode for OpenWebRx SDR Server


OpenWebRX is a web based SDR receiver system with healthy and current development.


I run many web based systems including several KiwiSDR systems.  Each has their benefits.  I find the OpenWebRX paired with my AirSpy HF Discovery is my go to receiver in my local network here at the QTH.

More AM Bandwidth Please

The current developer of the OpenWebRX defends a EU bias towards both FM and AM spectral bandwidths.  The US AM stations often have modulation bandwidths exceeding the +/- 5 kHz of the stock OpenWebRX AM bandwidth.  This is the “safe” option to be sure since AM broadcast stations are spaced every 10 kHz.  However, stations are allowed to impinge on the spectrum of neighbors.  This is often the case with AM stations broadcasting music.  Such is the case with a local music station here in Virginia… WKCW AM.


…if broadcasters are going to the trouble and expense of transmitting fidelity, why should an SDR based system capable of demodulating all if it, be constrained anywhere in the signal chain.  Assuming bandwidth between the OpenWebRX web server and the web client is of little consequence (on the local network for example), there it little reason to throttle the capabilities of the SDR that probably cost you a bit of coin.

More FM Bandwidth Please

The US amateur radio FM segments still have, and likely will continue to have, wider FM spectral content.  NBFM (10K1F3E) [1] does exist, but the norm is +/- 8 kHz aka 16K0F3E.[2]  So really for use with the US systems, FM should be set to a wider RF bandwidth.  One potential problem with FM goal is outlined in the OpenWebRx email list.  More research needed, but it doesn’t seem to break anything obvious in actual implementation.

Another clue in interesting OpenWebRX FM demod is how the Packet digital mode passes lower frequency audio (I can hear CTCSS tones) and seemingly better fidelity… but that’s for another discussion.


Here’s the short list of goals…

  • Widen the FM radio spectrum to ensure all the energy of US FM transmissions are considered during the demodulation process.
  • Add a wide AM bandwidth option to the demodulation choices to take advantage of shortwave and broadcast stations that take the trouble to transmit a higher fidelity signal.
  • Ensure the audio streaming from OpenWebRX to the web client has sufficient fidelity.

OpenWebRX to rescue

Fortunately the code base of OpenWebRX lends itself well to modifications.  Just three files in the 1.0.0 distro need a few tweaks: csdr.py, modes.py and Demodulator.js.  The easiest way to show the changes is with the output of the diff and then with diff -u.


In the python world, apparently, the name of a file in a distro is often named __init__.py,  Such is the case in my R-Pi install.  This diff works for me, but substitute csdr.py for __init__.py if that’s what your install happens to be…

diff src/openwebrx-1.0.0/csdr/__init__.py /usr/lib/python3/dist-packages/csdr/__init__.py
< elif which == “am”:

> elif which in [“am”, “wam”]:
< return demodulator == “wfm”

> return demodulator in [“wfm”, “wam”]

…then with diff -u…

diff -u src/openwebrx-1.0.0/csdr/__init__.py /usr/lib/python3/dist-packages/csdr/__init__.py
— src/openwebrx-1.0.0/csdr/__init__.py 2021-05-08 19:10:58.000000000 +0000
+++ /usr/lib/python3/dist-packages/csdr/__init__.py 2021-05-10 15:44:34.454686391 +0000
@@ -201,7 +201,7 @@
“CSDR_FIXED_BUFSIZE=32 csdr agc_ff –max 0.005 –initial 0.0005”,
“sox -t raw -r 8000 -e floating-point -b 32 -c 1 –buffer 32 – -t raw -r {output_rate} -e signed-integer -b 16 -c 1 – “,
– elif which == “am”:
+ elif which in [“am”, “wam”]:
chain += [“csdr amdemod_cf”, “csdr fastdcblock_ff”]
chain += last_decimation_block
chain += [
@@ -546,7 +546,7 @@
def isHdAudio(self, demodulator=None):
if demodulator is None:
demodulator = self.get_demodulator()
– return demodulator == “wfm”
+ return demodulator in [“wfm”, “wam”]

def isDrm(self, demodulator=None):
if demodulator is None:


diff src/openwebrx-1.0.0/owrx/modes.py /usr/lib/python3/dist-packages/owrx/modes.py
< AnalogMode(“nfm”, “FM”, bandpass=Bandpass(-4000, 4000)),

> AnalogMode(“nfm”, “FM”, bandpass=Bandpass(-8000, 8000)),
< AnalogMode(“am”, “AM”, bandpass=Bandpass(-4000, 4000)),

> AnalogMode(“am”, “AM”, bandpass=Bandpass(-5000, 5000)),
> AnalogMode(“wam”, “wAM”, bandpass=Bandpass(-9700, 9700)),

…then with diff -u…

diff -u src/openwebrx-1.0.0/owrx/modes.py /usr/lib/python3/dist-packages/owrx/modes.py
— src/openwebrx-1.0.0/owrx/modes.py 2021-05-08 19:10:58.000000000 +0000
+++ /usr/lib/python3/dist-packages/owrx/modes.py 2021-05-11 18:25:42.658123441 +0000
@@ -90,9 +90,10 @@

class Modes(object):
mappings = [
– AnalogMode(“nfm”, “FM”, bandpass=Bandpass(-4000, 4000)),
+ AnalogMode(“nfm”, “FM”, bandpass=Bandpass(-8000, 8000)),
AnalogMode(“wfm”, “WFM”, bandpass=Bandpass(-75000, 75000)),
– AnalogMode(“am”, “AM”, bandpass=Bandpass(-4000, 4000)),
+ AnalogMode(“am”, “AM”, bandpass=Bandpass(-5000, 5000)),
+ AnalogMode(“wam”, “wAM”, bandpass=Bandpass(-9700, 9700)),
AnalogMode(“lsb”, “LSB”, bandpass=Bandpass(-3000, -300)),
AnalogMode(“usb”, “USB”, bandpass=Bandpass(300, 3000)),
AnalogMode(“cw”, “CW”, bandpass=Bandpass(700, 900)),

I chose “wAM” just to have it stand out in the menu.  Most of you will logically choose ‘WAM” for your system.  The point is you can call it “Fred” or whatever you want in the section of the code.


diff src/openwebrx-1.0.0/htdocs/lib/Demodulator.js /usr/lib/python3/dist-packages/htdocs/lib/Demodulator.js
> } else if (this.demodulator.get_modulation() === ‘nfm’) {
> max_bw = 10000;
> } else if (this.demodulator.get_modulation() === ‘wam’) {
> max_bw = 10000;

… diff -u …

diff -u src/openwebrx-1.0.0/htdocs/lib/Demodulator.js /usr/lib/python3/dist-packages/htdocs/lib/Demodulator.js
— src/openwebrx-1.0.0/htdocs/lib/Demodulator.js 2021-05-08 19:10:58.000000000 +0000
+++ /usr/lib/python3/dist-packages/htdocs/lib/Demodulator.js 2021-05-11 18:30:23.864121553 +0000
@@ -11,6 +11,10 @@
max_bw = 6250;
} else if (this.demodulator.get_modulation() === ‘wfm’) {
max_bw = 100000;
+ } else if (this.demodulator.get_modulation() === ‘nfm’) {
+ max_bw = 10000;
+ } else if (this.demodulator.get_modulation() === ‘wam’) {
+ max_bw = 10000;
} else if (this.demodulator.get_modulation() === ‘drm’) {
max_bw = 50000;
} else {

This is an OpenWebRX hack

Make no mistake… this is an unsupported hack to the OpenWebRX code.


The author frequently notes in the OpenWebRX support forum the Eurocentric (aka narrower RF radio bandwidth) design.  The scorecard of the author is in good shape as the OpenWebRX systems works very well in my experience.  The curator of the OpenWebRX development project barely tolerates discussion of this topic in the support forum.  Thankfully some critical input from others survived and helped round out the tweaks to get all this working.


I tend to just ignore the bias and hack away.  Fortunately the well organized code base makes the process not necessarily easy, but straightforward.


The above changes to both AM and FM demod bandwidths were made specifically to the 1.0.0 release.  I applied these adjustments previously to the 0.20.3 version (same tweaks, but line numbers were different) with similar success.  Whether or not this will work for future releases is unknowable as the author claims the entire signal flow may undergo some serious redesign.  For now, those with 1.0.0 have a way for higher fidelity sound from OpenWebRX.

  • AM results: Even the cheapest speaker reveals dramatic improvement in audio fidelity for +/- 10 kHz AM signals.  There may well be some other limit at play that might prevent the highest frequencies, but there’s no question things are better.
  • FM results: Mixed and confusing.  The discussion on how the demod and audio sampling occurs and interrelates may suggest a limit to what can actually be done to make OpenWebRX compatible with American FM deviation rates.  For now this is a work in progress, but at least the above tweaks offer the tester a place to start.

AM works better.  FM not so much… yet.

Sometimes hacks help
Sometimes hacks are necessary for progress


  1. 10K1F3E – Frequency modulated (FM) 2.5 kHz deviation analog voice, “narrowband 12.5 kHz” (FMN mode in RadioReference.com Database). Commonly used as a designator in Australia and Canada, identical to 11K2F3E.
  2. 16K0F3E – Frequency modulated (FM) analog voice, 4 kHz deviation (NPSPAC); (FM mode in RadioReference.com Database).

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.