7 次代码提交

作者 SHA1 备注 提交日期
  Xerbo 66b8dd026e
Fix memory leak and move state entirely into aptdec_t 1年前
  Xerbo 071a9c8f84
Better naming, but valid this time 1年前
  Xerbo c9d89ea210
Better naming 1年前
  Xerbo 61ec605ffd
Fix syntax 1年前
  Xerbo 8c6cba0aa3
ARM builds 1年前
  Xerbo 711d0e0163
MSVC build in GitHub actions 1年前
  Xerbo c551e70335
Include missing header and fix stddev 1年前
共有 13 个文件被更改,包括 172 次插入56 次删除
  1. +2
    -3
      .github/ISSUE_TEMPLATE/bug-report.md
  2. +49
    -6
      .github/workflows/build.yml
  3. +1
    -0
      .gitignore
  4. +3
    -2
      CMakeLists.txt
  5. +34
    -0
      UPGRADE_GUIDE.md
  6. +1
    -0
      aptdec-cli/main.c
  7. +18
    -0
      build_arm.sh
  8. +13
    -11
      build_windows.bat
  9. +19
    -0
      cmake/toolchain-armhf.cmake
  10. +1
    -1
      cmake/toolchain-mingw32.cmake
  11. +3
    -6
      libaptdec/algebra.c
  12. +27
    -27
      libaptdec/dsp.c
  13. +1
    -0
      libaptdec/effects.c

+ 2
- 3
.github/ISSUE_TEMPLATE/bug-report.md 查看文件

@@ -4,7 +4,6 @@ about: Create a bug report to improve aptdec
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
@@ -17,7 +16,7 @@ Steps to reproduce the behavior.
A clear description of what you expected to happen.

**Link to audio**
A link to the audio that caused the problem.
A link to the audio file that caused the problem (if applicable).

**Build information**
The commit of aptdec you are running (check with `git rev-parse HEAD`), make sure it's up to date before opening this issue.
The version of aptdec you are running (check with `git describe --tag`), make sure it's up to date before opening this issue.

+ 49
- 6
.github/workflows/build.yml 查看文件

@@ -29,16 +29,16 @@ jobs:
- name: Build and package
run: cmake --build build -j$(nproc) && cmake --build build --target package

- name: Upload TGZ package
- name: Upload TGZ archive
uses: actions/upload-artifact@v3
with:
name: TGZ package
name: TGZ archive (x86_64-gcc)
path: build/aptdec_*.tar.gz

- name: Upload DEB package
- name: Upload Debian package
uses: actions/upload-artifact@v3
with:
name: Debian package
name: Debian package (x86_64-gcc)
path: build/aptdec_*.deb

build_windows:
@@ -56,8 +56,51 @@ jobs:
- name: Run build script
run: ./build_windows.sh $BUILD_TYPE

- name: Upload ZIP package
- name: Upload ZIP archive
uses: actions/upload-artifact@v3
with:
name: ZIP package
name: ZIP archive (x86_64-MinGW)
path: winbuild/aptdec_*.zip
build_windows_msvc:
runs-on: windows-latest

steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
fetch-depth: 0

- name: Run build script
shell: cmd
run: '"C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat" & build_windows.bat'

- name: Upload ZIP archive
uses: actions/upload-artifact@v3
with:
name: ZIP archive (x86_64-MSVC)
path: winbuild/aptdec_*.zip
build_linux_armhf:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
fetch-depth: 0

- name: Run build script
run: docker run -v $(pwd):/aptdec:z -w /aptdec debian:11 ./build_arm.sh

- name: Upload Debian package
uses: actions/upload-artifact@v3
with:
name: Debian package (armhf-gcc)
path: build/aptdec_*.deb

- name: Upload TGZ archive
uses: actions/upload-artifact@v3
with:
name: TGZ archive (armhf-gcc)
path: build/aptdec_*.tar.gz

+ 1
- 0
.gitignore 查看文件

