NOAA APT image decoder. Runs on Linux, Windows and OSX.

Takes a recorded WAV file (from GQRX, SDR#, etc.) and decodes the raw image. Later you can rotate the image and adjust the contrast with something like GIMP or Photoshop.

Works with WAV files of any sample rate, 32 bit float or 16 bit integer encoded. When loading audio files with more than one channel, only the first one is used.

If you get some kind of error or bad result don’t hesitate to open a Issue or to send me an email. You can try to run the program with the --debug option for more info.

Table of contents



Run by clicking the executable, or from terminal without arguments. You can do two things:



$ ./noaa-apt --help

    ./target/release/noaa-apt [OPTIONS] [INPUT_FILENAME]

Decode NOAA APT images from WAV files. Run without arguments to launch the GUI

positional arguments:
  input_filename        Input WAV file.

optional arguments:
  -h,--help             show this help message and exit
  -d,--debug            Print debugging messages.
  -q,--quiet            Don't print info messages.
  -o,--output FILENAME  Set output path. When decoding images the default is
                        './output.png', when resampling the default is
  -r,--resample SAMPLE_RATE
                        Resample WAV file to a given sample rate, no APT image
                        will be decoded.


You can download executables for Linux or Windows from the releases page. Your options are:


From a WAV file I found somewhere on Internet, the US upside down:

Example image

The output is upside down if the satellite went from south to north instead of north to south that day.



Build with --release, Rust does some optimizations and it works MUCH faster. Really, otherwise it takes FOREVER.

Linux portable

I can’t make gtk-rs to work with the x86_64-unknown-linux-musl target, so I’m building with the default x86_64-unknown-linux-gnu on Debian Jessie. I think the binary works on any linux with GLIBC newer than the one used when building, that’s why I’m using a Debian Jessie docker image.

Mac / OSX

Build with --release, Rust does some optimizations and it works MUCH faster. Really, otherwise it takes FOREVER.

Windows portable

I never tried to compile from Windows, I cross-compile from Linux to Windows. I tried to get a mingw64-gtk environment to work on Debian without success. So I use a Docker image I found here.


These are the alternatives I found, as of August 2018:

Others I found on GitHub:

I measured the speed of most of them using the time utility from bash, and made a comparison of the results on ./extra/comparison.ods.



This program starts a new line when it receives a sync frame (those seven white and black stripes), works well if the signal has clear sync frames.

The first time I recorded a NOAA APT signal the bright parts had lot’s of noise (I think the FM demodulator bandwith was too narrow and had saturation when receiving white), the sync frames were really low quality and the alignment was really bad.

Every decoder I’ve tested, excluding WXtoIMG, has the same problem.


You need the GNU Scientific Library: sudo apt install libgsl0-dev libgsl0.

cargo test

If you get something like a wall of errors because linking with GSL fails, run with the GSLv2 feature:

cargo test --features GSLv2

Things to do

How it works


Resampling algorithm

I did something like what you can see here but with a easier (and slower) implementation.

Resampling algorithm

For each output sample, we calculate the sum of the products between input samples and filter coefficients.

AM demodulation

Previously I used a Hilbert filter to get the analytic signal, then the absolute value of the analytic signal is the modulated signal.

Then I found a very fast demodulator implemented on pietern/apt137. For each output sample, you only need the current input sample, the previous one and the carrier frequency:

AM demodulation formula

Where theta is the AM carrier frequency divided by the sample rate.

I couldn’t find the theory behind that method, looks similar to I/Q demodulation. I was able to reach that final expression (which is used by pietern/apt137) by hand and I wrote the steps on extra/demodulation.pdf. I think it only works if the input AM signal is oversampled, maybe that’s why I can’t find anything about it on the web.