@@ -70,11 +70,10 @@ aptdec-cli -i lut -l luts/WXtoImg-N18-HVC.png gqrx_20200527_115730_137914960.wav | |||
### Arguments | |||
``` | |||
-h, --help show a help message and exit | |||
-i, --image=<str> set output image type (see below) | |||
-e, --effect=<str> add an effect (see below) | |||
-g, --gamma=<flt> gamma adjustment (1.0 = off) | |||
-s, --satellite=<int> satellite ID, must be between 15, 18 or 19 or NORAD | |||
-h, --help show this help message and exit | |||
-i, --image=<str> set output image type (see the README for a list) | |||
-e, --effect=<str> add an effect (see the README for a list) | |||
-s, --satellite=<int> satellite ID, must be either NORAD or 15/18/19 | |||
-l, --lut=<str> path to a LUT | |||
-o, --output=<str> path of output image | |||
-r, --realtime decode in realtime | |||
@@ -129,7 +128,7 @@ sudo apt install wget cmake make mingw-w64 git unzip | |||
To build natively on Windows using MSVC, you will need: git, ninja and cmake. Then run: | |||
``` | |||
.\build_windows.bat | |||
./build_windows.bat | |||
``` | |||
If you only want to build libaptdec, libpng and libsndfile aren't needed. | |||
@@ -110,7 +110,7 @@ int main(int argc, const char **argv) { | |||
OPT_STRING('i', "image", &opts.type, "set output image type (see the README for a list)", NULL, 0, 0), | |||
OPT_STRING('e', "effect", &opts.effects, "add an effect (see the README for a list)", NULL, 0, 0), | |||
OPT_GROUP("Satellite options"), | |||
OPT_INTEGER('s', "satellite", &opts.satellite, "satellite ID, must be either NORAD or between 15 and 19", NULL, 0, 0), | |||
OPT_INTEGER('s', "satellite", &opts.satellite, "satellite ID, must be either NORAD or 15/18/19", NULL, 0, 0), | |||
OPT_GROUP("Paths"), | |||
OPT_STRING('l', "lut", &opts.lut, "path to a LUT", NULL, 0, 0), | |||
OPT_STRING('o', "output", &opts.filename, "path of output image", NULL, 0, 0), | |||
@@ -454,7 +454,7 @@ static size_t callback(float *samples, size_t count, void *context) { | |||
case 1: | |||
return sf_read_float(file->file, samples, count); | |||
case 2: { | |||
float _samples[count * 2]; | |||
float _samples[APTDEC_BUFFER_SIZE * 2]; | |||
size_t read = sf_read_float(file->file, _samples, count * 2); | |||
for (size_t i = 0; i < count; i++) { | |||
@@ -22,7 +22,11 @@ | |||
#include <stddef.h> | |||
void error_noexit(const char *text); | |||
#ifdef _MSC_VER | |||
void error(const char *text); | |||
#else | |||
__attribute__((noreturn)) void error(const char *text); | |||
#endif | |||
void warning(const char *text); | |||
int clamp_int(int x, int lo, int hi); | |||
@@ -1,36 +1,36 @@ | |||
REM Build using Visual Studio 2019 on Windows | |||
REM Additional tools needed: git, cmake and ninja | |||
REM Build using MSVC on Windows | |||
REM Requires: git, cmake and ninja | |||
REM Build zlib | |||
git clone -b v1.2.13 https://github.com/madler/zlib | |||
cd zlib | |||
mkdir build | |||
cd build | |||
cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath .. | |||
ninja install | |||
cd ../../ | |||
IF NOT EXIST zlib ( | |||
git clone -b v1.2.13 https://github.com/madler/zlib | |||
cd zlib | |||
cmake -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath | |||
cmake --build build -j4 | |||
cmake --build build --target install | |||
cd .. | |||
) | |||
REM Build libpng | |||
git clone -b v1.6.39 https://github.com/glennrp/libpng | |||
cd libpng | |||
mkdir build | |||
cd build | |||
cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath .. | |||
ninja install | |||
cd ../.. | |||
IF NOT EXIST libpng ( | |||
git clone -b v1.6.39 https://github.com/glennrp/libpng | |||
cd libpng | |||
cmake -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath -DPNG_STATIC=OFF -DPNG_EXECUTABLES=OFF -DPNG_TESTS=OFF | |||
cmake --build build -j4 | |||
cmake --build build --target install | |||
cd .. | |||
) | |||
REM Build libsndfile - Could build Vorbis, FLAC and Opus first for extra support | |||
git clone -b 1.1.0 https://github.com/libsndfile/libsndfile | |||
cd libsndfile | |||
mkdir build | |||
cd build | |||
cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../winpath .. | |||
ninja install | |||
cd ../.. | |||
REM Build libsndfile, only with WAV support | |||
IF NOT EXIST libsndfile ( | |||
git clone -b 1.2.0 https://github.com/libsndfile/libsndfile | |||
cd libsndfile | |||
cmake -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath -BUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF -DBUILD_PROGRAMS=OFF | |||
cmake --build build -j4 | |||
cmake --build build --target install | |||
cd .. | |||
) | |||
REM Build aptdec | |||
mkdir winbuild | |||
cd winbuild | |||
cmake -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath .. | |||
ninja install | |||
cd .. | |||
cmake -B winbuild -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=190 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath | |||
cmake --build winbuil -j4 |
@@ -17,7 +17,7 @@ fi | |||
# Build libpng from source | |||
if [ ! -d "libpng" ]; then | |||
git clone --depth 1 -b v1.6.39 https://github.com/glennrp/libpng && cd libpng | |||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$TEMP_PATH | |||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$TEMP_PATH -DPNG_STATIC=OFF -DPNG_EXECUTABLES=OFF -DPNG_TESTS=OFF | |||
cmake --build build -j$(nproc) | |||
cmake --build build --target install | |||
cd .. | |||
@@ -27,7 +27,6 @@ | |||
#include "util.h" | |||
#include "algebra.h" | |||
#define BUFFER_SIZE 16384 | |||
#define LOW_PASS_SIZE 101 | |||
#define CARRIER_FREQ 2400.0f | |||
@@ -113,7 +112,7 @@ aptdec_t *aptdec_init(float sample_rate) { | |||
} | |||
// Hilbert transform | |||
apt->hilbert = fir_init(BUFFER_SIZE, 31); | |||
apt->hilbert = fir_init(APTDEC_BUFFER_SIZE, 31); | |||
if (apt->hilbert == NULL) { | |||
free(apt->pll); | |||
free(apt); | |||
@@ -163,18 +162,18 @@ static int am_demod(aptdec_t *apt, float *out, size_t count, aptdec_callback_t c | |||
} | |||
static int get_pixels(aptdec_t *apt, float *out, size_t count, aptdec_callback_t callback, void *context) { | |||
static float buffer[BUFFER_SIZE]; | |||
static size_t n = BUFFER_SIZE; | |||
static float buffer[APTDEC_BUFFER_SIZE]; | |||
static size_t n = APTDEC_BUFFER_SIZE; | |||
static float offset = 0.0; | |||
float ratio = apt->sample_rate / (4160.0f * apt->sync_frequency); | |||
for (size_t i = 0; i < count; i++) { | |||
// Get more samples if there are less than `LOW_PASS_SIZE` available | |||
if (n + LOW_PASS_SIZE > BUFFER_SIZE) { | |||
memcpy(buffer, &buffer[n], (BUFFER_SIZE-n) * sizeof(float)); | |||
if (n + LOW_PASS_SIZE > APTDEC_BUFFER_SIZE) { | |||
memcpy(buffer, &buffer[n], (APTDEC_BUFFER_SIZE-n) * sizeof(float)); | |||
size_t read = am_demod(apt, &buffer[BUFFER_SIZE-n], n, callback, context); | |||
size_t read = am_demod(apt, &buffer[APTDEC_BUFFER_SIZE-n], n, callback, context); | |||
if (read != n) { | |||
return i; | |||
} | |||
@@ -138,7 +138,7 @@ int apt_crop(apt_image_t *img) { | |||
const float sync_pattern[] = {-1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, | |||
1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 0}; | |||
float spc_rows[img->rows]; | |||
float *spc_rows = (float *)malloc(img->rows * sizeof(float)); | |||
int startCrop = 0; | |||
int endCrop = img->rows; | |||
@@ -171,5 +171,6 @@ int apt_crop(apt_image_t *img) { | |||
// Remove the noisy rows at start | |||
memmove(img->data, &img->data[startCrop * APT_IMG_WIDTH], img->rows * APT_IMG_WIDTH * sizeof(float)); | |||
free(spc_rows); | |||
return startCrop; | |||
} |
@@ -98,7 +98,11 @@ complexf_t hilbert_transform(const float *in, const float *taps, size_t len) { | |||
} | |||
float interpolating_convolve(const float *in, const float *taps, size_t len, float offset) { | |||
#ifdef _MSC_VER | |||
float *_taps = (float *)_alloca(len * sizeof(float)); | |||
#else | |||
float _taps[len]; | |||
#endif | |||
for (size_t i = 0; i < len; i++) { | |||
float next = (i == len-1) ? 0.0f : taps[i+1]; | |||
@@ -38,7 +38,7 @@ apt_image_t apt_image_clone(apt_image_t img) { | |||
static void decode_telemetry(const float *data, size_t rows, size_t offset, float *wedges) { | |||
// Calculate row average | |||
float telemetry_rows[rows]; | |||
float *telemetry_rows = (float *)malloc(rows * sizeof(float)); | |||
for (size_t y = 0; y < rows; y++) { | |||
telemetry_rows[y] = meanf(&data[y*APT_IMG_WIDTH + offset + APT_CH_WIDTH], APT_TELEMETRY_WIDTH); | |||
} | |||
@@ -74,10 +74,12 @@ static void decode_telemetry(const float *data, size_t rows, size_t offset, floa | |||
for (size_t i = 0; i < APT_FRAME_WEDGES; i++) { | |||
wedges[i] = meanf(&telemetry_rows[best_frame + i*APT_WEDGE_HEIGHT], APT_WEDGE_HEIGHT); | |||
} | |||
free(telemetry_rows); | |||
} | |||
static float average_spc(apt_image_t *img, size_t offset) { | |||
float rows[img->rows]; | |||
float *rows = (float *)malloc(img->rows * sizeof(float)); | |||
float average = 0.0f; | |||
for (size_t y = 0; y < img->rows; y++) { | |||
float row_average = 0.0f; | |||
@@ -100,6 +102,7 @@ static float average_spc(apt_image_t *img, size_t offset) { | |||
} | |||
} | |||
free(rows); | |||
return weighted_average / (float)n; | |||
} | |||
@@ -64,6 +64,8 @@ extern "C" { | |||
// Number of rows needed for apt_normalize to (reliably) work | |||
#define APTDEC_NORMALIZE_ROWS (APT_FRAME_LEN * 2) | |||
// Maximum amount of samples that will be requested from aptdec_callback_t | |||
#define APTDEC_BUFFER_SIZE 16384 | |||
// Channel 1: visible (0.58-0.68 um) | |||
// Channel 2: near-IR (0.725-1.0 um) | |||
@@ -115,7 +117,7 @@ typedef size_t (*aptdec_callback_t)(float *samples, size_t count, void *context) | |||
// Clone an apt_image_t struct | |||
// Useful for calibration | |||
apt_image_t apt_image_clone(apt_image_t img); | |||
APTDEC_API apt_image_t apt_image_clone(apt_image_t img); | |||
// Returns version of libaptdec in git tag format | |||
// i.e. v2.0.0 or v2.0.0-1-xxxxxx | |||
@@ -159,8 +161,8 @@ static const apt_region_t APT_REGION_CHA_FULL = { 0, APT_IMG_WIDTH | |||
static const apt_region_t APT_REGION_CHB_FULL = { APT_IMG_WIDTH/2, APT_IMG_WIDTH/2 }; | |||
static const apt_region_t APT_REGION_FULL = { 0, APT_IMG_WIDTH }; | |||
extern const uint32_t temperature_gradient[256]; | |||
extern const uint32_t precipitation_gradient[58]; | |||
APTDEC_API extern const uint32_t temperature_gradient[256]; | |||
APTDEC_API extern const uint32_t precipitation_gradient[58]; | |||
#ifdef __cplusplus | |||
} | |||