@@ -89,3 +89,4 @@ zlib/
libpng/
libsndfile-*-win64.zip
libsndfile-*-win64/
root/

+ 3
- 2
CMakeLists.txt 查看文件

@@ -79,13 +79,14 @@ endif()
install(TARGETS aptdec PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aptdec LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

# Packaging
set(CPACK_PACKAGE_VERSION "${VERSION}")
string(REPLACE v "" CPACK_PACKAGE_VERSION ${VERSION})
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
set(CPACK_PACKAGE_NAME "aptdec")
set(CPACK_PACKAGE_CONTACT "Xerbo (xerbo@protonmail.com)")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "NOAA APT satellite imagery decoder")
set(CPACK_PACKAGE_DESCRIPTION "Aptdec is a FOSS library/program that decodes images transmitted by the NOAA POES weather satellites. These satellites transmit constantly (among other things) medium resolution (4km/px) images of the earth over a analog mode called APT.")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}.${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libsndfile1, libpng16-16")

if(WIN32)
file(GLOB DLLS ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/*.dll)


+ 34
- 0
UPGRADE_GUIDE.md 查看文件

@@ -0,0 +1,34 @@
# Upgrading from aptdec 1.8.0 to 2.0.0

# `aptdec` (now `aptdec-cli`)

## Removed

- The `-d` (output directory) flag
- The `-g` (gamma) flag
- Map overlays/MCIR
- Reading raw PNG images

(Some of these features have been moved into `aptdec_post.py`)

## Changes

- "palettes" are now called "luts"
- Image type and effects are now full English words (separated by commas) instead of letters
- Output format of realtime images is now `CURRENT_TIME.png` instead of `CURRENT_TIME-r.png`
- Channel A/B images include telemetry

## Examples

| v1.8 | v2.0.0 |
|---------------------------------------|-------------------------------------------|
| `aptdec file.wav` | `aptdec-cli file.wav` |
| `aptdec -i rt file.wav` | `aptdec-cli -i raw,thermal file.wav` |
| `aptdec -i ab file.wav` | `aptdec-cli -i a,b -e strip file.wav` |
| `aptdec -i p -p palette.png file.wav` | `aptdec-cli -i lut -l lut.png file.wav` |
| `aptdec -d out *.wav` | `mkdir out; cd out; aptdec-cli ../*.wav` |


# `libapt` (now `libaptdec`)

To avoid confusion with `apt` (the Debian package manager) the name of the aptdec library has been changed to `libaptdec`.

+ 1
- 0
aptdec-cli/main.c 查看文件

@@ -244,6 +244,7 @@ static int process_file(const char *path, options_t *opts) {
// Normalize
int error;
apt_image_t img = apt_normalize(data, rows, opts->satellite, &error);
free(data);
if (error) {
error_noexit("Normalization failed");
return 0;


+ 18
- 0
build_arm.sh 查看文件

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# This script only works on Debian Bullseye
# If you have docker this is trivially easy:
# docker run -v $(pwd):/aptdec:z -w /aptdec debian:11 ./build_arm.sh

apt-get update
apt-get install -y debootstrap cmake gcc-arm-linux-gnueabihf

# Prepare armhf root environment
if [ ! -d root ]; then
debootstrap --keyring=/usr/share/keyrings/debian-archive-keyring.gpg --arch=armhf --include=libsndfile1-dev,libpng-dev --download-only bullseye root http://deb.debian.org/debian/
for i in root/var/cache/apt/archives/*.deb; do dpkg -x "$i" root; done
fi

# Build aptdec
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DCMAKE_INSTALL_PREFIX=/aptdec/root
cmake --build build -j$(nproc)
cmake --build build --target package

+ 13
- 11
build_windows.bat 查看文件

@@ -1,36 +1,38 @@
REM Build using MSVC on Windows
REM Requires: git, cmake and ninja
REM You need to run vcvars before running this
REM Build zlib
IF NOT EXIST zlib (
git clone -b v1.2.13 https://github.com/madler/zlib
git clone --depth 1 -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 -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath
cmake --build build -j%NUMBER_OF_PROCESSORS%
cmake --build build --target install
cd ..
)
REM Build libpng
IF NOT EXIST libpng (
git clone -b v1.6.39 https://github.com/glennrp/libpng
git clone --depth 1 -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 -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath -DPNG_STATIC=OFF -DPNG_EXECUTABLES=OFF -DPNG_TESTS=OFF
cmake --build build -j%NUMBER_OF_PROCESSORS%
cmake --build build --target install
cd ..
)
REM Build libsndfile, only with WAV support
IF NOT EXIST libsndfile (
git clone -b 1.2.0 https://github.com/libsndfile/libsndfile
git clone --depth 1 -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 -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF -DBUILD_PROGRAMS=OFF
cmake --build build -j%NUMBER_OF_PROCESSORS%
cmake --build build --target install
cd ..
)
REM Build aptdec
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
cmake -B winbuild -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../winpath
cmake --build winbuild -j%NUMBER_OF_PROCESSORS%
cmake --build winbuild --target package

+ 19
- 0
cmake/toolchain-armhf.cmake 查看文件

@@ -0,0 +1,19 @@
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_PROCESSOR armhf)

# which compilers to use for C and C++
SET(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf/ ${CMAKE_INSTALL_PREFIX})
# Hack
link_directories(${CMAKE_INSTALL_PREFIX}/lib/arm-linux-gnueabihf)

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 1
- 1
cmake/toolchain-mingw32.cmake 查看文件

@@ -1,6 +1,6 @@
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR amd64)
SET(CMAKE_SYSTEM_PROCESSOR x86_64)

# which compilers to use for C and C++
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)


+ 3
- 6
libaptdec/algebra.c 查看文件

@@ -52,12 +52,9 @@ linear_t linear_regression(const float *independent, const float *dependent, siz
return (linear_t){a, b};
}

// "Sample" standard deviation
float standard_deviation(const float *data, size_t len) {
float mean = 0.0f;
for (size_t i = 0; i < len; i++) {
mean += data[i];
}
mean /= (float)len;
float mean = meanf(data, len);

float deviation_mean = 0.0f;
for (size_t i = 0; i < len; i++) {
@@ -65,7 +62,7 @@ float standard_deviation(const float *data, size_t len) {
deviation_mean += deviation * deviation;
}

return sqrtf(deviation_mean / (float)len);
return sqrtf(deviation_mean / (float)(len-1));
}

float sumf(const float *x, size_t len) {


+ 27
- 27
libaptdec/dsp.c 查看文件

@@ -32,6 +32,10 @@
#define CARRIER_FREQ 2400.0f
#define MAX_CARRIER_OFFSET 10.0f

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};
#define SYNC_SIZE (sizeof(sync_pattern)/sizeof(sync_pattern[0]))

typedef struct {
float alpha;
float beta;
@@ -58,6 +62,11 @@ struct aptdec_t {
fir_t *hilbert;

float low_pass[LOW_PASS_SIZE];
float row_buffer[APT_IMG_WIDTH + SYNC_SIZE + 2];

float interpolator_buffer[APTDEC_BUFFER_SIZE];
size_t interpolator_n;
float interpolator_offset;
};

char *aptdec_get_version(void) {
@@ -162,47 +171,38 @@ 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[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 > APTDEC_BUFFER_SIZE) {
memcpy(buffer, &buffer[n], (APTDEC_BUFFER_SIZE-n) * sizeof(float));
if (apt->interpolator_n + LOW_PASS_SIZE > APTDEC_BUFFER_SIZE) {
memcpy(apt->interpolator_buffer, &apt->interpolator_buffer[apt->interpolator_n], (APTDEC_BUFFER_SIZE-apt->interpolator_n) * sizeof(float));

size_t read = am_demod(apt, &buffer[APTDEC_BUFFER_SIZE-n], n, callback, context);
if (read != n) {
size_t read = am_demod(apt, &apt->interpolator_buffer[APTDEC_BUFFER_SIZE-apt->interpolator_n], apt->interpolator_n, callback, context);
if (read != apt->interpolator_n) {
return i;
}
n = 0;
apt->interpolator_n = 0;
}

out[i] = interpolating_convolve(&buffer[n], apt->low_pass, LOW_PASS_SIZE, offset);
out[i] = interpolating_convolve(&apt->interpolator_buffer[apt->interpolator_n], apt->low_pass, LOW_PASS_SIZE, apt->interpolator_offset);

// Do not question the sacred code
int shift = ceilf(ratio - offset);
offset = shift + offset - ratio;
n += shift;
int shift = ceilf(ratio - apt->interpolator_offset);
apt->interpolator_offset = shift + apt->interpolator_offset - ratio;
apt->interpolator_n += shift;
}

return count;
}

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};
#define SYNC_SIZE (sizeof(sync_pattern)/sizeof(sync_pattern[0]))

// Get an entire row of pixels, aligned with sync markers
int aptdec_getrow(aptdec_t *apt, float *row, aptdec_callback_t callback, void *context) {
static float pixels[APT_IMG_WIDTH + SYNC_SIZE + 2];

// Wrap the circular buffer
memcpy(pixels, &pixels[APT_IMG_WIDTH], (SYNC_SIZE + 2) * sizeof(float));
memcpy(apt->row_buffer, &apt->row_buffer[APT_IMG_WIDTH], (SYNC_SIZE + 2) * sizeof(float));

// Get a lines worth (APT_IMG_WIDTH) of samples
if (get_pixels(apt, &pixels[SYNC_SIZE + 2], APT_IMG_WIDTH, callback, context) != APT_IMG_WIDTH) {
if (get_pixels(apt, &apt->row_buffer[SYNC_SIZE + 2], APT_IMG_WIDTH, callback, context) != APT_IMG_WIDTH) {
return 0;
}

@@ -213,9 +213,9 @@ int aptdec_getrow(aptdec_t *apt, float *row, aptdec_callback_t callback, void *c
size_t phase = 0;

for (size_t i = 0; i < APT_IMG_WIDTH; i++) {
float _left = convolve(&pixels[i + 0], sync_pattern, SYNC_SIZE);
float _middle = convolve(&pixels[i + 1], sync_pattern, SYNC_SIZE);
float _right = convolve(&pixels[i + 2], sync_pattern, SYNC_SIZE);
float _left = convolve(&apt->row_buffer[i + 0], sync_pattern, SYNC_SIZE);
float _middle = convolve(&apt->row_buffer[i + 1], sync_pattern, SYNC_SIZE);
float _right = convolve(&apt->row_buffer[i + 2], sync_pattern, SYNC_SIZE);
if (_middle > middle) {
left = _left;
middle = _middle;
@@ -226,11 +226,11 @@ int aptdec_getrow(aptdec_t *apt, float *row, aptdec_callback_t callback, void *c

// Frequency
float bias = (left / middle) - (right / middle);
apt->sync_frequency = 1.0f + bias / APT_IMG_WIDTH / 2.0f;
apt->sync_frequency = 1.0f + bias / APT_IMG_WIDTH / 4.0f;

// Phase
memcpy(&row[APT_IMG_WIDTH], &pixels[phase], (APT_IMG_WIDTH - phase) * sizeof(float));
memcpy(&row[APT_IMG_WIDTH - phase], pixels, phase * sizeof(float));
memcpy(&row[APT_IMG_WIDTH], &apt->row_buffer[phase], (APT_IMG_WIDTH - phase) * sizeof(float));
memcpy(&row[APT_IMG_WIDTH - phase], apt->row_buffer, phase * sizeof(float));

return 1;
}

+ 1
- 0
libaptdec/effects.c 查看文件

@@ -20,6 +20,7 @@
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#include "algebra.h"
#include "util.h"


正在加载...
取消
保存