@@ -18,7 +18,9 @@ jobs: | |||||
runs-on: ubuntu-latest | runs-on: ubuntu-latest | ||||
steps: | steps: | ||||
- uses: actions/checkout@v2 | |||||
- uses: actions/checkout@v3 | |||||
with: | |||||
submodules: 'recursive' | |||||
- name: Install dependencies | - name: Install dependencies | ||||
# The user does not run as root | # The user does not run as root | ||||
@@ -41,7 +41,7 @@ if (PNG_FOUND AND LIBSNDFILE_FOUND) | |||||
if(CMAKE_BUILD_TYPE MATCHES "Release") | if(CMAKE_BUILD_TYPE MATCHES "Release") | ||||
target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | ||||
else() | else() | ||||
target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic) | |||||
target_compile_options(aptdec PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | |||||
endif() | endif() | ||||
endif() | endif() | ||||
else() | else() | ||||
@@ -59,7 +59,7 @@ else() | |||||
if(CMAKE_BUILD_TYPE MATCHES "Release") | if(CMAKE_BUILD_TYPE MATCHES "Release") | ||||
target_compile_options(apt PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | target_compile_options(apt PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | ||||
else() | else() | ||||
target_compile_options(apt PRIVATE -Wall -Wextra -pedantic) | |||||
target_compile_options(apt PRIVATE -Wall -Wextra -pedantic -Wno-missing-field-initializers) | |||||
endif() | endif() | ||||
endif() | endif() | ||||
@@ -1,20 +1,19 @@ | |||||
/* | |||||
* This file is part of Aptdec. | |||||
* Copyright (c) 2004-2009 Thierry Leconte (F4DWV), Xerbo (xerbo@protonmail.com) 2019-2022 | |||||
/* | |||||
* aptdec - A lightweight FOSS (NOAA) APT decoder | |||||
* Copyright (C) 2004-2009 Thierry Leconte (F4DWV) 2019-2022 Xerbo (xerbo@protonmail.com) | |||||
* | * | ||||
* Aptdec is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | * | ||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | * | ||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
*/ | */ | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
@@ -24,6 +23,7 @@ | |||||
#include "apt.h" | #include "apt.h" | ||||
#include "filter.h" | #include "filter.h" | ||||
#include "taps.h" | |||||
// In case your C compiler is so old that Pi hadn't been invented yet | // In case your C compiler is so old that Pi hadn't been invented yet | ||||
#ifndef M_PI | #ifndef M_PI | ||||
@@ -41,13 +41,13 @@ | |||||
#define RSMULT 15 | #define RSMULT 15 | ||||
#define Fi (Fp * RSMULT) | #define Fi (Fp * RSMULT) | ||||
static double Fe; | |||||
static float Fe; | |||||
static double offset = 0.0; | |||||
static double FreqLine = 1.0; | |||||
static float offset = 0.0; | |||||
static float FreqLine = 1.0; | |||||
static double FreqOsc; | |||||
static double K1, K2; | |||||
static float FreqOsc; | |||||
static float K1, K2; | |||||
// Check the sample rate and calculate some constants | // Check the sample rate and calculate some constants | ||||
int apt_init(double F) { | int apt_init(double F) { | ||||
@@ -63,56 +63,25 @@ int apt_init(double F) { | |||||
return 0; | return 0; | ||||
} | } | ||||
/* Fast phase estimator | |||||
* Calculates the phase angle of a signal from a IQ sample | |||||
*/ | |||||
static inline double Phase(double I, double Q) { | |||||
double angle, r; | |||||
int s; | |||||
if(I == 0.0 && Q == 0.0) return 0.0; | |||||
if (Q < 0) { | |||||
s = -1; | |||||
Q = -Q; | |||||
} else { | |||||
s = 1; | |||||
} | |||||
if (I >= 0) { | |||||
r = (I - Q) / (I + Q); | |||||
angle = 0.25 - 0.25 * r; | |||||
} else { | |||||
r = (I + Q) / (Q - I); | |||||
angle = 0.75 - 0.25 * r; | |||||
} | |||||
if(s > 0){ | |||||
return angle; | |||||
}else{ | |||||
return -angle; | |||||
} | |||||
} | |||||
/* Phase locked loop | /* Phase locked loop | ||||
* https://arachnoid.com/phase_locked_loop/ | * https://arachnoid.com/phase_locked_loop/ | ||||
* Model of this filter here https://www.desmos.com/calculator/m0uadgkoee | * Model of this filter here https://www.desmos.com/calculator/m0uadgkoee | ||||
*/ | */ | ||||
static double pll(double I, double Q) { | |||||
static float pll(float I2, float Q) { | |||||
// PLL coefficient | // PLL coefficient | ||||
static double PhaseOsc = 0.0; | |||||
double Io, Qo; | |||||
double Ip, Qp; | |||||
double DPhi; | |||||
static float PhaseOsc = 0.0; | |||||
float Io, Qo; | |||||
float Ip, Qp; | |||||
float DPhi; | |||||
// Quadrature oscillator / reference | // Quadrature oscillator / reference | ||||
Io = cos(PhaseOsc); | Io = cos(PhaseOsc); | ||||
Qo = sin(PhaseOsc); | Qo = sin(PhaseOsc); | ||||
// Phase detector | // Phase detector | ||||
Ip = I * Io + Q * Qo; | |||||
Qp = Q * Io - I * Qo; | |||||
DPhi = Phase(Ip, Qp); | |||||
Ip = I2 * Io + Q * Qo; | |||||
Qp = Q * Io - I2 * Qo; | |||||
DPhi = atan2f(Qp, Ip); | |||||
// Loop filter | // Loop filter | ||||
PhaseOsc += 2.0 * M_PI * (K1 * DPhi + FreqOsc); | PhaseOsc += 2.0 * M_PI * (K1 * DPhi + FreqOsc); | ||||
@@ -131,16 +100,16 @@ static double pll(double I, double Q) { | |||||
} | } | ||||
// Convert samples into pixels | // Convert samples into pixels | ||||
static int getamp(double *ampbuff, int count, apt_getsamples_t getsamples, void *context) { | |||||
static int getamp(float *ampbuff, int count, apt_getsamples_t getsamples, void *context) { | |||||
static float inbuff[BLKIN]; | static float inbuff[BLKIN]; | ||||
static int idxin = 0; | static int idxin = 0; | ||||
static int nin = 0; | static int nin = 0; | ||||
for (int n = 0; n < count; n++) { | for (int n = 0; n < count; n++) { | ||||
double I, Q; | |||||
float I2, Q; | |||||
// Get some more samples when needed | // Get some more samples when needed | ||||
if (nin < IQFilterLen * 2 + 2) { | |||||
if (nin < HILBERT_FILTER_SIZE * 2 + 2) { | |||||
// Number of samples read | // Number of samples read | ||||
int res; | int res; | ||||
memmove(inbuff, &(inbuff[idxin]), nin * sizeof(float)); | memmove(inbuff, &(inbuff[idxin]), nin * sizeof(float)); | ||||
@@ -151,13 +120,15 @@ static int getamp(double *ampbuff, int count, apt_getsamples_t getsamples, void | |||||
nin += res; | nin += res; | ||||
// Make sure there is enough samples to continue | // Make sure there is enough samples to continue | ||||
if (nin < IQFilterLen * 2 + 2) | |||||
if (nin < HILBERT_FILTER_SIZE * 2 + 2) | |||||
return n; | return n; | ||||
} | } | ||||
// Process read samples into a brightness value | // Process read samples into a brightness value | ||||
iqfir(&inbuff[idxin], iqfilter, IQFilterLen, &I, &Q); | |||||
ampbuff[n] = pll(I, Q); | |||||
float complex tmp = hilbert_transform(&inbuff[idxin], hilbert_filter, HILBERT_FILTER_SIZE); | |||||
I2 = crealf(tmp); | |||||
Q = cimagf(tmp); | |||||
ampbuff[n] = pll(I2, Q); | |||||
// Increment current sample | // Increment current sample | ||||
idxin++; | idxin++; | ||||
@@ -167,25 +138,25 @@ static int getamp(double *ampbuff, int count, apt_getsamples_t getsamples, void | |||||
return count; | return count; | ||||
} | } | ||||
// Sub-pixel offsetting + FIR compensation | |||||
// Sub-pixel offsetting | |||||
int getpixelv(float *pvbuff, int count, apt_getsamples_t getsamples, void *context) { | int getpixelv(float *pvbuff, int count, apt_getsamples_t getsamples, void *context) { | ||||
// Amplitude buffer | // Amplitude buffer | ||||
static double ampbuff[BLKAMP]; | |||||
static float ampbuff[BLKAMP]; | |||||
static int nam = 0; | static int nam = 0; | ||||
static int idxam = 0; | static int idxam = 0; | ||||
double mult; | |||||
float mult; | |||||
// Gaussian resampling factor | // Gaussian resampling factor | ||||
mult = (double) Fi / Fe * FreqLine; | |||||
int m = (int)(RSFilterLen / mult + 1); | |||||
mult = (float) Fi / Fe * FreqLine; | |||||
int m = (int)(LOW_PASS_SIZE / mult + 1); | |||||
for (int n = 0; n < count; n++) { | for (int n = 0; n < count; n++) { | ||||
int shift; | int shift; | ||||
if (nam < m) { | if (nam < m) { | ||||
int res; | int res; | ||||
memmove(ampbuff, &(ampbuff[idxam]), nam * sizeof(double)); | |||||
memmove(ampbuff, &(ampbuff[idxam]), nam * sizeof(float)); | |||||
idxam = 0; | idxam = 0; | ||||
res = getamp(&(ampbuff[nam]), BLKAMP - nam, getsamples, context); | res = getamp(&(ampbuff[nam]), BLKAMP - nam, getsamples, context); | ||||
nam += res; | nam += res; | ||||
@@ -193,8 +164,7 @@ int getpixelv(float *pvbuff, int count, apt_getsamples_t getsamples, void *conte | |||||
return n; | return n; | ||||
} | } | ||||
// Gaussian FIR compensation filter | |||||
pvbuff[n] = (float)(rsfir(&(ampbuff[idxam]), rsfilter, RSFilterLen, offset, mult) * mult * 256.0); | |||||
pvbuff[n] = interpolating_convolve(&(ampbuff[idxam]), low_pass, LOW_PASS_SIZE, offset, mult) * mult * 256.0; | |||||
shift = ((int) floor((RSMULT - offset) / mult)) + 1; | shift = ((int) floor((RSMULT - offset) / mult)) + 1; | ||||
offset = shift * mult + offset - RSMULT; | offset = shift * mult + offset - RSMULT; | ||||
@@ -208,15 +178,15 @@ int getpixelv(float *pvbuff, int count, apt_getsamples_t getsamples, void *conte | |||||
// Get an entire row of pixels, aligned with sync markers | // Get an entire row of pixels, aligned with sync markers | ||||
int apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamples_t getsamples, void *context) { | int apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamples_t getsamples, void *context) { | ||||
static float pixels[PixelLine + SyncFilterLen]; | |||||
static int npv; | |||||
static float pixels[PixelLine + SYNC_PATTERN_SIZE]; | |||||
static size_t npv; | |||||
static int synced = 0; | static int synced = 0; | ||||
static double max = 0.0; | |||||
static double minDoppler = 1000000000, previous = 0; | |||||
static float max = 0.0; | |||||
static float minDoppler = 1000000000, previous = 0; | |||||
if(reset) synced = 0; | if(reset) synced = 0; | ||||
double corr, ecorr, lcorr; | |||||
float corr, ecorr, lcorr; | |||||
int res; | int res; | ||||
// Move the row buffer into the the image buffer | // Move the row buffer into the the image buffer | ||||
@@ -224,20 +194,20 @@ int apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamp | |||||
memmove(pixelv, pixels, npv * sizeof(float)); | memmove(pixelv, pixels, npv * sizeof(float)); | ||||
// Get the sync line | // Get the sync line | ||||
if (npv < SyncFilterLen + 2) { | |||||
res = getpixelv(&(pixelv[npv]), SyncFilterLen + 2 - npv, getsamples, context); | |||||
if (npv < SYNC_PATTERN_SIZE + 2) { | |||||
res = getpixelv(&(pixelv[npv]), SYNC_PATTERN_SIZE + 2 - npv, getsamples, context); | |||||
npv += res; | npv += res; | ||||
if (npv < SyncFilterLen + 2) | |||||
if (npv < SYNC_PATTERN_SIZE + 2) | |||||
return 0; | return 0; | ||||
} | } | ||||
// Calculate the frequency offset | // Calculate the frequency offset | ||||
ecorr = fir(pixelv, Sync, SyncFilterLen); | |||||
corr = fir(&pixelv[1], Sync, SyncFilterLen - 1); | |||||
lcorr = fir(&pixelv[2], Sync, SyncFilterLen - 2); | |||||
ecorr = convolve(pixelv, sync_pattern, SYNC_PATTERN_SIZE); | |||||
corr = convolve(&pixelv[1], sync_pattern, SYNC_PATTERN_SIZE - 1); | |||||
lcorr = convolve(&pixelv[2], sync_pattern, SYNC_PATTERN_SIZE - 2); | |||||
FreqLine = 1.0+((ecorr-lcorr) / corr / PixelLine / 4.0); | FreqLine = 1.0+((ecorr-lcorr) / corr / PixelLine / 4.0); | ||||
double val = fabs(lcorr - ecorr)*0.25 + previous*0.75; | |||||
float val = fabs(lcorr - ecorr)*0.25 + previous*0.75; | |||||
if(val < minDoppler && nrow > 10){ | if(val < minDoppler && nrow > 10){ | ||||
minDoppler = val; | minDoppler = val; | ||||
*zenith = nrow; | *zenith = nrow; | ||||
@@ -255,19 +225,19 @@ int apt_getpixelrow(float *pixelv, int nrow, int *zenith, int reset, apt_getsamp | |||||
int mshift; | int mshift; | ||||
static int lastmshift; | static int lastmshift; | ||||
if (npv < PixelLine + SyncFilterLen) { | |||||
res = getpixelv(&(pixelv[npv]), PixelLine + SyncFilterLen - npv, getsamples, context); | |||||
if (npv < PixelLine + SYNC_PATTERN_SIZE) { | |||||
res = getpixelv(&(pixelv[npv]), PixelLine + SYNC_PATTERN_SIZE - npv, getsamples, context); | |||||
npv += res; | npv += res; | ||||
if (npv < PixelLine + SyncFilterLen) | |||||
if (npv < PixelLine + SYNC_PATTERN_SIZE) | |||||
return 0; | return 0; | ||||
} | } | ||||
// Test every possible position until we get the best result | // Test every possible position until we get the best result | ||||
mshift = 0; | mshift = 0; | ||||
for (int shift = 0; shift < PixelLine; shift++) { | for (int shift = 0; shift < PixelLine; shift++) { | ||||
double corr; | |||||
float corr; | |||||
corr = fir(&(pixelv[shift + 1]), Sync, SyncFilterLen); | |||||
corr = convolve(&(pixelv[shift + 1]), sync_pattern, SYNC_PATTERN_SIZE); | |||||
if (corr > max) { | if (corr > max) { | ||||
mshift = shift; | mshift = shift; | ||||
max = corr; | max = corr; | ||||
@@ -1,65 +1,56 @@ | |||||
/* | |||||
* This file is part of Aptdec. | |||||
* Copyright (c) 2004-2009 Thierry Leconte (F4DWV), Xerbo (xerbo@protonmail.com) 2019-2022 | |||||
/* | |||||
* aptdec - A lightweight FOSS (NOAA) APT decoder | |||||
* Copyright (C) 2004-2009 Thierry Leconte (F4DWV) 2019-2022 Xerbo (xerbo@protonmail.com) | |||||
* | * | ||||
* Aptdec is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | * | ||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | * | ||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
*/ | */ | ||||
#include <math.h> | #include <math.h> | ||||
#include "filter.h" | |||||
#include "util.h" | |||||
// Finite impulse response | |||||
float fir(float *buff, const float *coeff, const int len) { | |||||
double r; | |||||
r = 0.0; | |||||
for (int i = 0; i < len; i++) { | |||||
r += buff[i] * coeff[i]; | |||||
float convolve(const float *in, const float *taps, size_t len) { | |||||
float sum = 0.0; | |||||
for (size_t i = 0; i < len; i++) { | |||||
sum += in[i] * taps[i]; | |||||
} | } | ||||
return (float)r; | |||||
return sum; | |||||
} | } | ||||
/* IQ finite impulse response | |||||
* Turn samples into a single IQ sample | |||||
*/ | |||||
void iqfir(float *buff, const float *coeff, const int len, double *I, double *Q) { | |||||
double i = 0.0, q = 0.0; | |||||
float complex hilbert_transform(const float *in, const float *taps, size_t len) { | |||||
float i = 0.0; | |||||
float q = 0.0; | |||||
for (int k = 0; k < len; k++) { | |||||
q += buff[2*k] * coeff[k]; | |||||
i += buff[2*k]; | |||||
for (size_t k = 0; k < len; k++) { | |||||
q += in[2*k] * taps[k]; | |||||
i += in[2*k]; | |||||
} | } | ||||
i = buff[len-1] - (i / len); | |||||
*I = i, *Q = q; | |||||
i = in[len-1] - (i / len); | |||||
return i + q*I; | |||||
} | } | ||||
/* Gaussian finite impulse responce compensation | |||||
* https://www.recordingblogs.com/wiki/gaussian-window | |||||
*/ | |||||
float rsfir(double *buff, const float *coeff, const int len, const double offset, const double delta) { | |||||
double out; | |||||
float interpolating_convolve(const float *in, const float *taps, size_t len, float offset, float delta) { | |||||
float out = 0.0; | |||||
float n = offset; | |||||
out = 0.0; | |||||
double n = offset; | |||||
for (int i = 0; i < (len-1)/delta-1; n += delta, i++) { | |||||
int k; | |||||
double alpha; | |||||
for (size_t i = 0; i < (len-1)/delta-1; n += delta, i++) { | |||||
int k = (int)floor(n); | |||||
float alpha = n - k; | |||||
k = (int)floor(n); | |||||
alpha = n - k; | |||||
out += buff[i] * (coeff[k] * (1.0 - alpha) + coeff[k + 1] * alpha); | |||||
out += in[i] * (taps[k] * (1.0f-alpha) + taps[k + 1] * alpha); | |||||
} | } | ||||
return (float)out; | |||||
return out; | |||||
} | } |
@@ -1,100 +1,24 @@ | |||||
/* | |||||
* This file is part of Aptdec. | |||||
* Copyright (c) 2004-2009 Thierry Leconte (F4DWV), Xerbo (xerbo@protonmail.com) 2019-2022 | |||||
/* | |||||
* aptdec - A lightweight FOSS (NOAA) APT decoder | |||||
* Copyright (C) 2019-2022 Xerbo (xerbo@protonmail.com) | |||||
* | * | ||||
* Aptdec is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | * | ||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | * | ||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
*/ | */ | ||||
float fir(float *buff, const float *coeff, const int len); | |||||
void iqfir(float *buff, const float *coeff, const int len, double *I, double *Q); | |||||
float rsfir(double *buff, const float *coeff, const int len, const double offset, const double delta); | |||||
// IQ finite impulse response filter | |||||
#define IQFilterLen 32 | |||||
const float iqfilter[IQFilterLen] = { 0.0205361, 0.0219524, 0.0235785, 0.0254648, 0.0276791, 0.0303152, | |||||
0.0335063, 0.0374482, 0.0424413, 0.0489708, 0.0578745, 0.0707355, 0.0909457, 0.127324, 0.212207, 0.63662, | |||||
-0.63662, -0.212207, -0.127324, -0.0909457, -0.0707355, -0.0578745, -0.0489708, -0.0424413, -0.0374482, | |||||
-0.0335063, -0.0303152, -0.0276791, -0.0254648, -0.0235785, -0.0219524, -0.0205361 }; | |||||
// Pattern of a NOAA sync line | |||||
#define SyncFilterLen 32 | |||||
const float Sync[SyncFilterLen] = { -14, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, | |||||
18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, -14 }; | |||||
#include <stddef.h> | |||||
#include <complex.h> | |||||
// Gaussian finite impulse response compensation filter | |||||
#define RSFilterLen 437 | |||||
const float rsfilter[RSFilterLen] = { -3.37279e-04, -8.80292e-06, -3.96418e-04, -1.78544e-04, -5.27511e-04, | |||||
-3.75376e-04, -6.95337e-04, -5.93148e-04, -8.79730e-04, -8.15327e-04, -1.05669e-03, -1.01377e-03, | |||||
-1.19836e-03, -1.15443e-03, -1.26937e-03, -1.20955e-03, -1.23904e-03, -1.15302e-03, -1.08660e-03, | |||||
-9.64235e-04, -8.02450e-04, -6.46202e-04, -3.95376e-04, -2.18096e-04, 1.11906e-04, 2.89567e-04, | |||||
6.67167e-04, 8.19039e-04, 1.21725e-03, 1.30556e-03, 1.69365e-03, 1.68588e-03, 2.03277e-03, 1.90159e-03, | |||||
2.18455e-03, 1.90833e-03, 2.12100e-03, 1.69052e-03, 1.77484e-03, 1.42542e-03, 1.18292e-03, 8.66979e-04, | |||||
5.54161e-04, 2.15793e-04, -1.11623e-04, -4.35173e-04, -7.27194e-04, -9.91551e-04, -1.20407e-03, | |||||
-1.37032e-03, -1.46991e-03, -1.51120e-03, -1.48008e-03, -1.39047e-03, -1.23115e-03, -1.02128e-03, | |||||
-7.60099e-04, -4.68008e-04, -1.46339e-04, 1.80867e-04, 5.11244e-04, 8.19243e-04, 1.09739e-03, 1.32668e-03, | |||||
1.50632e-03, 1.61522e-03, 1.66246e-03, 1.62390e-03, 1.52430e-03, 1.34273e-03, 1.10736e-03, 8.10335e-04, | |||||
4.76814e-04, 1.13622e-04, -2.64150e-04, -6.26595e-04, -9.95436e-04, -1.27846e-03, -1.54080e-03, | |||||
-1.74292e-03, -1.86141e-03, -1.89318e-03, -1.83969e-03, -1.69770e-03, -1.47938e-03, -1.18696e-03, | |||||
-8.37003e-04, -4.39507e-04, -1.56907e-05, 4.19904e-04, 8.43172e-04, 1.23827e-03, 1.58411e-03, | |||||
1.86382e-03, 2.06312e-03, 2.17177e-03, 2.18121e-03, 2.08906e-03, 1.89772e-03, 1.61153e-03, | |||||
1.24507e-03, 8.13976e-04, 3.29944e-04, -1.74591e-04, -6.83619e-04, -1.17826e-03, -1.61659e-03, | |||||
-2.00403e-03, -2.29070e-03, -2.49179e-03, -2.56546e-03, -2.53448e-03, -2.37032e-03, -2.10060e-03, | |||||
-1.72140e-03, -1.24542e-03, -7.15425e-04, -1.24964e-04, 4.83736e-04, 1.08328e-03, 1.64530e-03, | |||||
2.14503e-03, 2.55400e-03, 2.85589e-03, 3.02785e-03, 3.06271e-03, 2.95067e-03, 2.69770e-03, | |||||
2.30599e-03, 1.79763e-03, 1.18587e-03, 5.04003e-04, -2.23591e-04, -9.57591e-04, -1.66939e-03, | |||||
-2.31717e-03, -2.87636e-03, -3.31209e-03, -3.60506e-03, -3.73609e-03, -3.69208e-03, -3.44913e-03, | |||||
-3.06572e-03, -2.50229e-03, -1.80630e-03, -1.00532e-03, -1.22305e-04, 7.83910e-04, 1.69402e-03, | |||||
2.53826e-03, 3.30312e-03, 3.91841e-03, 4.38017e-03, 4.63546e-03, 4.68091e-03, 4.50037e-03, | |||||
4.09614e-03, 3.47811e-03, 2.67306e-03, 1.70418e-03, 6.20542e-04, -5.36994e-04, -1.70981e-03, | |||||
-2.84712e-03, -3.88827e-03, -4.78659e-03, -5.48593e-03, -5.95049e-03, -6.14483e-03, -6.05118e-03, | |||||
-5.65829e-03, -4.97525e-03, -4.01796e-03, -2.82224e-03, -1.43003e-03, 1.00410e-04, 1.71169e-03, | |||||
3.31983e-03, 4.87796e-03, 6.23237e-03, 7.31013e-03, 8.20642e-03, 8.67374e-03, 8.77681e-03, | |||||
8.43444e-03, 7.66794e-03, 6.46827e-03, 4.87294e-03, 2.92923e-03, 6.98913e-04, -1.72126e-03, | |||||
-4.24785e-03, -6.75380e-03, -9.13309e-03, -1.12532e-02, -1.30038e-02, -1.42633e-02, -1.49338e-02, | |||||
-1.49145e-02, -1.41484e-02, -1.25761e-02, -1.01870e-02, -6.97432e-03, -2.97910e-03, 1.75386e-03, | |||||
7.11899e-03, 1.30225e-02, 1.93173e-02, 2.58685e-02, 3.24965e-02, 3.90469e-02, 4.53316e-02, | |||||
5.11931e-02, 5.64604e-02, 6.09924e-02, 6.46584e-02, 6.73547e-02, 6.90049e-02, 6.97096e-02, | |||||
6.90049e-02, 6.73547e-02, 6.46584e-02, 6.09924e-02, 5.64604e-02, 5.11931e-02, 4.53316e-02, | |||||
3.90469e-02, 3.24965e-02, 2.58685e-02, 1.93173e-02, 1.30225e-02, 7.11899e-03, 1.75386e-03, | |||||
-2.97910e-03, -6.97432e-03, -1.01870e-02, -1.25761e-02, -1.41484e-02, -1.49145e-02, -1.49338e-02, | |||||
-1.42633e-02, -1.30038e-02, -1.12532e-02, -9.13309e-03, -6.75380e-03, -4.24785e-03, -1.72126e-03, | |||||
6.98913e-04, 2.92923e-03, 4.87294e-03, 6.46827e-03, 7.66794e-03, 8.43444e-03, 8.77681e-03, | |||||
8.67374e-03, 8.20642e-03, 7.31013e-03, 6.23237e-03, 4.87796e-03, 3.31983e-03, 1.71169e-03, | |||||
1.00410e-04, -1.43003e-03, -2.82224e-03, -4.01796e-03, -4.97525e-03, -5.65829e-03, -6.05118e-03, | |||||
-6.14483e-03, -5.95049e-03, -5.48593e-03, -4.78659e-03, -3.88827e-03, -2.84712e-03, -1.70981e-03, | |||||
-5.36994e-04, 6.20542e-04, 1.70418e-03, 2.67306e-03, 3.47811e-03, 4.09614e-03, 4.50037e-03, | |||||
4.68091e-03, 4.63546e-03, 4.38017e-03, 3.91841e-03, 3.30312e-03, 2.53826e-03, 1.69402e-03, | |||||
7.83910e-04, -1.22305e-04, -1.00532e-03, -1.80630e-03, -2.50229e-03, -3.06572e-03, -3.44913e-03, | |||||
-3.69208e-03, -3.73609e-03, -3.60506e-03, -3.31209e-03, -2.87636e-03, -2.31717e-03, -1.66939e-03, | |||||
-9.57591e-04, -2.23591e-04, 5.04003e-04, 1.18587e-03, 1.79763e-03, 2.30599e-03, 2.69770e-03, | |||||
2.95067e-03, 3.06271e-03, 3.02785e-03, 2.85589e-03, 2.55400e-03, 2.14503e-03, 1.64530e-03, | |||||
1.08328e-03, 4.83736e-04, -1.24964e-04, -7.15425e-04, -1.24542e-03, -1.72140e-03, -2.10060e-03, | |||||
-2.37032e-03, -2.53448e-03, -2.56546e-03, -2.49179e-03, -2.29070e-03, -2.00403e-03, -1.61659e-03, | |||||
-1.17826e-03, -6.83619e-04, -1.74591e-04, 3.29944e-04, 8.13976e-04, 1.24507e-03, 1.61153e-03, | |||||
1.89772e-03, 2.08906e-03, 2.18121e-03, 2.17177e-03, 2.06312e-03, 1.86382e-03, 1.58411e-03, | |||||
1.23827e-03, 8.43172e-04, 4.19904e-04, -1.56907e-05, -4.39507e-04, -8.37003e-04, -1.18696e-03, | |||||
-1.47938e-03, -1.69770e-03, -1.83969e-03, -1.89318e-03, -1.86141e-03, -1.74292e-03, -1.54080e-03, | |||||
-1.27846e-03, -9.95436e-04, -6.26595e-04, -2.64150e-04, 1.13622e-04, 4.76814e-04, 8.10335e-04, | |||||
1.10736e-03, 1.34273e-03, 1.52430e-03, 1.62390e-03, 1.66246e-03, 1.61522e-03, 1.50632e-03, | |||||
1.32668e-03, 1.09739e-03, 8.19243e-04, 5.11244e-04, 1.80867e-04, -1.46339e-04, -4.68008e-04, | |||||
-7.60099e-04, -1.02128e-03, -1.23115e-03, -1.39047e-03, -1.48008e-03, -1.51120e-03, -1.46991e-03, | |||||
-1.37032e-03, -1.20407e-03, -9.91551e-04, -7.27194e-04, -4.35173e-04, -1.11623e-04, 2.15793e-04, | |||||
5.54161e-04, 8.66979e-04, 1.18292e-03, 1.42542e-03, 1.77484e-03, 1.69052e-03, 2.12100e-03, | |||||
1.90833e-03, 2.18455e-03, 1.90159e-03, 2.03277e-03, 1.68588e-03, 1.69365e-03, 1.30556e-03, | |||||
1.21725e-03, 8.19039e-04, 6.67167e-04, 2.89567e-04, 1.11906e-04, -2.18096e-04, -3.95376e-04, | |||||
-6.46202e-04, -8.02450e-04, -9.64235e-04, -1.08660e-03, -1.15302e-03, -1.23904e-03, -1.20955e-03, | |||||
-1.26937e-03, -1.15443e-03, -1.19836e-03, -1.01377e-03, -1.05669e-03, -8.15327e-04, -8.79730e-04, | |||||
-5.93148e-04, -6.95337e-04, -3.75376e-04, -5.27511e-04, -1.78544e-04, -3.96418e-04, -8.80292e-06, | |||||
-3.37279e-04 }; | |||||
float convolve(const float *in, const float *taps, size_t len); | |||||
float complex 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, float delta); |
@@ -33,8 +33,8 @@ static linear_t compute_regression(float *wedges) { | |||||
return linear_regression(wedges, teleramp, 9); | return linear_regression(wedges, teleramp, 9); | ||||
} | } | ||||
static double tele[16]; | |||||
static double Cs; | |||||
static float tele[16]; | |||||
static float Cs; | |||||
void apt_histogramEqualise(float **prow, int nrow, int offset, int width){ | void apt_histogramEqualise(float **prow, int nrow, int offset, int width){ | ||||
// Plot histogram | // Plot histogram | ||||
@@ -97,9 +97,9 @@ void calibrateImage(float **prow, int nrow, int offset, int width, linear_t regr | |||||
} | } | ||||
} | } | ||||
double teleNoise(float *wedges){ | |||||
double pattern[9] = { 31.07, 63.02, 94.96, 126.9, 158.86, 191.1, 228.62, 255.0, 0.0 }; | |||||
double noise = 0; | |||||
float teleNoise(float *wedges){ | |||||
float pattern[9] = { 31.07, 63.02, 94.96, 126.9, 158.86, 191.1, 228.62, 255.0, 0.0 }; | |||||
float noise = 0; | |||||
for(int i = 0; i < 9; i++) | for(int i = 0; i < 9; i++) | ||||
noise += fabs(wedges[i] - pattern[i]); | noise += fabs(wedges[i] - pattern[i]); | ||||
@@ -108,7 +108,7 @@ double teleNoise(float *wedges){ | |||||
// Get telemetry data for thermal calibration | // Get telemetry data for thermal calibration | ||||
apt_channel_t apt_calibrate(float **prow, int nrow, int offset, int width) { | apt_channel_t apt_calibrate(float **prow, int nrow, int offset, int width) { | ||||
double teleline[APT_MAX_HEIGHT] = { 0.0 }; | |||||
float teleline[APT_MAX_HEIGHT] = { 0.0 }; | |||||
float wedge[16]; | float wedge[16]; | ||||
linear_t regr[APT_MAX_HEIGHT/APT_FRAME_LEN + 1]; | linear_t regr[APT_MAX_HEIGHT/APT_FRAME_LEN + 1]; | ||||
int telestart, mtelestart = 0; | int telestart, mtelestart = 0; | ||||
@@ -156,7 +156,7 @@ apt_channel_t apt_calibrate(float **prow, int nrow, int offset, int width) { | |||||
} | } | ||||
// Find the least noisy frame | // Find the least noisy frame | ||||
double minNoise = -1; | |||||
float minNoise = -1; | |||||
int bestFrame = -1; | int bestFrame = -1; | ||||
for (int n = telestart, k = 0; n < nrow - APT_FRAME_LEN; n += APT_FRAME_LEN, k++) { | for (int n = telestart, k = 0; n < nrow - APT_FRAME_LEN; n += APT_FRAME_LEN, k++) { | ||||
int j; | int j; | ||||
@@ -170,7 +170,7 @@ apt_channel_t apt_calibrate(float **prow, int nrow, int offset, int width) { | |||||
wedge[j] /= 6; | wedge[j] /= 6; | ||||
} | } | ||||
double noise = teleNoise(wedge); | |||||
float noise = teleNoise(wedge); | |||||
if(noise < minNoise || minNoise == -1){ | if(noise < minNoise || minNoise == -1){ | ||||
minNoise = noise; | minNoise = noise; | ||||
bestFrame = k; | bestFrame = k; | ||||
@@ -313,16 +313,16 @@ int apt_cropNoise(apt_image_t *img){ | |||||
#include "satcal.h" | #include "satcal.h" | ||||
typedef struct { | typedef struct { | ||||
double Nbb; | |||||
double Cs; | |||||
double Cb; | |||||
float Nbb; | |||||
float Cs; | |||||
float Cb; | |||||
int ch; | int ch; | ||||
} tempparam_t; | } tempparam_t; | ||||
// IR channel temperature compensation | // IR channel temperature compensation | ||||
static void tempcomp(double t[16], int ch, int satnum, tempparam_t *tpr) { | |||||
double Tbb, T[4]; | |||||
double C; | |||||
static void tempcomp(float t[16], int ch, int satnum, tempparam_t *tpr) { | |||||
float Tbb, T[4]; | |||||
float C; | |||||
tpr->ch = ch - 4; | tpr->ch = ch - 4; | ||||
@@ -352,9 +352,9 @@ static void tempcomp(double t[16], int ch, int satnum, tempparam_t *tpr) { | |||||
} | } | ||||
// IR channel temperature calibration | // IR channel temperature calibration | ||||
static double tempcal(float Ce, int satnum, tempparam_t * rgpr) { | |||||
double Nl, Nc, Ns, Ne; | |||||
double T, vc; | |||||
static float tempcal(float Ce, int satnum, tempparam_t * rgpr) { | |||||
float Nl, Nc, Ns, Ne; | |||||
float T, vc; | |||||
Ns = satcal[satnum].cor[rgpr->ch].Ns; | Ns = satcal[satnum].cor[rgpr->ch].Ns; | ||||
Nl = Ns + (rgpr->Nbb - Ns) * (rgpr->Cs - Ce * 4.0) / (rgpr->Cs - rgpr->Cb); | Nl = Ns + (rgpr->Nbb - Ns) * (rgpr->Cs - Ce * 4.0) / (rgpr->Cs - rgpr->Cb); | ||||
@@ -0,0 +1,92 @@ | |||||
/* | |||||
* aptdec - A lightweight FOSS (NOAA) APT decoder | |||||
* Copyright (C) 2004-2009 Thierry Leconte (F4DWV) 2019-2022 Xerbo (xerbo@protonmail.com) | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
*/ | |||||
static const float hilbert_filter[] = { 0.0205361, 0.0219524, 0.0235785, 0.0254648, 0.0276791, 0.0303152, | |||||
0.0335063, 0.0374482, 0.0424413, 0.0489708, 0.0578745, 0.0707355, 0.0909457, 0.127324, 0.212207, 0.63662, | |||||
-0.63662, -0.212207, -0.127324, -0.0909457, -0.0707355, -0.0578745, -0.0489708, -0.0424413, -0.0374482, | |||||
-0.0335063, -0.0303152, -0.0276791, -0.0254648, -0.0235785, -0.0219524, -0.0205361 }; | |||||
#define HILBERT_FILTER_SIZE (sizeof(hilbert_filter)/sizeof(hilbert_filter[0])) | |||||
static const float low_pass[] = { -3.37279e-04, -8.80292e-06, -3.96418e-04, -1.78544e-04, -5.27511e-04, | |||||
-3.75376e-04, -6.95337e-04, -5.93148e-04, -8.79730e-04, -8.15327e-04, -1.05669e-03, -1.01377e-03, | |||||
-1.19836e-03, -1.15443e-03, -1.26937e-03, -1.20955e-03, -1.23904e-03, -1.15302e-03, -1.08660e-03, | |||||
-9.64235e-04, -8.02450e-04, -6.46202e-04, -3.95376e-04, -2.18096e-04, 1.11906e-04, 2.89567e-04, | |||||
6.67167e-04, 8.19039e-04, 1.21725e-03, 1.30556e-03, 1.69365e-03, 1.68588e-03, 2.03277e-03, 1.90159e-03, | |||||
2.18455e-03, 1.90833e-03, 2.12100e-03, 1.69052e-03, 1.77484e-03, 1.42542e-03, 1.18292e-03, 8.66979e-04, | |||||
5.54161e-04, 2.15793e-04, -1.11623e-04, -4.35173e-04, -7.27194e-04, -9.91551e-04, -1.20407e-03, | |||||
-1.37032e-03, -1.46991e-03, -1.51120e-03, -1.48008e-03, -1.39047e-03, -1.23115e-03, -1.02128e-03, | |||||
-7.60099e-04, -4.68008e-04, -1.46339e-04, 1.80867e-04, 5.11244e-04, 8.19243e-04, 1.09739e-03, 1.32668e-03, | |||||
1.50632e-03, 1.61522e-03, 1.66246e-03, 1.62390e-03, 1.52430e-03, 1.34273e-03, 1.10736e-03, 8.10335e-04, | |||||
4.76814e-04, 1.13622e-04, -2.64150e-04, -6.26595e-04, -9.95436e-04, -1.27846e-03, -1.54080e-03, | |||||
-1.74292e-03, -1.86141e-03, -1.89318e-03, -1.83969e-03, -1.69770e-03, -1.47938e-03, -1.18696e-03, | |||||
-8.37003e-04, -4.39507e-04, -1.56907e-05, 4.19904e-04, 8.43172e-04, 1.23827e-03, 1.58411e-03, | |||||
1.86382e-03, 2.06312e-03, 2.17177e-03, 2.18121e-03, 2.08906e-03, 1.89772e-03, 1.61153e-03, | |||||
1.24507e-03, 8.13976e-04, 3.29944e-04, -1.74591e-04, -6.83619e-04, -1.17826e-03, -1.61659e-03, | |||||
-2.00403e-03, -2.29070e-03, -2.49179e-03, -2.56546e-03, -2.53448e-03, -2.37032e-03, -2.10060e-03, | |||||
-1.72140e-03, -1.24542e-03, -7.15425e-04, -1.24964e-04, 4.83736e-04, 1.08328e-03, 1.64530e-03, | |||||
2.14503e-03, 2.55400e-03, 2.85589e-03, 3.02785e-03, 3.06271e-03, 2.95067e-03, 2.69770e-03, | |||||
2.30599e-03, 1.79763e-03, 1.18587e-03, 5.04003e-04, -2.23591e-04, -9.57591e-04, -1.66939e-03, | |||||
-2.31717e-03, -2.87636e-03, -3.31209e-03, -3.60506e-03, -3.73609e-03, -3.69208e-03, -3.44913e-03, | |||||
-3.06572e-03, -2.50229e-03, -1.80630e-03, -1.00532e-03, -1.22305e-04, 7.83910e-04, 1.69402e-03, | |||||
2.53826e-03, 3.30312e-03, 3.91841e-03, 4.38017e-03, 4.63546e-03, 4.68091e-03, 4.50037e-03, | |||||
4.09614e-03, 3.47811e-03, 2.67306e-03, 1.70418e-03, 6.20542e-04, -5.36994e-04, -1.70981e-03, | |||||
-2.84712e-03, -3.88827e-03, -4.78659e-03, -5.48593e-03, -5.95049e-03, -6.14483e-03, -6.05118e-03, | |||||
-5.65829e-03, -4.97525e-03, -4.01796e-03, -2.82224e-03, -1.43003e-03, 1.00410e-04, 1.71169e-03, | |||||
3.31983e-03, 4.87796e-03, 6.23237e-03, 7.31013e-03, 8.20642e-03, 8.67374e-03, 8.77681e-03, | |||||
8.43444e-03, 7.66794e-03, 6.46827e-03, 4.87294e-03, 2.92923e-03, 6.98913e-04, -1.72126e-03, | |||||
-4.24785e-03, -6.75380e-03, -9.13309e-03, -1.12532e-02, -1.30038e-02, -1.42633e-02, -1.49338e-02, | |||||
-1.49145e-02, -1.41484e-02, -1.25761e-02, -1.01870e-02, -6.97432e-03, -2.97910e-03, 1.75386e-03, | |||||
7.11899e-03, 1.30225e-02, 1.93173e-02, 2.58685e-02, 3.24965e-02, 3.90469e-02, 4.53316e-02, | |||||
5.11931e-02, 5.64604e-02, 6.09924e-02, 6.46584e-02, 6.73547e-02, 6.90049e-02, 6.97096e-02, | |||||
6.90049e-02, 6.73547e-02, 6.46584e-02, 6.09924e-02, 5.64604e-02, 5.11931e-02, 4.53316e-02, | |||||
3.90469e-02, 3.24965e-02, 2.58685e-02, 1.93173e-02, 1.30225e-02, 7.11899e-03, 1.75386e-03, | |||||
-2.97910e-03, -6.97432e-03, -1.01870e-02, -1.25761e-02, -1.41484e-02, -1.49145e-02, -1.49338e-02, | |||||
-1.42633e-02, -1.30038e-02, -1.12532e-02, -9.13309e-03, -6.75380e-03, -4.24785e-03, -1.72126e-03, | |||||
6.98913e-04, 2.92923e-03, 4.87294e-03, 6.46827e-03, 7.66794e-03, 8.43444e-03, 8.77681e-03, | |||||
8.67374e-03, 8.20642e-03, 7.31013e-03, 6.23237e-03, 4.87796e-03, 3.31983e-03, 1.71169e-03, | |||||
1.00410e-04, -1.43003e-03, -2.82224e-03, -4.01796e-03, -4.97525e-03, -5.65829e-03, -6.05118e-03, | |||||
-6.14483e-03, -5.95049e-03, -5.48593e-03, -4.78659e-03, -3.88827e-03, -2.84712e-03, -1.70981e-03, | |||||
-5.36994e-04, 6.20542e-04, 1.70418e-03, 2.67306e-03, 3.47811e-03, 4.09614e-03, 4.50037e-03, | |||||
4.68091e-03, 4.63546e-03, 4.38017e-03, 3.91841e-03, 3.30312e-03, 2.53826e-03, 1.69402e-03, | |||||
7.83910e-04, -1.22305e-04, -1.00532e-03, -1.80630e-03, -2.50229e-03, -3.06572e-03, -3.44913e-03, | |||||
-3.69208e-03, -3.73609e-03, -3.60506e-03, -3.31209e-03, -2.87636e-03, -2.31717e-03, -1.66939e-03, | |||||
-9.57591e-04, -2.23591e-04, 5.04003e-04, 1.18587e-03, 1.79763e-03, 2.30599e-03, 2.69770e-03, | |||||
2.95067e-03, 3.06271e-03, 3.02785e-03, 2.85589e-03, 2.55400e-03, 2.14503e-03, 1.64530e-03, | |||||
1.08328e-03, 4.83736e-04, -1.24964e-04, -7.15425e-04, -1.24542e-03, -1.72140e-03, -2.10060e-03, | |||||
-2.37032e-03, -2.53448e-03, -2.56546e-03, -2.49179e-03, -2.29070e-03, -2.00403e-03, -1.61659e-03, | |||||
-1.17826e-03, -6.83619e-04, -1.74591e-04, 3.29944e-04, 8.13976e-04, 1.24507e-03, 1.61153e-03, | |||||
1.89772e-03, 2.08906e-03, 2.18121e-03, 2.17177e-03, 2.06312e-03, 1.86382e-03, 1.58411e-03, | |||||
1.23827e-03, 8.43172e-04, 4.19904e-04, -1.56907e-05, -4.39507e-04, -8.37003e-04, -1.18696e-03, | |||||
-1.47938e-03, -1.69770e-03, -1.83969e-03, -1.89318e-03, -1.86141e-03, -1.74292e-03, -1.54080e-03, | |||||
-1.27846e-03, -9.95436e-04, -6.26595e-04, -2.64150e-04, 1.13622e-04, 4.76814e-04, 8.10335e-04, | |||||
1.10736e-03, 1.34273e-03, 1.52430e-03, 1.62390e-03, 1.66246e-03, 1.61522e-03, 1.50632e-03, | |||||
1.32668e-03, 1.09739e-03, 8.19243e-04, 5.11244e-04, 1.80867e-04, -1.46339e-04, -4.68008e-04, | |||||
-7.60099e-04, -1.02128e-03, -1.23115e-03, -1.39047e-03, -1.48008e-03, -1.51120e-03, -1.46991e-03, | |||||
-1.37032e-03, -1.20407e-03, -9.91551e-04, -7.27194e-04, -4.35173e-04, -1.11623e-04, 2.15793e-04, | |||||
5.54161e-04, 8.66979e-04, 1.18292e-03, 1.42542e-03, 1.77484e-03, 1.69052e-03, 2.12100e-03, | |||||
1.90833e-03, 2.18455e-03, 1.90159e-03, 2.03277e-03, 1.68588e-03, 1.69365e-03, 1.30556e-03, | |||||
1.21725e-03, 8.19039e-04, 6.67167e-04, 2.89567e-04, 1.11906e-04, -2.18096e-04, -3.95376e-04, | |||||
-6.46202e-04, -8.02450e-04, -9.64235e-04, -1.08660e-03, -1.15302e-03, -1.23904e-03, -1.20955e-03, | |||||
-1.26937e-03, -1.15443e-03, -1.19836e-03, -1.01377e-03, -1.05669e-03, -8.15327e-04, -8.79730e-04, | |||||
-5.93148e-04, -6.95337e-04, -3.75376e-04, -5.27511e-04, -1.78544e-04, -3.96418e-04, -8.80292e-06, | |||||
-3.37279e-04 }; | |||||
#define LOW_PASS_SIZE (sizeof(low_pass)/sizeof(low_pass[0])) | |||||
static const float sync_pattern[] = { -14, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, | |||||
18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, 18, 18, -14, -14, -14 }; | |||||
#define SYNC_PATTERN_SIZE (sizeof(sync_pattern)/sizeof(sync_pattern[0])) |
@@ -0,0 +1,20 @@ | |||||
/* | |||||
* aptdec - A lightweight FOSS (NOAA) APT decoder | |||||
* Copyright (C) 2019-2022 Xerbo (xerbo@protonmail.com) | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | |||||
*/ | |||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) | |||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) |