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"


読み込み中…
キャンセル
保存