diff --git a/ft8CN/app/src/main/cpp/CMakeLists.txt b/ft8CN/app/src/main/cpp/CMakeLists.txt deleted file mode 100644 index fae89e1..0000000 --- a/ft8CN/app/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ - -# For more information about using CMake with Android Studio, read the -# documentation: https://d.android.com/studio/projects/add-native-code.html - -# Sets the minimum version of CMake required to build the native library. - -cmake_minimum_required(VERSION 3.18.1) - -# Declares and names the project. - -project("ft8cn") - -# Creates and names a library, sets it as either STATIC -# or SHARED, and provides the relative paths to its source code. -# You can define multiple libraries, and CMake builds them for you. -# Gradle automatically packages shared libraries with your APK. - -add_library( # Sets the name of the library. - ft8cn - - # Sets the library as a shared library. - SHARED - - # Provides a relative path to your source file(s). - - generate_ft8.cpp - ft8Listener.cpp - ft8Spectrum.cpp - fft/kiss_fftr.c - fft/kiss_fft.c - - ft8/decode.c - ft8/crc.c - ft8/constants.c - ft8/ldpc.c - ft8/unpack.c - ft8/text.c - ft8/hash22.c - ft8/encode.c - ft8/pack.c - monitor_opr.c - ft8Decoder.c - ft8Encoder.c - spectrum_data.c - ) - -# Searches for a specified prebuilt library and stores the path as a -# variable. Because CMake includes system libraries in the search path by -# default, you only need to specify the name of the public NDK library -# you want to add. CMake verifies that the library exists before -# completing its build. - -find_library( # Sets the name of the path variable. - log-lib - - # Specifies the name of the NDK library that - # you want CMake to locate. - log ) - -# Specifies libraries CMake should link to your target library. You -# can link multiple libraries, such as libraries you define in this -# build script, prebuilt third-party libraries, or system libraries. - -target_link_libraries( # Specifies the target library. - ft8cn - - # Links the target library to the log library - # included in the NDK. - ${log-lib} ) diff --git a/ft8CN/app/src/main/cpp/common/comm_str.h b/ft8CN/app/src/main/cpp/common/comm_str.h deleted file mode 100644 index 185aca8..0000000 --- a/ft8CN/app/src/main/cpp/common/comm_str.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by jmsmf on 2022/4/22. -// - -#ifndef NATIVEC_COMM_STR_H -#define NATIVEC_COMM_STR_H - -#endif //NATIVEC_COMM_STR_H -const char ERROR_FILE_NAME_IS_NULL[] = "error:wav_path is null!!!"; -const char ERROR_OPEN_FILE_FAILED[] ="Error : the content of the file does not meet the requirements."; -const char INFO_DECODE_OK[] ="decode OK!!!"; \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/common/common.h b/ft8CN/app/src/main/cpp/common/common.h deleted file mode 100644 index fc2a2f9..0000000 --- a/ft8CN/app/src/main/cpp/common/common.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif diff --git a/ft8CN/app/src/main/cpp/common/debug.h b/ft8CN/app/src/main/cpp/common/debug.h deleted file mode 100644 index 4dec693..0000000 --- a/ft8CN/app/src/main/cpp/common/debug.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include - -#define LOG_DEBUG 0 -#define LOG_INFO 1 -#define LOG_WARN 2 -#define LOG_ERROR 3 -#define LOG_FATAL 4 -#define LOG_LEVEL LOG_DEBUG -//#define LOG_LEVEL LOG_INFO - -//#define LOG(level, ...) if (level >= LOG_LEVEL) fprintf(stderr, __VA_ARGS__) -#define TAG "FT8_DECODER" // 这个是自定义的LOG的标识 -#define LOG(level, ...) if (level >= LOG_LEVEL) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) -#define LOG_PRINTF(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) - -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 -#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 -#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/common/wave.c b/ft8CN/app/src/main/cpp/common/wave.c deleted file mode 100644 index 6f08ac6..0000000 --- a/ft8CN/app/src/main/cpp/common/wave.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "wave.h" - -#include -#include -#include - -#include - -// Save signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers. -void save_wav(const float* signal, int num_samples, int sample_rate, const char* path) -{ - char subChunk1ID[4] = { 'f', 'm', 't', ' ' }; - uint32_t subChunk1Size = 16; // 16 for PCM - uint16_t audioFormat = 1; // PCM = 1 - uint16_t numChannels = 1; - uint16_t bitsPerSample = 16; - uint32_t sampleRate = sample_rate; - uint16_t blockAlign = numChannels * bitsPerSample / 8; - uint32_t byteRate = sampleRate * blockAlign; - - char subChunk2ID[4] = { 'd', 'a', 't', 'a' }; - uint32_t subChunk2Size = num_samples * blockAlign; - - char chunkID[4] = { 'R', 'I', 'F', 'F' }; - uint32_t chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); - char format[4] = { 'W', 'A', 'V', 'E' }; - - int16_t* raw_data = (int16_t*)malloc(num_samples * blockAlign); - for (int i = 0; i < num_samples; i++) - { - float x = signal[i]; - if (x > 1.0) - x = 1.0; - else if (x < -1.0) - x = -1.0; - raw_data[i] = (int)(x * 32767.0); - } - - FILE* f = fopen(path, "wb"); - - // NOTE: works only on little-endian architecture - fwrite(chunkID, sizeof(chunkID), 1, f); - fwrite(&chunkSize, sizeof(chunkSize), 1, f); - fwrite(format, sizeof(format), 1, f); - - fwrite(subChunk1ID, sizeof(subChunk1ID), 1, f); - fwrite(&subChunk1Size, sizeof(subChunk1Size), 1, f); - fwrite(&audioFormat, sizeof(audioFormat), 1, f); - fwrite(&numChannels, sizeof(numChannels), 1, f); - fwrite(&sampleRate, sizeof(sampleRate), 1, f); - fwrite(&byteRate, sizeof(byteRate), 1, f); - fwrite(&blockAlign, sizeof(blockAlign), 1, f); - fwrite(&bitsPerSample, sizeof(bitsPerSample), 1, f); - - fwrite(subChunk2ID, sizeof(subChunk2ID), 1, f); - fwrite(&subChunk2Size, sizeof(subChunk2Size), 1, f); - - fwrite(raw_data, blockAlign, num_samples, f); - - fclose(f); - - free(raw_data); -} - -// Load signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers. -int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path) -{ - char subChunk1ID[4]; // = {'f', 'm', 't', ' '}; - uint32_t subChunk1Size; // = 16; // 16 for PCM - uint16_t audioFormat; // = 1; // PCM = 1 - uint16_t numChannels; // = 1; - uint16_t bitsPerSample; // = 16; - uint32_t sampleRate; - uint16_t blockAlign; // = numChannels * bitsPerSample / 8; - uint32_t byteRate; // = sampleRate * blockAlign; - - char subChunk2ID[4]; // = {'d', 'a', 't', 'a'}; - uint32_t subChunk2Size; // = num_samples * blockAlign; - - char chunkID[4]; // = {'R', 'I', 'F', 'F'}; - uint32_t chunkSize; // = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); - char format[4]; // = {'W', 'A', 'V', 'E'}; - - FILE* f = fopen(path, "rb"); - if (f==NULL){ - return -1; - } - - // NOTE: works only on little-endian architecture - fread((void*)chunkID, sizeof(chunkID), 1, f); - fread((void*)&chunkSize, sizeof(chunkSize), 1, f); - fread((void*)format, sizeof(format), 1, f); - - fread((void*)subChunk1ID, sizeof(subChunk1ID), 1, f); - fread((void*)&subChunk1Size, sizeof(subChunk1Size), 1, f); - if (subChunk1Size != 16) - return -1; - - fread((void*)&audioFormat, sizeof(audioFormat), 1, f); - fread((void*)&numChannels, sizeof(numChannels), 1, f); - fread((void*)&sampleRate, sizeof(sampleRate), 1, f); - fread((void*)&byteRate, sizeof(byteRate), 1, f); - fread((void*)&blockAlign, sizeof(blockAlign), 1, f); - fread((void*)&bitsPerSample, sizeof(bitsPerSample), 1, f); - - if (audioFormat != 1 || numChannels != 1 || bitsPerSample != 16) - return -1; - - fread((void*)subChunk2ID, sizeof(subChunk2ID), 1, f); - fread((void*)&subChunk2Size, sizeof(subChunk2Size), 1, f); - - if (subChunk2Size / blockAlign > *num_samples) - return -2; - - *num_samples = subChunk2Size / blockAlign; - *sample_rate = sampleRate; - - int16_t* raw_data = (int16_t*)malloc(*num_samples * blockAlign); - - fread((void*)raw_data, blockAlign, *num_samples, f); - for (int i = 0; i < *num_samples; i++) - { - signal[i] = raw_data[i] / 32768.0f; - } - - free(raw_data); - - fclose(f); - - return 0; -} diff --git a/ft8CN/app/src/main/cpp/common/wave.h b/ft8CN/app/src/main/cpp/common/wave.h deleted file mode 100644 index def1296..0000000 --- a/ft8CN/app/src/main/cpp/common/wave.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _INCLUDE_WAVE_H_ -#define _INCLUDE_WAVE_H_ - -// Save signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers. -void save_wav(const float* signal, int num_samples, int sample_rate, const char* path); - -// Load signal in floating point format (-1 .. +1) as a WAVE file using 16-bit signed integers. -int load_wav(float* signal, int* num_samples, int* sample_rate, const char* path); - -#endif // _INCLUDE_WAVE_H_ diff --git a/ft8CN/app/src/main/cpp/fft/_kiss_fft_guts.h b/ft8CN/app/src/main/cpp/fft/_kiss_fft_guts.h deleted file mode 100644 index bf5d53c..0000000 --- a/ft8CN/app/src/main/cpp/fft/_kiss_fft_guts.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. - * This file is part of KISS FFT - https://github.com/mborgerding/kissfft - * - * SPDX-License-Identifier: BSD-3-Clause - * See COPYING file for more information. - */ - -/* kiss_fft.h - defines kiss_fft_scalar as either short or a float type - and defines - typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ -#include "kiss_fft.h" -#include - -#define MAXFACTORS 32 -/* e.g. an fft of length 128 has 4 factors - as far as kissfft is concerned - 4*4*4*2 - */ - -struct kiss_fft_state{ - int nfft; - int inverse; - int factors[2*MAXFACTORS]; - kiss_fft_cpx twiddles[1]; -}; - -/* - Explanation of macros dealing with complex math: - - C_MUL(m,a,b) : m = a*b - C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise - C_SUB( res, a,b) : res = a - b - C_SUBFROM( res , a) : res -= a - C_ADDTO( res , a) : res += a - * */ -#ifdef FIXED_POINT -#if (FIXED_POINT==32) -# define FRACBITS 31 -# define SAMPPROD int64_t -#define SAMP_MAX 2147483647 -#else -# define FRACBITS 15 -# define SAMPPROD int32_t -#define SAMP_MAX 32767 -#endif - -#define SAMP_MIN -SAMP_MAX - -#if defined(CHECK_OVERFLOW) -# define CHECK_OVERFLOW_OP(a,op,b) \ - if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ - fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } -#endif - - -# define smul(a,b) ( (SAMPPROD)(a)*(b) ) -# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) - -# define S_MUL(a,b) sround( smul(a,b) ) - -# define C_MUL(m,a,b) \ - do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ - (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) - -# define DIVSCALAR(x,k) \ - (x) = sround( smul( x, SAMP_MAX/k ) ) - -# define C_FIXDIV(c,div) \ - do { DIVSCALAR( (c).r , div); \ - DIVSCALAR( (c).i , div); }while (0) - -# define C_MULBYSCALAR( c, s ) \ - do{ (c).r = sround( smul( (c).r , s ) ) ;\ - (c).i = sround( smul( (c).i , s ) ) ; }while(0) - -#else /* not FIXED_POINT*/ - -# define S_MUL(a,b) ( (a)*(b) ) -#define C_MUL(m,a,b) \ - do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ - (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) -# define C_FIXDIV(c,div) /* NOOP */ -# define C_MULBYSCALAR( c, s ) \ - do{ (c).r *= (s);\ - (c).i *= (s); }while(0) -#endif - -#ifndef CHECK_OVERFLOW_OP -# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ -#endif - -#define C_ADD( res, a,b)\ - do { \ - CHECK_OVERFLOW_OP((a).r,+,(b).r)\ - CHECK_OVERFLOW_OP((a).i,+,(b).i)\ - (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ - }while(0) -#define C_SUB( res, a,b)\ - do { \ - CHECK_OVERFLOW_OP((a).r,-,(b).r)\ - CHECK_OVERFLOW_OP((a).i,-,(b).i)\ - (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ - }while(0) -#define C_ADDTO( res , a)\ - do { \ - CHECK_OVERFLOW_OP((res).r,+,(a).r)\ - CHECK_OVERFLOW_OP((res).i,+,(a).i)\ - (res).r += (a).r; (res).i += (a).i;\ - }while(0) - -#define C_SUBFROM( res , a)\ - do {\ - CHECK_OVERFLOW_OP((res).r,-,(a).r)\ - CHECK_OVERFLOW_OP((res).i,-,(a).i)\ - (res).r -= (a).r; (res).i -= (a).i; \ - }while(0) - - -#ifdef FIXED_POINT -# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) -# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) -# define HALF_OF(x) ((x)>>1) -#elif defined(USE_SIMD) -# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) -# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) -# define HALF_OF(x) ((x)*_mm_set1_ps(.5)) -#else -# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) -# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) -# define HALF_OF(x) ((x)*.5) -#endif - -#define kf_cexp(x,phase) \ - do{ \ - (x)->r = KISS_FFT_COS(phase);\ - (x)->i = KISS_FFT_SIN(phase);\ - }while(0) - - -/* a debugging function */ -#define pcpx(c)\ - fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) - - -#ifdef KISS_FFT_USE_ALLOCA -// define this to allow use of alloca instead of malloc for temporary buffers -// Temporary buffers are used in two case: -// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 -// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. -#include -#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) -#define KISS_FFT_TMP_FREE(ptr) -#else -#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) -#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) -#endif diff --git a/ft8CN/app/src/main/cpp/fft/kiss_fft.c b/ft8CN/app/src/main/cpp/fft/kiss_fft.c deleted file mode 100644 index af2f695..0000000 --- a/ft8CN/app/src/main/cpp/fft/kiss_fft.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. - * This file is part of KISS FFT - https://github.com/mborgerding/kissfft - * - * SPDX-License-Identifier: BSD-3-Clause - * See COPYING file for more information. - */ - - -#include "_kiss_fft_guts.h" -/* The guts header contains all the multiplication and addition macros that are defined for - fixed or floating point complex numbers. It also delares the kf_ internal functions. - */ - -static void kf_bfly2( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m - ) -{ - kiss_fft_cpx * Fout2; - kiss_fft_cpx * tw1 = st->twiddles; - kiss_fft_cpx t; - Fout2 = Fout + m; - do{ - C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2); - - C_MUL (t, *Fout2 , *tw1); - tw1 += fstride; - C_SUB( *Fout2 , *Fout , t ); - C_ADDTO( *Fout , t ); - ++Fout2; - ++Fout; - }while (--m); -} - -static void kf_bfly4( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - const size_t m - ) -{ - kiss_fft_cpx *tw1,*tw2,*tw3; - kiss_fft_cpx scratch[6]; - size_t k=m; - const size_t m2=2*m; - const size_t m3=3*m; - - - tw3 = tw2 = tw1 = st->twiddles; - - do { - C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4); - - C_MUL(scratch[0],Fout[m] , *tw1 ); - C_MUL(scratch[1],Fout[m2] , *tw2 ); - C_MUL(scratch[2],Fout[m3] , *tw3 ); - - C_SUB( scratch[5] , *Fout, scratch[1] ); - C_ADDTO(*Fout, scratch[1]); - C_ADD( scratch[3] , scratch[0] , scratch[2] ); - C_SUB( scratch[4] , scratch[0] , scratch[2] ); - C_SUB( Fout[m2], *Fout, scratch[3] ); - tw1 += fstride; - tw2 += fstride*2; - tw3 += fstride*3; - C_ADDTO( *Fout , scratch[3] ); - - if(st->inverse) { - Fout[m].r = scratch[5].r - scratch[4].i; - Fout[m].i = scratch[5].i + scratch[4].r; - Fout[m3].r = scratch[5].r + scratch[4].i; - Fout[m3].i = scratch[5].i - scratch[4].r; - }else{ - Fout[m].r = scratch[5].r + scratch[4].i; - Fout[m].i = scratch[5].i - scratch[4].r; - Fout[m3].r = scratch[5].r - scratch[4].i; - Fout[m3].i = scratch[5].i + scratch[4].r; - } - ++Fout; - }while(--k); -} - -static void kf_bfly3( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - size_t m - ) -{ - size_t k=m; - const size_t m2 = 2*m; - kiss_fft_cpx *tw1,*tw2; - kiss_fft_cpx scratch[5]; - kiss_fft_cpx epi3; - epi3 = st->twiddles[fstride*m]; - - tw1=tw2=st->twiddles; - - do{ - C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); - - C_MUL(scratch[1],Fout[m] , *tw1); - C_MUL(scratch[2],Fout[m2] , *tw2); - - C_ADD(scratch[3],scratch[1],scratch[2]); - C_SUB(scratch[0],scratch[1],scratch[2]); - tw1 += fstride; - tw2 += fstride*2; - - Fout[m].r = Fout->r - HALF_OF(scratch[3].r); - Fout[m].i = Fout->i - HALF_OF(scratch[3].i); - - C_MULBYSCALAR( scratch[0] , epi3.i ); - - C_ADDTO(*Fout,scratch[3]); - - Fout[m2].r = Fout[m].r + scratch[0].i; - Fout[m2].i = Fout[m].i - scratch[0].r; - - Fout[m].r -= scratch[0].i; - Fout[m].i += scratch[0].r; - - ++Fout; - }while(--k); -} - -static void kf_bfly5( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m - ) -{ - kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; - int u; - kiss_fft_cpx scratch[13]; - kiss_fft_cpx * twiddles = st->twiddles; - kiss_fft_cpx *tw; - kiss_fft_cpx ya,yb; - ya = twiddles[fstride*m]; - yb = twiddles[fstride*2*m]; - - Fout0=Fout; - Fout1=Fout0+m; - Fout2=Fout0+2*m; - Fout3=Fout0+3*m; - Fout4=Fout0+4*m; - - tw=st->twiddles; - for ( u=0; ur += scratch[7].r + scratch[8].r; - Fout0->i += scratch[7].i + scratch[8].i; - - scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); - scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); - - scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); - scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); - - C_SUB(*Fout1,scratch[5],scratch[6]); - C_ADD(*Fout4,scratch[5],scratch[6]); - - scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); - scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); - scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); - scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); - - C_ADD(*Fout2,scratch[11],scratch[12]); - C_SUB(*Fout3,scratch[11],scratch[12]); - - ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; - } -} - -/* perform the butterfly for one stage of a mixed radix FFT */ -static void kf_bfly_generic( - kiss_fft_cpx * Fout, - const size_t fstride, - const kiss_fft_cfg st, - int m, - int p - ) -{ - int u,k,q1,q; - kiss_fft_cpx * twiddles = st->twiddles; - kiss_fft_cpx t; - int Norig = st->nfft; - - kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p); - - for ( u=0; u=Norig) twidx-=Norig; - C_MUL(t,scratch[q] , twiddles[twidx] ); - C_ADDTO( Fout[ k ] ,t); - } - k += m; - } - } - KISS_FFT_TMP_FREE(scratch); -} - -static -void kf_work( - kiss_fft_cpx * Fout, - const kiss_fft_cpx * f, - const size_t fstride, - int in_stride, - int * factors, - const kiss_fft_cfg st - ) -{ - kiss_fft_cpx * Fout_beg=Fout; - const int p=*factors++; /* the radix */ - const int m=*factors++; /* stage's fft length/p */ - const kiss_fft_cpx * Fout_end = Fout + p*m; - -#ifdef _OPENMP - // use openmp extensions at the - // top-level (not recursive) - if (fstride==1 && p<=5) - { - int k; - - // execute the p different work units in different threads -# pragma omp parallel for - for (k=0;k floor_sqrt) - p = n; /* no more factors, skip to end */ - } - n /= p; - *facbuf++ = p; - *facbuf++ = n; - } while (n > 1); -} - -/* - * - * User-callable function to allocate all necessary storage space for the fft. - * - * The return value is a contiguous block of memory, allocated with malloc. As such, - * It can be freed with free(), rather than a kiss_fft-specific function. - * */ -kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) -{ - kiss_fft_cfg st=NULL; - size_t memneeded = sizeof(struct kiss_fft_state) - + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ - - if ( lenmem==NULL ) { - st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); - }else{ - if (mem != NULL && *lenmem >= memneeded) - st = (kiss_fft_cfg)mem; - *lenmem = memneeded; - } - if (st) { - int i; - st->nfft=nfft; - st->inverse = inverse_fft; - - for (i=0;iinverse) - phase *= -1; - kf_cexp(st->twiddles+i, phase ); - } - - kf_factor(nfft,st->factors); - } - return st; -} - - -void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) -{ - if (fin == fout) { - //NOTE: this is not really an in-place FFT algorithm. - //It just performs an out-of-place FFT into a temp buffer - kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft); - kf_work(tmpbuf,fin,1,in_stride, st->factors,st); - memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); - KISS_FFT_TMP_FREE(tmpbuf); - }else{ - kf_work( fout, fin, 1,in_stride, st->factors,st ); - } -} - -void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) -{ - kiss_fft_stride(cfg,fin,fout,1); -} - - -void kiss_fft_cleanup(void) -{ - // nothing needed any more -} - -int kiss_fft_next_fast_size(int n) -{ - while(1) { - int m=n; - while ( (m%2) == 0 ) m/=2; - while ( (m%3) == 0 ) m/=3; - while ( (m%5) == 0 ) m/=5; - if (m<=1) - break; /* n is completely factorable by twos, threes, and fives */ - n++; - } - return n; -} diff --git a/ft8CN/app/src/main/cpp/fft/kiss_fft.h b/ft8CN/app/src/main/cpp/fft/kiss_fft.h deleted file mode 100644 index 45c3a6a..0000000 --- a/ft8CN/app/src/main/cpp/fft/kiss_fft.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. - * This file is part of KISS FFT - https://github.com/mborgerding/kissfft - * - * SPDX-License-Identifier: BSD-3-Clause - * See COPYING file for more information. - */ - -#ifndef KISS_FFT_H -#define KISS_FFT_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - ATTENTION! - If you would like a : - -- a utility that will handle the caching of fft objects - -- real-only (no imaginary time component ) FFT - -- a multi-dimensional FFT - -- a command-line utility to perform ffts - -- a command-line utility to perform fast-convolution filtering - - Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c - in the tools/ directory. -*/ - -#ifdef USE_SIMD -# include -# define kiss_fft_scalar __m128 -#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) -#define KISS_FFT_FREE _mm_free -#else -#define KISS_FFT_MALLOC malloc -#define KISS_FFT_FREE free -#endif - - -#ifdef FIXED_POINT -#include -# if (FIXED_POINT == 32) -# define kiss_fft_scalar int32_t -# else -# define kiss_fft_scalar int16_t -# endif -#else -# ifndef kiss_fft_scalar -/* default is float */ -# define kiss_fft_scalar float -# endif -#endif - -typedef struct { - kiss_fft_scalar r; - kiss_fft_scalar i; -}kiss_fft_cpx; - -typedef struct kiss_fft_state* kiss_fft_cfg; - -/* - * kiss_fft_alloc - * - * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. - * - * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); - * - * The return value from fft_alloc is a cfg buffer used internally - * by the fft routine or NULL. - * - * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. - * The returned value should be free()d when done to avoid memory leaks. - * - * The state can be placed in a user supplied buffer 'mem': - * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, - * then the function places the cfg in mem and the size used in *lenmem - * and returns mem. - * - * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), - * then the function returns NULL and places the minimum cfg - * buffer size in *lenmem. - * */ - -kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); - -/* - * kiss_fft(cfg,in_out_buf) - * - * Perform an FFT on a complex input buffer. - * for a forward FFT, - * fin should be f[0] , f[1] , ... ,f[nfft-1] - * fout will be F[0] , F[1] , ... ,F[nfft-1] - * Note that each element is complex and can be accessed like - f[k].r and f[k].i - * */ -void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); - -/* - A more generic version of the above function. It reads its input from every Nth sample. - * */ -void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); - -/* If kiss_fft_alloc allocated a buffer, it is one contiguous - buffer and can be simply free()d when no longer needed*/ -#define kiss_fft_free KISS_FFT_FREE - -/* - Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up - your compiler output to call this before you exit. -*/ -void kiss_fft_cleanup(void); - - -/* - * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) - */ -int kiss_fft_next_fast_size(int n); - -/* for real ffts, we need an even size */ -#define kiss_fftr_next_fast_size_real(n) \ - (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ft8CN/app/src/main/cpp/fft/kiss_fftr.c b/ft8CN/app/src/main/cpp/fft/kiss_fftr.c deleted file mode 100644 index 8102132..0000000 --- a/ft8CN/app/src/main/cpp/fft/kiss_fftr.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved. - * This file is part of KISS FFT - https://github.com/mborgerding/kissfft - * - * SPDX-License-Identifier: BSD-3-Clause - * See COPYING file for more information. - */ - -#include "kiss_fftr.h" -#include "_kiss_fft_guts.h" - -struct kiss_fftr_state{ - kiss_fft_cfg substate; - kiss_fft_cpx * tmpbuf; - kiss_fft_cpx * super_twiddles; -#ifdef USE_SIMD - void * pad; -#endif -}; - -kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) -{ - int i; - kiss_fftr_cfg st = NULL; - size_t subsize = 0, memneeded; - - if (nfft & 1) { - fprintf(stderr,"Real FFT optimization must be even.\n"); - return NULL; - } - nfft >>= 1; - - kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); - memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); - - if (lenmem == NULL) { - st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); - } else { - if (*lenmem >= memneeded) - st = (kiss_fftr_cfg) mem; - *lenmem = memneeded; - } - if (!st) - return NULL; - - st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ - st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); - st->super_twiddles = st->tmpbuf + nfft; - kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); - - for (i = 0; i < nfft/2; ++i) { - double phase = - -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5); - if (inverse_fft) - phase *= -1; - kf_cexp (st->super_twiddles+i,phase); - } - return st; -} - -void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) -{ - /* input buffer timedata is stored row-wise */ - int k,ncfft; - kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; - - if ( st->substate->inverse) { - fprintf(stderr,"kiss fft usage error: improper alloc\n"); - exit(1); - } - - ncfft = st->substate->nfft; - - /*perform the parallel fft of two real signals packed in real,imag*/ - kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); - /* The real part of the DC element of the frequency spectrum in st->tmpbuf - * contains the sum of the even-numbered elements of the input time sequence - * The imag part is the sum of the odd-numbered elements - * - * The sum of tdc.r and tdc.i is the sum of the input time sequence. - * yielding DC of input time sequence - * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... - * yielding Nyquist bin of input time sequence - */ - - tdc.r = st->tmpbuf[0].r; - tdc.i = st->tmpbuf[0].i; - C_FIXDIV(tdc,2); - CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); - CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); - freqdata[0].r = tdc.r + tdc.i; - freqdata[ncfft].r = tdc.r - tdc.i; -#ifdef USE_SIMD - freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); -#else - freqdata[ncfft].i = freqdata[0].i = 0; -#endif - - for ( k=1;k <= ncfft/2 ; ++k ) { - fpk = st->tmpbuf[k]; - fpnk.r = st->tmpbuf[ncfft-k].r; - fpnk.i = - st->tmpbuf[ncfft-k].i; - C_FIXDIV(fpk,2); - C_FIXDIV(fpnk,2); - - C_ADD( f1k, fpk , fpnk ); - C_SUB( f2k, fpk , fpnk ); - C_MUL( tw , f2k , st->super_twiddles[k-1]); - - freqdata[k].r = HALF_OF(f1k.r + tw.r); - freqdata[k].i = HALF_OF(f1k.i + tw.i); - freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); - freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); - } -} - -void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) -{ - /* input buffer timedata is stored row-wise */ - int k, ncfft; - - if (st->substate->inverse == 0) { - fprintf (stderr, "kiss fft usage error: improper alloc\n"); - exit (1); - } - - ncfft = st->substate->nfft; - - st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; - st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; - C_FIXDIV(st->tmpbuf[0],2); - - for (k = 1; k <= ncfft / 2; ++k) { - kiss_fft_cpx fk, fnkc, fek, fok, tmp; - fk = freqdata[k]; - fnkc.r = freqdata[ncfft - k].r; - fnkc.i = -freqdata[ncfft - k].i; - C_FIXDIV( fk , 2 ); - C_FIXDIV( fnkc , 2 ); - - C_ADD (fek, fk, fnkc); - C_SUB (tmp, fk, fnkc); - C_MUL (fok, tmp, st->super_twiddles[k-1]); - C_ADD (st->tmpbuf[k], fek, fok); - C_SUB (st->tmpbuf[ncfft - k], fek, fok); -#ifdef USE_SIMD - st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); -#else - st->tmpbuf[ncfft - k].i *= -1; -#endif - } - kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); -} diff --git a/ft8CN/app/src/main/cpp/fft/kiss_fftr.h b/ft8CN/app/src/main/cpp/fft/kiss_fftr.h deleted file mode 100644 index 588948d..0000000 --- a/ft8CN/app/src/main/cpp/fft/kiss_fftr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved. - * This file is part of KISS FFT - https://github.com/mborgerding/kissfft - * - * SPDX-License-Identifier: BSD-3-Clause - * See COPYING file for more information. - */ - -#ifndef KISS_FTR_H -#define KISS_FTR_H - -#include "kiss_fft.h" -#ifdef __cplusplus -extern "C" { -#endif - - -/* - - Real optimized version can save about 45% cpu time vs. complex fft of a real seq. - - - - */ - -typedef struct kiss_fftr_state *kiss_fftr_cfg; - - -kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); -/* - nfft must be even - - If you don't care to allocate space, use mem = lenmem = NULL -*/ - - -void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); -/* - input timedata has nfft scalar points - output freqdata has nfft/2+1 complex points -*/ - -void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); -/* - input freqdata has nfft/2+1 complex points - output timedata has nfft scalar points -*/ - -#define kiss_fftr_free KISS_FFT_FREE - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ft8CN/app/src/main/cpp/ft8/constants.c b/ft8CN/app/src/main/cpp/ft8/constants.c deleted file mode 100644 index f98fc50..0000000 --- a/ft8CN/app/src/main/cpp/ft8/constants.c +++ /dev/null @@ -1,394 +0,0 @@ -#include "constants.h" - - -//科斯塔阵列 -const uint8_t kFT8CostasPattern[7] = { 3, 1, 4, 0, 6, 5, 2 }; -const uint8_t kFT4CostasPattern[4][4] = { - { 0, 1, 3, 2 }, - { 1, 0, 2, 3 }, - { 2, 3, 1, 0 }, - { 3, 2, 0, 1 } -}; - -// Gray code map (FTx bits -> channel symbols) -//格雷码 -const uint8_t kFT8GrayMap[8] = { 0, 1, 3, 2, 5, 6, 4, 7 }; -const uint8_t kFT4GrayMap[4] = { 0, 1, 3, 2 }; - -const uint8_t kFT4XORSequence[10] = { - 0x4Au, // 01001010 - 0x5Eu, // 01011110 - 0x89u, // 10001001 - 0xB4u, // 10110100 - 0xB0u, // 10110000 - 0x8Au, // 10001010 - 0x79u, // 01111001 - 0x55u, // 01010101 - 0xBEu, // 10111110 - 0x28u, // 00101 [000] -}; - -// Parity generator matrix for (174,91) LDPC code, stored in bitpacked format (MSB first) -const uint8_t kFTXLDPCGenerator[FTX_LDPC_M][FTX_LDPC_K_BYTES] = { - { 0x83, 0x29, 0xce, 0x11, 0xbf, 0x31, 0xea, 0xf5, 0x09, 0xf2, 0x7f, 0xc0 }, - { 0x76, 0x1c, 0x26, 0x4e, 0x25, 0xc2, 0x59, 0x33, 0x54, 0x93, 0x13, 0x20 }, - { 0xdc, 0x26, 0x59, 0x02, 0xfb, 0x27, 0x7c, 0x64, 0x10, 0xa1, 0xbd, 0xc0 }, - { 0x1b, 0x3f, 0x41, 0x78, 0x58, 0xcd, 0x2d, 0xd3, 0x3e, 0xc7, 0xf6, 0x20 }, - { 0x09, 0xfd, 0xa4, 0xfe, 0xe0, 0x41, 0x95, 0xfd, 0x03, 0x47, 0x83, 0xa0 }, - { 0x07, 0x7c, 0xcc, 0xc1, 0x1b, 0x88, 0x73, 0xed, 0x5c, 0x3d, 0x48, 0xa0 }, - { 0x29, 0xb6, 0x2a, 0xfe, 0x3c, 0xa0, 0x36, 0xf4, 0xfe, 0x1a, 0x9d, 0xa0 }, - { 0x60, 0x54, 0xfa, 0xf5, 0xf3, 0x5d, 0x96, 0xd3, 0xb0, 0xc8, 0xc3, 0xe0 }, - { 0xe2, 0x07, 0x98, 0xe4, 0x31, 0x0e, 0xed, 0x27, 0x88, 0x4a, 0xe9, 0x00 }, - { 0x77, 0x5c, 0x9c, 0x08, 0xe8, 0x0e, 0x26, 0xdd, 0xae, 0x56, 0x31, 0x80 }, - { 0xb0, 0xb8, 0x11, 0x02, 0x8c, 0x2b, 0xf9, 0x97, 0x21, 0x34, 0x87, 0xc0 }, - { 0x18, 0xa0, 0xc9, 0x23, 0x1f, 0xc6, 0x0a, 0xdf, 0x5c, 0x5e, 0xa3, 0x20 }, - { 0x76, 0x47, 0x1e, 0x83, 0x02, 0xa0, 0x72, 0x1e, 0x01, 0xb1, 0x2b, 0x80 }, - { 0xff, 0xbc, 0xcb, 0x80, 0xca, 0x83, 0x41, 0xfa, 0xfb, 0x47, 0xb2, 0xe0 }, - { 0x66, 0xa7, 0x2a, 0x15, 0x8f, 0x93, 0x25, 0xa2, 0xbf, 0x67, 0x17, 0x00 }, - { 0xc4, 0x24, 0x36, 0x89, 0xfe, 0x85, 0xb1, 0xc5, 0x13, 0x63, 0xa1, 0x80 }, - { 0x0d, 0xff, 0x73, 0x94, 0x14, 0xd1, 0xa1, 0xb3, 0x4b, 0x1c, 0x27, 0x00 }, - { 0x15, 0xb4, 0x88, 0x30, 0x63, 0x6c, 0x8b, 0x99, 0x89, 0x49, 0x72, 0xe0 }, - { 0x29, 0xa8, 0x9c, 0x0d, 0x3d, 0xe8, 0x1d, 0x66, 0x54, 0x89, 0xb0, 0xe0 }, - { 0x4f, 0x12, 0x6f, 0x37, 0xfa, 0x51, 0xcb, 0xe6, 0x1b, 0xd6, 0xb9, 0x40 }, - { 0x99, 0xc4, 0x72, 0x39, 0xd0, 0xd9, 0x7d, 0x3c, 0x84, 0xe0, 0x94, 0x00 }, - { 0x19, 0x19, 0xb7, 0x51, 0x19, 0x76, 0x56, 0x21, 0xbb, 0x4f, 0x1e, 0x80 }, - { 0x09, 0xdb, 0x12, 0xd7, 0x31, 0xfa, 0xee, 0x0b, 0x86, 0xdf, 0x6b, 0x80 }, - { 0x48, 0x8f, 0xc3, 0x3d, 0xf4, 0x3f, 0xbd, 0xee, 0xa4, 0xea, 0xfb, 0x40 }, - { 0x82, 0x74, 0x23, 0xee, 0x40, 0xb6, 0x75, 0xf7, 0x56, 0xeb, 0x5f, 0xe0 }, - { 0xab, 0xe1, 0x97, 0xc4, 0x84, 0xcb, 0x74, 0x75, 0x71, 0x44, 0xa9, 0xa0 }, - { 0x2b, 0x50, 0x0e, 0x4b, 0xc0, 0xec, 0x5a, 0x6d, 0x2b, 0xdb, 0xdd, 0x00 }, - { 0xc4, 0x74, 0xaa, 0x53, 0xd7, 0x02, 0x18, 0x76, 0x16, 0x69, 0x36, 0x00 }, - { 0x8e, 0xba, 0x1a, 0x13, 0xdb, 0x33, 0x90, 0xbd, 0x67, 0x18, 0xce, 0xc0 }, - { 0x75, 0x38, 0x44, 0x67, 0x3a, 0x27, 0x78, 0x2c, 0xc4, 0x20, 0x12, 0xe0 }, - { 0x06, 0xff, 0x83, 0xa1, 0x45, 0xc3, 0x70, 0x35, 0xa5, 0xc1, 0x26, 0x80 }, - { 0x3b, 0x37, 0x41, 0x78, 0x58, 0xcc, 0x2d, 0xd3, 0x3e, 0xc3, 0xf6, 0x20 }, - { 0x9a, 0x4a, 0x5a, 0x28, 0xee, 0x17, 0xca, 0x9c, 0x32, 0x48, 0x42, 0xc0 }, - { 0xbc, 0x29, 0xf4, 0x65, 0x30, 0x9c, 0x97, 0x7e, 0x89, 0x61, 0x0a, 0x40 }, - { 0x26, 0x63, 0xae, 0x6d, 0xdf, 0x8b, 0x5c, 0xe2, 0xbb, 0x29, 0x48, 0x80 }, - { 0x46, 0xf2, 0x31, 0xef, 0xe4, 0x57, 0x03, 0x4c, 0x18, 0x14, 0x41, 0x80 }, - { 0x3f, 0xb2, 0xce, 0x85, 0xab, 0xe9, 0xb0, 0xc7, 0x2e, 0x06, 0xfb, 0xe0 }, - { 0xde, 0x87, 0x48, 0x1f, 0x28, 0x2c, 0x15, 0x39, 0x71, 0xa0, 0xa2, 0xe0 }, - { 0xfc, 0xd7, 0xcc, 0xf2, 0x3c, 0x69, 0xfa, 0x99, 0xbb, 0xa1, 0x41, 0x20 }, - { 0xf0, 0x26, 0x14, 0x47, 0xe9, 0x49, 0x0c, 0xa8, 0xe4, 0x74, 0xce, 0xc0 }, - { 0x44, 0x10, 0x11, 0x58, 0x18, 0x19, 0x6f, 0x95, 0xcd, 0xd7, 0x01, 0x20 }, - { 0x08, 0x8f, 0xc3, 0x1d, 0xf4, 0xbf, 0xbd, 0xe2, 0xa4, 0xea, 0xfb, 0x40 }, - { 0xb8, 0xfe, 0xf1, 0xb6, 0x30, 0x77, 0x29, 0xfb, 0x0a, 0x07, 0x8c, 0x00 }, - { 0x5a, 0xfe, 0xa7, 0xac, 0xcc, 0xb7, 0x7b, 0xbc, 0x9d, 0x99, 0xa9, 0x00 }, - { 0x49, 0xa7, 0x01, 0x6a, 0xc6, 0x53, 0xf6, 0x5e, 0xcd, 0xc9, 0x07, 0x60 }, - { 0x19, 0x44, 0xd0, 0x85, 0xbe, 0x4e, 0x7d, 0xa8, 0xd6, 0xcc, 0x7d, 0x00 }, - { 0x25, 0x1f, 0x62, 0xad, 0xc4, 0x03, 0x2f, 0x0e, 0xe7, 0x14, 0x00, 0x20 }, - { 0x56, 0x47, 0x1f, 0x87, 0x02, 0xa0, 0x72, 0x1e, 0x00, 0xb1, 0x2b, 0x80 }, - { 0x2b, 0x8e, 0x49, 0x23, 0xf2, 0xdd, 0x51, 0xe2, 0xd5, 0x37, 0xfa, 0x00 }, - { 0x6b, 0x55, 0x0a, 0x40, 0xa6, 0x6f, 0x47, 0x55, 0xde, 0x95, 0xc2, 0x60 }, - { 0xa1, 0x8a, 0xd2, 0x8d, 0x4e, 0x27, 0xfe, 0x92, 0xa4, 0xf6, 0xc8, 0x40 }, - { 0x10, 0xc2, 0xe5, 0x86, 0x38, 0x8c, 0xb8, 0x2a, 0x3d, 0x80, 0x75, 0x80 }, - { 0xef, 0x34, 0xa4, 0x18, 0x17, 0xee, 0x02, 0x13, 0x3d, 0xb2, 0xeb, 0x00 }, - { 0x7e, 0x9c, 0x0c, 0x54, 0x32, 0x5a, 0x9c, 0x15, 0x83, 0x6e, 0x00, 0x00 }, - { 0x36, 0x93, 0xe5, 0x72, 0xd1, 0xfd, 0xe4, 0xcd, 0xf0, 0x79, 0xe8, 0x60 }, - { 0xbf, 0xb2, 0xce, 0xc5, 0xab, 0xe1, 0xb0, 0xc7, 0x2e, 0x07, 0xfb, 0xe0 }, - { 0x7e, 0xe1, 0x82, 0x30, 0xc5, 0x83, 0xcc, 0xcc, 0x57, 0xd4, 0xb0, 0x80 }, - { 0xa0, 0x66, 0xcb, 0x2f, 0xed, 0xaf, 0xc9, 0xf5, 0x26, 0x64, 0x12, 0x60 }, - { 0xbb, 0x23, 0x72, 0x5a, 0xbc, 0x47, 0xcc, 0x5f, 0x4c, 0xc4, 0xcd, 0x20 }, - { 0xde, 0xd9, 0xdb, 0xa3, 0xbe, 0xe4, 0x0c, 0x59, 0xb5, 0x60, 0x9b, 0x40 }, - { 0xd9, 0xa7, 0x01, 0x6a, 0xc6, 0x53, 0xe6, 0xde, 0xcd, 0xc9, 0x03, 0x60 }, - { 0x9a, 0xd4, 0x6a, 0xed, 0x5f, 0x70, 0x7f, 0x28, 0x0a, 0xb5, 0xfc, 0x40 }, - { 0xe5, 0x92, 0x1c, 0x77, 0x82, 0x25, 0x87, 0x31, 0x6d, 0x7d, 0x3c, 0x20 }, - { 0x4f, 0x14, 0xda, 0x82, 0x42, 0xa8, 0xb8, 0x6d, 0xca, 0x73, 0x35, 0x20 }, - { 0x8b, 0x8b, 0x50, 0x7a, 0xd4, 0x67, 0xd4, 0x44, 0x1d, 0xf7, 0x70, 0xe0 }, - { 0x22, 0x83, 0x1c, 0x9c, 0xf1, 0x16, 0x94, 0x67, 0xad, 0x04, 0xb6, 0x80 }, - { 0x21, 0x3b, 0x83, 0x8f, 0xe2, 0xae, 0x54, 0xc3, 0x8e, 0xe7, 0x18, 0x00 }, - { 0x5d, 0x92, 0x6b, 0x6d, 0xd7, 0x1f, 0x08, 0x51, 0x81, 0xa4, 0xe1, 0x20 }, - { 0x66, 0xab, 0x79, 0xd4, 0xb2, 0x9e, 0xe6, 0xe6, 0x95, 0x09, 0xe5, 0x60 }, - { 0x95, 0x81, 0x48, 0x68, 0x2d, 0x74, 0x8a, 0x38, 0xdd, 0x68, 0xba, 0xa0 }, - { 0xb8, 0xce, 0x02, 0x0c, 0xf0, 0x69, 0xc3, 0x2a, 0x72, 0x3a, 0xb1, 0x40 }, - { 0xf4, 0x33, 0x1d, 0x6d, 0x46, 0x16, 0x07, 0xe9, 0x57, 0x52, 0x74, 0x60 }, - { 0x6d, 0xa2, 0x3b, 0xa4, 0x24, 0xb9, 0x59, 0x61, 0x33, 0xcf, 0x9c, 0x80 }, - { 0xa6, 0x36, 0xbc, 0xbc, 0x7b, 0x30, 0xc5, 0xfb, 0xea, 0xe6, 0x7f, 0xe0 }, - { 0x5c, 0xb0, 0xd8, 0x6a, 0x07, 0xdf, 0x65, 0x4a, 0x90, 0x89, 0xa2, 0x00 }, - { 0xf1, 0x1f, 0x10, 0x68, 0x48, 0x78, 0x0f, 0xc9, 0xec, 0xdd, 0x80, 0xa0 }, - { 0x1f, 0xbb, 0x53, 0x64, 0xfb, 0x8d, 0x2c, 0x9d, 0x73, 0x0d, 0x5b, 0xa0 }, - { 0xfc, 0xb8, 0x6b, 0xc7, 0x0a, 0x50, 0xc9, 0xd0, 0x2a, 0x5d, 0x03, 0x40 }, - { 0xa5, 0x34, 0x43, 0x30, 0x29, 0xea, 0xc1, 0x5f, 0x32, 0x2e, 0x34, 0xc0 }, - { 0xc9, 0x89, 0xd9, 0xc7, 0xc3, 0xd3, 0xb8, 0xc5, 0x5d, 0x75, 0x13, 0x00 }, - { 0x7b, 0xb3, 0x8b, 0x2f, 0x01, 0x86, 0xd4, 0x66, 0x43, 0xae, 0x96, 0x20 }, - { 0x26, 0x44, 0xeb, 0xad, 0xeb, 0x44, 0xb9, 0x46, 0x7d, 0x1f, 0x42, 0xc0 }, - { 0x60, 0x8c, 0xc8, 0x57, 0x59, 0x4b, 0xfb, 0xb5, 0x5d, 0x69, 0x60, 0x00 } -}; - -// Each row describes one LDPC parity check. -// Each number is an index into the codeword (1-origin). -// The codeword bits mentioned in each row must XOR to zero. -const uint8_t kFTX_LDPC_Nm[FTX_LDPC_M][7] = { - { 4, 31, 59, 91, 92, 96, 153 }, - { 5, 32, 60, 93, 115, 146, 0 }, - { 6, 24, 61, 94, 122, 151, 0 }, - { 7, 33, 62, 95, 96, 143, 0 }, - { 8, 25, 63, 83, 93, 96, 148 }, - { 6, 32, 64, 97, 126, 138, 0 }, - { 5, 34, 65, 78, 98, 107, 154 }, - { 9, 35, 66, 99, 139, 146, 0 }, - { 10, 36, 67, 100, 107, 126, 0 }, - { 11, 37, 67, 87, 101, 139, 158 }, - { 12, 38, 68, 102, 105, 155, 0 }, - { 13, 39, 69, 103, 149, 162, 0 }, - { 8, 40, 70, 82, 104, 114, 145 }, - { 14, 41, 71, 88, 102, 123, 156 }, - { 15, 42, 59, 106, 123, 159, 0 }, - { 1, 33, 72, 106, 107, 157, 0 }, - { 16, 43, 73, 108, 141, 160, 0 }, - { 17, 37, 74, 81, 109, 131, 154 }, - { 11, 44, 75, 110, 121, 166, 0 }, - { 45, 55, 64, 111, 130, 161, 173 }, - { 8, 46, 71, 112, 119, 166, 0 }, - { 18, 36, 76, 89, 113, 114, 143 }, - { 19, 38, 77, 104, 116, 163, 0 }, - { 20, 47, 70, 92, 138, 165, 0 }, - { 2, 48, 74, 113, 128, 160, 0 }, - { 21, 45, 78, 83, 117, 121, 151 }, - { 22, 47, 58, 118, 127, 164, 0 }, - { 16, 39, 62, 112, 134, 158, 0 }, - { 23, 43, 79, 120, 131, 145, 0 }, - { 19, 35, 59, 73, 110, 125, 161 }, - { 20, 36, 63, 94, 136, 161, 0 }, - { 14, 31, 79, 98, 132, 164, 0 }, - { 3, 44, 80, 124, 127, 169, 0 }, - { 19, 46, 81, 117, 135, 167, 0 }, - { 7, 49, 58, 90, 100, 105, 168 }, - { 12, 50, 61, 118, 119, 144, 0 }, - { 13, 51, 64, 114, 118, 157, 0 }, - { 24, 52, 76, 129, 148, 149, 0 }, - { 25, 53, 69, 90, 101, 130, 156 }, - { 20, 46, 65, 80, 120, 140, 170 }, - { 21, 54, 77, 100, 140, 171, 0 }, - { 35, 82, 133, 142, 171, 174, 0 }, - { 14, 30, 83, 113, 125, 170, 0 }, - { 4, 29, 68, 120, 134, 173, 0 }, - { 1, 4, 52, 57, 86, 136, 152 }, - { 26, 51, 56, 91, 122, 137, 168 }, - { 52, 84, 110, 115, 145, 168, 0 }, - { 7, 50, 81, 99, 132, 173, 0 }, - { 23, 55, 67, 95, 172, 174, 0 }, - { 26, 41, 77, 109, 141, 148, 0 }, - { 2, 27, 41, 61, 62, 115, 133 }, - { 27, 40, 56, 124, 125, 126, 0 }, - { 18, 49, 55, 124, 141, 167, 0 }, - { 6, 33, 85, 108, 116, 156, 0 }, - { 28, 48, 70, 85, 105, 129, 158 }, - { 9, 54, 63, 131, 147, 155, 0 }, - { 22, 53, 68, 109, 121, 174, 0 }, - { 3, 13, 48, 78, 95, 123, 0 }, - { 31, 69, 133, 150, 155, 169, 0 }, - { 12, 43, 66, 89, 97, 135, 159 }, - { 5, 39, 75, 102, 136, 167, 0 }, - { 2, 54, 86, 101, 135, 164, 0 }, - { 15, 56, 87, 108, 119, 171, 0 }, - { 10, 44, 82, 91, 111, 144, 149 }, - { 23, 34, 71, 94, 127, 153, 0 }, - { 11, 49, 88, 92, 142, 157, 0 }, - { 29, 34, 87, 97, 147, 162, 0 }, - { 30, 50, 60, 86, 137, 142, 162 }, - { 10, 53, 66, 84, 112, 128, 165 }, - { 22, 57, 85, 93, 140, 159, 0 }, - { 28, 32, 72, 103, 132, 166, 0 }, - { 28, 29, 84, 88, 117, 143, 150 }, - { 1, 26, 45, 80, 128, 147, 0 }, - { 17, 27, 89, 103, 116, 153, 0 }, - { 51, 57, 98, 163, 165, 172, 0 }, - { 21, 37, 73, 138, 152, 169, 0 }, - { 16, 47, 76, 130, 137, 154, 0 }, - { 3, 24, 30, 72, 104, 139, 0 }, - { 9, 40, 90, 106, 134, 151, 0 }, - { 15, 58, 60, 74, 111, 150, 163 }, - { 18, 42, 79, 144, 146, 152, 0 }, - { 25, 38, 65, 99, 122, 160, 0 }, - { 17, 42, 75, 129, 170, 172, 0 } -}; - -// Each row corresponds to a codeword bit. -// The numbers indicate which three LDPC parity checks (rows in Nm) refer to the codeword bit. -// 1-origin. -const uint8_t kFTX_LDPC_Mn[FTX_LDPC_N][3] = { - { 16, 45, 73 }, - { 25, 51, 62 }, - { 33, 58, 78 }, - { 1, 44, 45 }, - { 2, 7, 61 }, - { 3, 6, 54 }, - { 4, 35, 48 }, - { 5, 13, 21 }, - { 8, 56, 79 }, - { 9, 64, 69 }, - { 10, 19, 66 }, - { 11, 36, 60 }, - { 12, 37, 58 }, - { 14, 32, 43 }, - { 15, 63, 80 }, - { 17, 28, 77 }, - { 18, 74, 83 }, - { 22, 53, 81 }, - { 23, 30, 34 }, - { 24, 31, 40 }, - { 26, 41, 76 }, - { 27, 57, 70 }, - { 29, 49, 65 }, - { 3, 38, 78 }, - { 5, 39, 82 }, - { 46, 50, 73 }, - { 51, 52, 74 }, - { 55, 71, 72 }, - { 44, 67, 72 }, - { 43, 68, 78 }, - { 1, 32, 59 }, - { 2, 6, 71 }, - { 4, 16, 54 }, - { 7, 65, 67 }, - { 8, 30, 42 }, - { 9, 22, 31 }, - { 10, 18, 76 }, - { 11, 23, 82 }, - { 12, 28, 61 }, - { 13, 52, 79 }, - { 14, 50, 51 }, - { 15, 81, 83 }, - { 17, 29, 60 }, - { 19, 33, 64 }, - { 20, 26, 73 }, - { 21, 34, 40 }, - { 24, 27, 77 }, - { 25, 55, 58 }, - { 35, 53, 66 }, - { 36, 48, 68 }, - { 37, 46, 75 }, - { 38, 45, 47 }, - { 39, 57, 69 }, - { 41, 56, 62 }, - { 20, 49, 53 }, - { 46, 52, 63 }, - { 45, 70, 75 }, - { 27, 35, 80 }, - { 1, 15, 30 }, - { 2, 68, 80 }, - { 3, 36, 51 }, - { 4, 28, 51 }, - { 5, 31, 56 }, - { 6, 20, 37 }, - { 7, 40, 82 }, - { 8, 60, 69 }, - { 9, 10, 49 }, - { 11, 44, 57 }, - { 12, 39, 59 }, - { 13, 24, 55 }, - { 14, 21, 65 }, - { 16, 71, 78 }, - { 17, 30, 76 }, - { 18, 25, 80 }, - { 19, 61, 83 }, - { 22, 38, 77 }, - { 23, 41, 50 }, - { 7, 26, 58 }, - { 29, 32, 81 }, - { 33, 40, 73 }, - { 18, 34, 48 }, - { 13, 42, 64 }, - { 5, 26, 43 }, - { 47, 69, 72 }, - { 54, 55, 70 }, - { 45, 62, 68 }, - { 10, 63, 67 }, - { 14, 66, 72 }, - { 22, 60, 74 }, - { 35, 39, 79 }, - { 1, 46, 64 }, - { 1, 24, 66 }, - { 2, 5, 70 }, - { 3, 31, 65 }, - { 4, 49, 58 }, - { 1, 4, 5 }, - { 6, 60, 67 }, - { 7, 32, 75 }, - { 8, 48, 82 }, - { 9, 35, 41 }, - { 10, 39, 62 }, - { 11, 14, 61 }, - { 12, 71, 74 }, - { 13, 23, 78 }, - { 11, 35, 55 }, - { 15, 16, 79 }, - { 7, 9, 16 }, - { 17, 54, 63 }, - { 18, 50, 57 }, - { 19, 30, 47 }, - { 20, 64, 80 }, - { 21, 28, 69 }, - { 22, 25, 43 }, - { 13, 22, 37 }, - { 2, 47, 51 }, - { 23, 54, 74 }, - { 26, 34, 72 }, - { 27, 36, 37 }, - { 21, 36, 63 }, - { 29, 40, 44 }, - { 19, 26, 57 }, - { 3, 46, 82 }, - { 14, 15, 58 }, - { 33, 52, 53 }, - { 30, 43, 52 }, - { 6, 9, 52 }, - { 27, 33, 65 }, - { 25, 69, 73 }, - { 38, 55, 83 }, - { 20, 39, 77 }, - { 18, 29, 56 }, - { 32, 48, 71 }, - { 42, 51, 59 }, - { 28, 44, 79 }, - { 34, 60, 62 }, - { 31, 45, 61 }, - { 46, 68, 77 }, - { 6, 24, 76 }, - { 8, 10, 78 }, - { 40, 41, 70 }, - { 17, 50, 53 }, - { 42, 66, 68 }, - { 4, 22, 72 }, - { 36, 64, 81 }, - { 13, 29, 47 }, - { 2, 8, 81 }, - { 56, 67, 73 }, - { 5, 38, 50 }, - { 12, 38, 64 }, - { 59, 72, 80 }, - { 3, 26, 79 }, - { 45, 76, 81 }, - { 1, 65, 74 }, - { 7, 18, 77 }, - { 11, 56, 59 }, - { 14, 39, 54 }, - { 16, 37, 66 }, - { 10, 28, 55 }, - { 15, 60, 70 }, - { 17, 25, 82 }, - { 20, 30, 31 }, - { 12, 67, 68 }, - { 23, 75, 80 }, - { 27, 32, 62 }, - { 24, 69, 75 }, - { 19, 21, 71 }, - { 34, 53, 61 }, - { 35, 46, 47 }, - { 33, 59, 76 }, - { 40, 43, 83 }, - { 41, 42, 63 }, - { 49, 75, 83 }, - { 20, 44, 48 }, - { 42, 49, 57 } -}; - -const uint8_t kFTX_LDPCNumRows[FTX_LDPC_M] = { - 7, 6, 6, 6, 7, 6, 7, 6, 6, 7, 6, 6, 7, 7, 6, 6, - 6, 7, 6, 7, 6, 7, 6, 6, 6, 7, 6, 6, 6, 7, 6, 6, - 6, 6, 7, 6, 6, 6, 7, 7, 6, 6, 6, 6, 7, 7, 6, 6, - 6, 6, 7, 6, 6, 6, 7, 6, 6, 6, 6, 7, 6, 6, 6, 7, - 6, 6, 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 7, - 6, 6, 6 -}; \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/constants.h b/ft8CN/app/src/main/cpp/ft8/constants.h deleted file mode 100644 index a97dd50..0000000 --- a/ft8CN/app/src/main/cpp/ft8/constants.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef _INCLUDE_CONSTANTS_H_ -#define _INCLUDE_CONSTANTS_H_ - -#include -#include - -typedef enum -{ - PROTO_FT4, - PROTO_FT8 -} ftx_protocol_t; -#define kMin_score (10) /// 候选人的最低同步分数阈值。Minimum sync score threshold for candidates -#define FT8_SAMPLE_RATE (12000)//采样率 -#define FT8_SYMBOL_PERIOD (0.160f) ///< FT8 symbol duration, defines tone deviation in Hz and symbol rate -#define FT8_SLOT_TIME (15.0f) ///< FT8 slot period - -#define FT4_SYMBOL_PERIOD (0.048f) ///< FT4 symbol duration, defines tone deviation in Hz and symbol rate -#define FT4_SLOT_TIME (7.5f) ///< FT4 slot period - -// Define FT8 symbol counts -// FT8 message structure: -// S D1 S D2 S -// S - sync block (7 symbols of Costas pattern) -// D1 - first data block (29 symbols each encoding 3 bits) -#define FT8_ND (58) ///< Data symbols -#define FT8_NN (79) ///< Total channel symbols (FT8_NS + FT8_ND) -#define FT8_LENGTH_SYNC (7) ///< Length of each sync group -#define FT8_NUM_SYNC (3) ///< Number of sync groups -#define FT8_SYNC_OFFSET (36) ///< Offset between sync groups -#define FT8_SYMBOL_BT (2.0f) - -// Define FT4 symbol counts -// FT4 message structure: -// R Sa D1 Sb D2 Sc D3 Sd R -// R - ramping symbol (no payload information conveyed) -// Sx - one of four _different_ sync blocks (4 symbols of Costas pattern) -// Dy - data block (29 symbols each encoding 2 bits) -#define FT4_ND (87) ///< Data symbols -#define FT4_NR (2) ///< Ramp symbols (beginning + end) -#define FT4_NN (105) ///< Total channel symbols (FT4_NS + FT4_ND + FT4_NR) -#define FT4_LENGTH_SYNC (4) ///< Length of each sync group -#define FT4_NUM_SYNC (4) ///< Number of sync groups -#define FT4_SYNC_OFFSET (33) ///< Offset between sync groups - -// Define LDPC parameters -#define FTX_LDPC_N (174) ///编码消息中的位数(LDPC校验和位的有效负载)< Number of bits in the encoded message (payload with LDPC checksum bits) -#define FTX_LDPC_K (91) ///< 有效负载位数(包括CRC)Number of payload bits (including CRC) -#define FTX_LDPC_M (83) ///< Number of LDPC checksum bits (FTX_LDPC_N - FTX_LDPC_K) -#define FTX_LDPC_N_BYTES ((FTX_LDPC_N + 7) / 8) ///< Number of whole bytes needed to store 174 bits (full message) -#define FTX_LDPC_K_BYTES ((FTX_LDPC_K + 7) / 8) ///< 存储91位所需的整字节数(仅限有效负载+CRC)Number of whole bytes needed to store 91 bits (payload + CRC only) - -// Define CRC parameters -#define FT8_CRC_POLYNOMIAL ((uint16_t)0x2757u) ///< CRC-14 polynomial without the leading (MSB) 1 -#define FT8_CRC_WIDTH (14) - -#define DECODE_TIME_OUT (1) ///解码迭代时间超时(秒) - -/// Costas 7x7 tone pattern for synchronization -extern const uint8_t kFT8CostasPattern[7]; -extern const uint8_t kFT4CostasPattern[4][4]; - -/// Gray code map to encode 8 symbols (tones) -extern const uint8_t kFT8GrayMap[8]; -extern const uint8_t kFT4GrayMap[4]; - -extern const uint8_t kFT4XORSequence[10]; - -/// Parity generator matrix for (174,91) LDPC code, stored in bitpacked format (MSB first) -extern const uint8_t kFTXLDPCGenerator[FTX_LDPC_M][FTX_LDPC_K_BYTES]; - -/// LDPC(174,91) parity check matrix, containing 83 rows, -/// each row describes one parity check, -/// each number is an index into the codeword (1-origin). -/// The codeword bits mentioned in each row must xor to zero. -/// From WSJT-X's ldpc_174_91_c_reordered_parity.f90. -extern const uint8_t kFTX_LDPC_Nm[FTX_LDPC_M][7]; - -/// Mn from WSJT-X's bpdecode174.f90. Each row corresponds to a codeword bit. -/// The numbers indicate which three parity checks (rows in Nm) refer to the codeword bit. -/// The numbers use 1 as the origin (first entry). -extern const uint8_t kFTX_LDPC_Mn[FTX_LDPC_N][3]; - -/// Number of rows (columns in C/C++) in the array Nm. -extern const uint8_t kFTX_LDPCNumRows[FTX_LDPC_M]; - -#endif // _INCLUDE_CONSTANTS_H_ - - - diff --git a/ft8CN/app/src/main/cpp/ft8/crc.c b/ft8CN/app/src/main/cpp/ft8/crc.c deleted file mode 100644 index 72a4c89..0000000 --- a/ft8CN/app/src/main/cpp/ft8/crc.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "crc.h" -#include "constants.h" - -#define TOPBIT (1u << (FT8_CRC_WIDTH - 1)) - -// Compute 14-bit CRC for a sequence of given number of bits -// Adapted from https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code -// [IN] message - byte sequence (MSB first) -// [IN] num_bits - number of bits in the sequence -uint16_t ftx_compute_crc(const uint8_t message[], int num_bits) -{ - uint16_t remainder = 0; - int idx_byte = 0; - - // Perform modulo-2 division, a bit at a time. - for (int idx_bit = 0; idx_bit < num_bits; ++idx_bit) - { - if (idx_bit % 8 == 0) - { - // Bring the next byte into the remainder. - remainder ^= (message[idx_byte] << (FT8_CRC_WIDTH - 8)); - ++idx_byte; - } - - // Try to divide the current data bit. - if (remainder & TOPBIT) - { - remainder = (remainder << 1) ^ FT8_CRC_POLYNOMIAL; - } - else - { - remainder = (remainder << 1); - } - } - - return remainder & ((TOPBIT << 1) - 1u); -} - -uint16_t ftx_extract_crc(const uint8_t a91[]) -{ - uint16_t chksum = ((a91[9] & 0x07) << 11) | (a91[10] << 3) | (a91[11] >> 5); - return chksum; -} - -void ftx_add_crc(const uint8_t payload[], uint8_t a91[]) -{ - // Copy 77 bits of payload data - for (int i = 0; i < 10; i++) - a91[i] = payload[i]; - - // Clear 3 bits after the payload to make 82 bits - a91[9] &= 0xF8u; - a91[10] = 0; - - // Calculate CRC of 82 bits (77 + 5 zeros) - // 'The CRC is calculated on the source-encoded message, zero-extended from 77 to 82 bits' - uint16_t checksum = ftx_compute_crc(a91, 96 - 14); - - // Store the CRC at the end of 77 bit message - a91[9] |= (uint8_t)(checksum >> 11); - a91[10] = (uint8_t)(checksum >> 3); - a91[11] = (uint8_t)(checksum << 5); -} diff --git a/ft8CN/app/src/main/cpp/ft8/crc.h b/ft8CN/app/src/main/cpp/ft8/crc.h deleted file mode 100644 index 99db708..0000000 --- a/ft8CN/app/src/main/cpp/ft8/crc.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _INCLUDE_CRC_H_ -#define _INCLUDE_CRC_H_ - -#include -#include - -// Compute 14-bit CRC for a sequence of given number of bits using FT8/FT4 CRC polynomial -// [IN] message - byte sequence (MSB first) -// [IN] num_bits - number of bits in the sequence -uint16_t ftx_compute_crc(const uint8_t message[], int num_bits); - -/// Extract the FT8/FT4 CRC of a packed message (during decoding) -/// 提取压缩消息的FT8/FT4 CRC(解码期间) -/// @param[in] a91 77 bits of payload data + CRC -/// @return Extracted CRC -uint16_t ftx_extract_crc(const uint8_t a91[]); - -/// Add FT8/FT4 CRC to a packed message (during encoding) -/// @param[in] payload 77 bits of payload data -/// @param[out] a91 91 bits of payload data + CRC -void ftx_add_crc(const uint8_t payload[], uint8_t a91[]); - -#endif // _INCLUDE_CRC_H_ \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/decode.c b/ft8CN/app/src/main/cpp/ft8/decode.c deleted file mode 100644 index a5e69bb..0000000 --- a/ft8CN/app/src/main/cpp/ft8/decode.c +++ /dev/null @@ -1,628 +0,0 @@ -#include "decode.h" -#include "constants.h" -#include "crc.h" -#include "ldpc.h" -#include "unpack.h" - -#include -#include -#include "../common/debug.h" -#include "hash22.h" - -/// Compute log likelihood log(p(1) / p(0)) of 174 message bits for later use in soft-decision LDPC decoding -/// @param[in] wf Waterfall data collected during message slot -/// @param[in] cand Candidate to extract the message from -/// @param[in] code_map Symbol encoding map -/// @param[out] log174 Output of decoded log likelihoods for each of the 174 message bits -static void ft4_extract_likelihood(const waterfall_t *wf, const candidate_t *cand, float *log174); - -static void ft8_extract_likelihood(const waterfall_t *wf, candidate_t *cand, float *log174); - -/// Packs a string of bits each represented as a zero/non-zero byte in bit_array[], -/// as a string of packed bits starting from the MSB of the first byte of packed[] -/// @param[in] plain Array of bits (0 and nonzero values) with num_bits entires -/// @param[in] num_bits Number of bits (entries) passed in bit_array -/// @param[out] packed Byte-packed bits representing the data in bit_array -static void pack_bits(const uint8_t bit_array[], int num_bits, uint8_t packed[]); - -static float max2(float a, float b); - -static float max4(float a, float b, float c, float d); - -static void heapify_down(candidate_t heap[], int heap_size); - -static void heapify_up(candidate_t heap[], int heap_size); - -static void ftx_normalize_logl(float *log174); - -static void ft4_extract_symbol(const uint8_t *wf, float *logl); - -static void ft8_extract_symbol(const uint8_t *wf, float *logl); - -static void -ft8_decode_multi_symbols(const uint8_t *wf, int num_bins, int n_syms, int bit_idx, float *log174); - -static int get_index(const waterfall_t *wf, const candidate_t *candidate) { - int offset = candidate->time_offset;//time_offset:-12 ~ 23,(costas阵列7个符号+29个数据符号=36) - offset = (offset * wf->time_osr) + candidate->time_sub;//time_sub:0~1 - offset = (offset * wf->freq_osr) + candidate->freq_sub;//freq_sub:0~1 - offset = (offset * wf->num_bins) + - candidate->freq_offset;//num_bins:960,freq_offset:0~ 960(-1) -7 - return offset; -} - - -static int ft8_sync_score(const waterfall_t *wf, candidate_t *candidate) { - /* - * ft8本应有58个符号,但在开始(0-7)、中间(36-43)、结尾(72-79)加了科斯塔阵列,所以共有79个符号, - *此函数在4层循环中执行。时间采样率2*频率采样率2*时间偏移(-12~24=36)*频率偏移(num_bins:960-7) - */ - int score = 0; - int num_average = 0; - - float signal = 0; - float noise = 0; - - // Get the pointer to symbol 0 of the candidate - //获取指向候选符号0的指针,在mag数组中取candidate对应的mag数据。 - const uint8_t *mag_cand = wf->mag + get_index(wf, candidate); - //用于信号量和噪音的计算,暂时注释掉 - // const float *mag_signal = wf->mag2 + get_index(wf, candidate); - - - // Compute average score over sync symbols (m+k = 0-7, 36-43, 72-79) - //计算同步符号的平均分数(m+k=0-7、36-43、72-79) - //m=0~2(3组),k=0~6(7个符号) - for (int m = 0; m < FT8_NUM_SYNC; ++m) { - for (int k = 0; k < FT8_LENGTH_SYNC; ++k) { - //FT8_SYNC_OFFSET=36,block=0..6,36~43,72~79,这是costas阵列在符号序列中的索引 - int block = (FT8_SYNC_OFFSET * m) + k; // 相对于消息relative to the message - int block_abs = - //time_offset=-12.。23(36个) - candidate->time_offset + block; // 相对于捕获的信号relative to the captured signal - // Check for time boundaries - //检查时间界限 - if (block_abs < 0) - continue; - if (block_abs >= wf->num_blocks) - break; - - // Get the pointer to symbol 'block' of the candidate - //获取指向候选人符号“block”的指针 - const uint8_t *p8 = mag_cand + (block * wf->block_stride); - - // Weighted difference between the expected and all other symbols - //预期符号和所有其他符号之间的加权差 - // Does not work as well as the alternative score below - //效果不如下面的备选分数 - // score += 8 * p8[kFT8CostasPattern[k]] - - // p8[0] - p8[1] - p8[2] - p8[3] - - // p8[4] - p8[5] - p8[6] - p8[7]; - // ++num_average; - - // Check only the neighbors of the expected symbol frequency- and time-wise - //仅检查预期符号频率和时间的相邻项,k=0..6 - int sm = kFT8CostasPattern[k]; //预期数据的索引 Index of the expected bin - - - //此处计算信号量和噪音,可能不正确,暂时注释掉 - // const float *p8Signal = mag_signal + (block * wf->block_stride); - - - - //通过sm判断相邻频率的信号量是否小于本位置的信号量,小于就加分 - if (sm > 0) { - // look at one frequency bin lower - //信号量的差值。 - score += p8[sm] - p8[sm - 1]; - ++num_average; - } - if (sm < 7) { - // look at one frequency bin higher - score += p8[sm] - p8[sm + 1]; - ++num_average; - } - //判断前后符号时间频率信号量是否小于本位置的信号量,小于就加分 - if ((k > 0) && (block_abs > 0)) { - // look one symbol back in time - score += p8[sm] - p8[sm - wf->block_stride]; - - ++num_average; - } - if (((k + 1) < FT8_LENGTH_SYNC) && ((block_abs + 1) < wf->num_blocks)) { - // look one symbol forward in time - score += p8[sm] - p8[sm + wf->block_stride]; - ++num_average; - } - } - } - - if (num_average > 0) { - score /= num_average; - } - - return score; -} - -static int ft4_sync_score(const waterfall_t *wf, const candidate_t *candidate) { - int score = 0; - int num_average = 0; - - // Get the pointer to symbol 0 of the candidate - const uint8_t *mag_cand = wf->mag + get_index(wf, candidate); - - // Compute average score over sync symbols (block = 1-4, 34-37, 67-70, 100-103) - for (int m = 0; m < FT4_NUM_SYNC; ++m) { - for (int k = 0; k < FT4_LENGTH_SYNC; ++k) { - int block = 1 + (FT4_SYNC_OFFSET * m) + k; - int block_abs = candidate->time_offset + block; - // Check for time boundaries - if (block_abs < 0) - continue; - if (block_abs >= wf->num_blocks) - break; - - // Get the pointer to symbol 'block' of the candidate - const uint8_t *p4 = mag_cand + (block * wf->block_stride); - - int sm = kFT4CostasPattern[m][k]; // Index of the expected bin - - // score += (4 * p4[sm]) - p4[0] - p4[1] - p4[2] - p4[3]; - // num_average += 4; - - // Check only the neighbors of the expected symbol frequency- and time-wise - if (sm > 0) { - // look at one frequency bin lower - score += p4[sm] - p4[sm - 1]; - ++num_average; - } - if (sm < 3) { - // look at one frequency bin higher - score += p4[sm] - p4[sm + 1]; - ++num_average; - } - if ((k > 0) && (block_abs > 0)) { - // look one symbol back in time - score += p4[sm] - p4[sm - wf->block_stride]; - ++num_average; - } - if (((k + 1) < FT4_LENGTH_SYNC) && ((block_abs + 1) < wf->num_blocks)) { - // look one symbol forward in time - score += p4[sm] - p4[sm + wf->block_stride]; - ++num_average; - } - } - } - - if (num_average > 0) - score /= num_average; - - return score; -} - -//检测ft8信号,num_candidates最大候选人数量=120,heap[]候选人列表(size=120),kMin_score候选人的最低同步分数阈值=10 -int ft8_find_sync(const waterfall_t *wf, int num_candidates, candidate_t heap[], int min_score) { - int heap_size = 0; - candidate_t candidate;//候选人 - // Here we allow time offsets that exceed signal boundaries, as long as we still have all data bits. - // I.e. we can afford to skip the first 7 or the last 7 Costas symbols, as long as we track how many - // sync symbols we included in the score, so the score is averaged. - //在这里,我们允许超过信号边界的时间偏移,只要我们仍然拥有所有数据位。 - //也就是说,我们可以跳过前7个或最后7个Costas符号,只要我们跟踪有多少个 - //我们在分数中包含了同步符号,所以分数是平均值。 - //循环:时间过采样*频率过采样*前36个符号(7同步+29信息)*fft频率偏移=2*2*36*960=3840*36=138240 - for (candidate.time_sub = 0; candidate.time_sub < wf->time_osr; ++candidate.time_sub) { - for (candidate.freq_sub = 0; candidate.freq_sub < wf->freq_osr; ++candidate.freq_sub) { - for (candidate.time_offset = -12; candidate.time_offset < 24; ++candidate.time_offset) { - for (candidate.freq_offset = 0; - (candidate.freq_offset + 7) < wf->num_bins; ++candidate.freq_offset) { - if (wf->protocol == PROTO_FT4) { - candidate.score = ft4_sync_score(wf, &candidate); - } else { - candidate.score = ft8_sync_score(wf, &candidate); - } - - if (candidate.score < min_score) - continue; - - // If the heap is full AND the current candidate is better than - // the worst in the heap, we remove the worst and make space - //如果堆已满且当前候选堆优于在堆中最坏的,我们移除最坏的,并创造空间 - if (heap_size == num_candidates && candidate.score > heap[0].score) { - heap[0] = heap[heap_size - 1]; - --heap_size; - //降序? - heapify_down(heap, heap_size); - } - - // If there's free space in the heap, we add the current candidate - //如果堆中有可用空间,我们将添加当前候选堆 - if (heap_size < num_candidates) { - heap[heap_size] = candidate; - ++heap_size; - //升序? - heapify_up(heap, heap_size); - } - } - } - } - } - - - - // Sort the candidates by sync strength - here we benefit from the heap structure - int len_unsorted = heap_size; - while (len_unsorted > 1) { - candidate_t tmp = heap[len_unsorted - 1]; - heap[len_unsorted - 1] = heap[0]; - heap[0] = tmp; - len_unsorted--; - heapify_down(heap, len_unsorted); - } - - return heap_size; -} - -static void ft4_extract_likelihood(const waterfall_t *wf, const candidate_t *cand, float *log174) { - const uint8_t *mag_cand = wf->mag + get_index(wf, cand); - - // Go over FSK tones and skip Costas sync symbols - for (int k = 0; k < FT4_ND; ++k) { - // Skip either 5, 9 or 13 sync symbols - // TODO: replace magic numbers with constants - int sym_idx = k + ((k < 29) ? 5 : ((k < 58) ? 9 : 13)); - int bit_idx = 2 * k; - - // Check for time boundaries - int block = cand->time_offset + sym_idx; - if ((block < 0) || (block >= wf->num_blocks)) { - log174[bit_idx + 0] = 0; - log174[bit_idx + 1] = 0; - } else { - // Pointer to 4 bins of the current symbol - const uint8_t *ps = mag_cand + (sym_idx * wf->block_stride); - - ft4_extract_symbol(ps, log174 + bit_idx); - } - } -} - -//解开可能的FT8信号 -static void ft8_extract_likelihood(const waterfall_t *wf, candidate_t *cand, float *log174) { - const uint8_t *mag_cand = wf->mag + get_index(wf, cand); - - ////FT8总消息的为174位,符号是174/3=58个,加上同步costas阵列的7*3=21个符号,共计58+21=79个符号。 - //log174数组的大小是174 - // Go over FSK tones and skip Costas sync symbols - //浏览FSK音调并跳过Costas同步符号,所以log174 - //FT8_ND=58,k=0..57 - for (int k = 0; k < FT8_ND; ++k) { - // Skip either 7 or 14 sync symbols - // TODO: replace magic numbers with constants - //sym_idx=7..35,43..71 - int sym_idx = k + ((k < 29) ? 7 : 14); - //bit_idx符号位的索引 - int bit_idx = 3 * k; - - // Check for time boundaries - //检测时间边界 - int block = cand->time_offset + sym_idx; - if ((block < 0) || (block >= wf->num_blocks)) { - log174[bit_idx + 0] = 0; - log174[bit_idx + 1] = 0; - log174[bit_idx + 2] = 0; - } else { - // Pointer to 8 bins of the current symbol - //指向当前符号信号量的8个箱子的指针 - //block_stride=960*2*2=3840 - const uint8_t *ps = mag_cand + (sym_idx * wf->block_stride); - - //每个符号,bit_idx是符号的3倍 - ft8_extract_symbol(ps, log174 + bit_idx); - } - } -} - -static void ftx_normalize_logl(float *log174) { - // Compute the variance of log174 - //计算log174的方差 - float sum = 0; - float sum2 = 0; - //FTX_LDPC_N=174 - for (int i = 0; i < FTX_LDPC_N; ++i) { - sum += log174[i];//取和 - sum2 += log174[i] * log174[i];//取平方和 - } - float inv_n = 1.0f / FTX_LDPC_N; - //variance方差 - float variance = (sum2 - (sum * sum * inv_n)) * inv_n; - - // Normalize log174 distribution and scale it with experimentally found coefficient - ////规范化log174分布,并用实验发现的系数对其进行缩放 - float norm_factor = sqrtf(24.0f / variance); - for (int i = 0; i < FTX_LDPC_N; ++i) { - log174[i] *= norm_factor; - } -} - -//推算snr -static void ft8_guess_snr(const waterfall_t *wf, candidate_t *cand) { - const float *mag_signal = wf->mag2 + get_index(wf, cand); - - - float signal = 0, noise = 0; - for (int i = 0; i < 7; ++i) { - if ((cand->time_offset + i >= 0) && (cand->time_offset + i < wf->num_blocks + 8)) { - //LOG_PRINTF("End guess SNR 0..."); - signal += mag_signal[(i) * wf->block_stride + kFT8CostasPattern[i]]; - noise += mag_signal[(i) * wf->block_stride + ((kFT8CostasPattern[i] + 4) % 8)]; - //LOG_PRINTF("End guess SNR 0... done"); - } - if ((cand->time_offset + i + 36 >= 0) && (cand->time_offset + i < wf->num_blocks + 8)) { - //LOG_PRINTF("End guess SNR 36..."); - signal += mag_signal[(i + 36) * wf->block_stride + kFT8CostasPattern[i]]; - noise += mag_signal[(i + 36) * wf->block_stride + ((kFT8CostasPattern[i] + 4) % 8)]; - //LOG_PRINTF("End guess SNR 36... done"); - } - //此处容易产生数组下标越界的问题 -// if ((cand->time_offset+i+72>=0)&&(cand->time_offset+inum_blocks+8)) { -// LOG_PRINTF("End guess SNR 72..."); -// signal += mag_signal[(i + 72) * wf->block_stride + kFT8CostasPattern[i]]; -// noise += mag_signal[(i + 72) * wf->block_stride + ((kFT8CostasPattern[i] + 4) % 8)]; -// LOG_PRINTF("End guess SNR 72... done"); -// } - } - //LOG(LOG_INFO, "Max magnitude:ft8_guess_snr 002\n"); - if (noise != 0) { - float raw = signal / noise; - cand->snr = floor(10 * log10f(1E-12f + raw) - 24 + 0.5); - if (cand->snr < -30) {//-30是最小值了。 - cand->snr = -30; - } - } else { - cand->snr = -100; - } -} - -//max_iterations=20 LDPC的迭代次数。 -bool -ft8_decode(waterfall_t *wf, candidate_t *cand, message_t *message, int max_iterations, - decode_status_t *status) { - //FT8总消息的为174位,符号是174/3=58个,加上同步costas阵列的7*3=21个符号,共计58+21=79个符号。 - //FTX_LDPC_N=174,是把7*3个符号的位去掉后的数组, - float log174[FTX_LDPC_N]; //编码为似然的消息位 message bits encoded as likelihood - if (wf->protocol == PROTO_FT4) { - ft4_extract_likelihood(wf, cand, log174); - } else { - //检测可能的FT8信号,结果在log174中,每3个为一组,与8个格雷码为索引的信号量的平方差的值 - ft8_extract_likelihood(wf, cand, log174); - } - - //规范化 - ftx_normalize_logl(log174); - - //FTX_LDPC_N=174 - uint8_t plain174[FTX_LDPC_N]; // message bits (0/1) - - //bp_decode是原作者采用的,ldpc_decode经测试也是可以用的。 - //结果在plain174中,以0和1为值。包括77位信息+14位冗余校验+83位前向纠错=174位。 - //max_iterations是最大迭代次数,越大速度越慢,精度越高 - bp_decode(log174, max_iterations, plain174, &status->ldpc_errors); - //ldpc_decode(log174, max_iterations, plain174, &status->ldpc_errors); - - if (status->ldpc_errors > 0) { - return false; - } - - // Extract payload + CRC (first FTX_LDPC_K bits) packed into a byte array - ////提取压缩到字节数组中的有效负载+CRC(第一个FTX\U LDPC\U K位) - ////FTX_LDPC_K_BYTES:存储91位所需的整字节数(仅限有效负载+CRC) - ////FTX_LDPC_K有效负载位数(包括CRC) - uint8_t a91[FTX_LDPC_K_BYTES]; - //提取出91个位,77位信息+14位冗余校验 - pack_bits(plain174, FTX_LDPC_K, a91); - - // Extract CRC and check it - ////提取CRC并进行检查,后面crc_extracted又作为hash值保存下来 - status->crc_extracted = ftx_extract_crc(a91); - - // [1]: 'The CRC is calculated on the source-encoded message, zero-extended from 77 to 82 bits.' - a91[9] &= 0xF8; - a91[10] &= 0x00; - status->crc_calculated = ftx_compute_crc(a91, 96 - 14); - - if (status->crc_extracted != status->crc_calculated) { - return false; - } - - if (wf->protocol == PROTO_FT4) { - // '[..] for FT4 only, in order to avoid transmitting a long string of zeros when sending CQ messages, - // the assembled 77-bit message is bitwise exclusive-OR’ed with [a] pseudorandom sequence before computing the CRC and FEC parity bits' - for (int i = 0; i < 10; ++i) { - a91[i] ^= kFT4XORSequence[i]; - } - } - - //从91位解包77位信息,然后返回消息的文本内容。 - //status->unpack_status = unpack77(a91, message->text); - message->call_to[0] = message->call_de[0] = message->maidenGrid[0] = message->extra[0] = '\0'; - message->call_de_hash.hash10 = message->call_de_hash.hash12 = message->call_de_hash.hash22 = 0; - message->call_to_hash.hash10 = message->call_to_hash.hash12 = message->call_to_hash.hash22 = 0; - memcpy(message->a91, a91, FTX_LDPC_K_BYTES);//把数据包保存下来,用于音频相减 - - //LOG_PRINTF("hex:%0x %0x %0x %0x %0x %0x %0x %0x %0x %0x" - // ,a91[0],a91[1],a91[2],a91[3],a91[4],a91[5],a91[6],a91[7],a91[8],a91[9]); - - - status->unpack_status = unpackToMessage_t(a91, message); - //message->call_de_hash.hash12=hashcall(message->call_de,HASH_12) ; - - if (status->unpack_status < 0) { - return false; - } - - // Reuse binary message CRC as hash value for the message - //重用二进制消息CRC作为消息的哈希值 - message->hash = status->crc_extracted; - - - //2022-05-13增加解析i3,n3 - //解出i3和n3 - // Extract i3 (bits 74..76) - //message->i3 = (a91[9] >> 3) & 0x07; - // Extract n3 (bits 71..73) - //message->n3 = ((a91[8] << 2) & 0x04) | ((a91[9] >> 6) & 0x03); - //推算信噪比 - ft8_guess_snr(wf, cand); - - return true; -} - -static float max2(float a, float b) { - return (a >= b) ? a : b; -} - -static float max4(float a, float b, float c, float d) { - return max2(max2(a, b), max2(c, d)); -} - -static void heapify_down(candidate_t heap[], int heap_size) { - // heapify from the root down - int current = 0; - while (true) { - int largest = current; - int left = 2 * current + 1; - int right = left + 1; - - if (left < heap_size && heap[left].score < heap[largest].score) { - largest = left; - } - if (right < heap_size && heap[right].score < heap[largest].score) { - largest = right; - } - if (largest == current) { - break; - } - - candidate_t tmp = heap[largest]; - heap[largest] = heap[current]; - heap[current] = tmp; - current = largest; - } -} - -static void heapify_up(candidate_t heap[], int heap_size) { - // heapify from the last node up - int current = heap_size - 1; - while (current > 0) { - int parent = (current - 1) / 2; - if (heap[current].score >= heap[parent].score) { - break; - } - - candidate_t tmp = heap[parent]; - heap[parent] = heap[current]; - heap[current] = tmp; - current = parent; - } -} - -// Compute unnormalized log likelihood log(p(1) / p(0)) of 2 message bits (1 FSK symbol) -static void ft4_extract_symbol(const uint8_t *wf, float *logl) { - // Cleaned up code for the simple case of n_syms==1 - float s2[4]; - - for (int j = 0; j < 4; ++j) { - s2[j] = (float) wf[kFT4GrayMap[j]]; - } - - logl[0] = max2(s2[2], s2[3]) - max2(s2[0], s2[1]); - logl[1] = max2(s2[1], s2[3]) - max2(s2[0], s2[2]); -} - -// Compute unnormalized log likelihood log(p(1) / p(0)) of 3 message bits (1 FSK symbol) -//计算3个消息位(1个FSK符号)的非规范化对数似然对数log((p(1)/p(0)) -//wf当前符号的信号量的地址,logl当前符号的位数组的地址。 -static void ft8_extract_symbol(const uint8_t *wf, float *logl) { - // Cleaned up code for the simple case of n_syms==1 - //清理了n_syms==1简单案例的代码 - float s2[8];//信号强度数组,格雷码数组内容做偏移索引:{ 0, 1, 3, 2, 5, 6, 4, 7 } - - for (int j = 0; j < 8; ++j) { - s2[j] = (float) wf[kFT8GrayMap[j]];//格雷码值作索引,对应信号的强度保存到 - } - //信号量的值在之前已经是平方过的了,相减实际上是log(p(1)/p(0))。 - logl[0] = max4(s2[4], s2[5], s2[6], s2[7]) - max4(s2[0], s2[1], s2[2], s2[3]); - logl[1] = max4(s2[2], s2[3], s2[6], s2[7]) - max4(s2[0], s2[1], s2[4], s2[5]); - logl[2] = max4(s2[1], s2[3], s2[5], s2[7]) - max4(s2[0], s2[2], s2[4], s2[6]); -} - -// Compute unnormalized log likelihood log(p(1) / p(0)) of bits corresponding to several FSK symbols at once -static void -ft8_decode_multi_symbols(const uint8_t *wf, int num_bins, int n_syms, int bit_idx, float *log174) { - const int n_bits = 3 * n_syms; - const int n_tones = (1 << n_bits); - - float s2[n_tones]; - - for (int j = 0; j < n_tones; ++j) { - int j1 = j & 0x07; - if (n_syms == 1) { - s2[j] = (float) wf[kFT8GrayMap[j1]]; - continue; - } - int j2 = (j >> 3) & 0x07; - if (n_syms == 2) { - s2[j] = (float) wf[kFT8GrayMap[j2]]; - s2[j] += (float) wf[kFT8GrayMap[j1] + 4 * num_bins]; - continue; - } - int j3 = (j >> 6) & 0x07; - s2[j] = (float) wf[kFT8GrayMap[j3]]; - s2[j] += (float) wf[kFT8GrayMap[j2] + 4 * num_bins]; - s2[j] += (float) wf[kFT8GrayMap[j1] + 8 * num_bins]; - } - - // Extract bit significance (and convert them to float) - // 8 FSK tones = 3 bits - for (int i = 0; i < n_bits; ++i) { - if (bit_idx + i >= FTX_LDPC_N) { - // Respect array size - break; - } - - uint16_t mask = (n_tones >> (i + 1)); - float max_zero = -1000, max_one = -1000; - for (int n = 0; n < n_tones; ++n) { - if (n & mask) { - max_one = max2(max_one, s2[n]); - } else { - max_zero = max2(max_zero, s2[n]); - } - } - - log174[bit_idx + i] = max_one - max_zero; - } -} - -// Packs a string of bits each represented as a zero/non-zero byte in plain[], -// as a string of packed bits starting from the MSB of the first byte of packed[] -static void pack_bits(const uint8_t bit_array[], int num_bits, uint8_t packed[]) { - int num_bytes = (num_bits + 7) / 8; - for (int i = 0; i < num_bytes; ++i) { - packed[i] = 0; - } - - uint8_t mask = 0x80; - int byte_idx = 0; - for (int i = 0; i < num_bits; ++i) { - if (bit_array[i]) { - packed[byte_idx] |= mask; - } - mask >>= 1; - if (!mask) { - mask = 0x80; - ++byte_idx; - } - } -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/decode.h b/ft8CN/app/src/main/cpp/ft8/decode.h deleted file mode 100644 index eea7b7e..0000000 --- a/ft8CN/app/src/main/cpp/ft8/decode.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef _INCLUDE_DECODE_H_ -#define _INCLUDE_DECODE_H_ - -#include -#include - -#include "constants.h" -#include "../fft/kiss_fft.h" -#include "../common/debug.h" -/// Input structure to ft8_find_sync() function. This structure describes stored waterfall data over the whole message slot. -/// Fields time_osr and freq_osr specify additional oversampling rate for time and frequency resolution. -/// If time_osr=1, FFT magnitude data is collected once for every symbol transmitted, i.e. every 1/6.25 = 0.16 seconds. -/// Values time_osr > 1 mean each symbol is further subdivided in time. -/// If freq_osr=1, each bin in the FFT magnitude data corresponds to 6.25 Hz, which is the tone spacing. -/// Values freq_osr > 1 mean the tone spacing is further subdivided by FFT analysis. - -/// ft8_find_sync()函数的输入结构。这种结构描述了整个消息槽中存储的瀑布数据。 -/// time_osr和freq_osr字段指定时间和频率分辨率的额外过采样率。 -/// 如果time_osr=1,则针对每个传输的符号收集一次FFT幅度数据,即每1/6.25=0.16秒收集一次。FSK符号的时间长度是0.16秒。 -/// 如果time_osr>1表示每个符号在时间上进一步过采样。 -/// 如果freq_osr=1,FFT幅度数据中的每个单元对应于6.25 Hz,这是音调间隔(FSK的符号时长)。 -/// 如果freq_osr>1意味着通过FFT分析进一步对音调间隔过采样。 - -typedef struct -{ - int max_blocks; ///< mag阵列中分配的块(符号)数。number of blocks (symbols) allocated in the mag array - int num_blocks; ///< mag阵列中存储的块(符号)编号,时域序列号。number of blocks (symbols) stored in the mag array - //num_bins = 12000 * 0.16 / 2 = 960 - int num_bins; ///< 以6.25 Hz为单位的FFT箱数量(960)。number of FFT bins in terms of 6.25 Hz - int time_osr; ///< 时间过采样率(时间细分数)。number of time subdivisions - int freq_osr; ///< 频率过采样率(频率细分数)。number of frequency subdivisions - uint8_t* mag; ///< FFT的magnitudes(量级)存储。FFT magnitudes stored as uint8_t[blocks][time_osr][freq_osr][num_bins] - int block_stride; ///< 块的步态?没搞懂。Helper value = time_osr * freq_osr * num_bins - ftx_protocol_t protocol; ///< 协议。Indicate if using FT4 or FT8 - float* mag2;///用于存储准确信号量的数组,这是个平方值,真正的值需要开方,为了速度,就不开方了,等后续再计算。 - -} waterfall_t; - -/// Output structure of ft8_find_sync() and input structure of ft8_decode(). -/// Holds the position of potential start of a message in time and frequency. -// 此结构是ft8_find_sync()的输出结构,ft8_decode()的输入 -// 在时间和频率上,保持消息的潜在起始位置。 -typedef struct -{ - int16_t score; ///< score 候选分数(非负数;分数越高表示可能性越大)。Candidate score (non-negative number; higher score means higher likelihood) - int16_t time_offset; ///< 时间段索引。Index of the time block - int16_t freq_offset; ///< 频率段索引。Index of the frequency bin - uint8_t time_sub; ///< 所用时间细分的索引。Index of the time subdivision used - uint8_t freq_sub; ///< 所用频率细分的索引。Index of the frequency subdivision used - int snr;//信噪比 -} candidate_t; - -/// Structure that holds the decoded message -typedef struct { - uint32_t hash22; - uint32_t hash12; - uint32_t hash10; -} hashCode; -// 保存已解码消息的结构 -typedef struct -{ - //2022-05-13增加i3和n3 - uint8_t i3; - uint8_t n3; - - // TODO: check again that this size is enough - //char text[25]; ///< 纯文本,Plain text,原文是25, - char text[48]; ///<但在在unpack.c中,unpack77函数的最大可能是14+14+19= - uint16_t hash; ///用于对消息hash,防止消息重复< Hash value to be used in hash table and quick checking for duplicates - - //2022-05-26新增以下内容 - char call_to[14];//被呼叫的呼号 - char call_de[14];//发起的呼号 - char extra[19];//扩展内容 - - //---TODO------------- - char maidenGrid[5];//梅登海德 - int report;//信号报告 - - hashCode call_to_hash;//22位长度的哈希码 - hashCode call_de_hash;//22位长度的哈希码 - //TO HASH , FROM HASH - - uint8_t a91[FTX_LDPC_K_BYTES];//用于生成减法代码的数据 - -} message_t; - -/// Structure that contains the status of various steps during decoding of a message -/// 包含消息解码过程中各个步骤的状态的结构 -typedef struct -{ - int ldpc_errors; ///< 解码期间的LDPC(稀疏校验矩阵)错误数。Number of LDPC errors during decoding - uint16_t crc_extracted; ///< 从消息中恢复的CRC值。CRC value recovered from the message - uint16_t crc_calculated; ///< 在有效负载上计算的CRC值。CRC value calculated over the payload - int unpack_status; ///< 解包例程的返回值。Return value of the unpack routine -} decode_status_t; - -/// Localize top N candidates in frequency and time according to their sync strength (looking at Costas symbols) -/// 根据同步强度(查看Costas符号),在频率和时间上对前N名候选人进行本地化。 -/// We treat and organize the candidate list as a min-heap (empty initially). -/// 我们将候选列表视为一个最小堆(最初为空)。 - -/// @param[in] power 在消息槽期间收集的瀑布数据。Waterfall data collected during message slot -/// @param[in] sync_pattern 同步模式。Synchronization pattern -/// @param[in] num_candidates 最大候选数量(堆数组大小)。Number of maximum candidates (size of heap array) -/// @param[in,out] heap 候选项类型的数组(分配了num个候选项)。Array of candidate_t type entries (with num_candidates allocated entries) -/// @param[in] min_score 删减不太可能的候选项所允许的最低分数(可以为零,没有效果)。Minimal score allowed for pruning unlikely candidates (can be zero for no effect) -/// @return 堆中填写的候选人数。Number of candidates filled in the heap -int ft8_find_sync(const waterfall_t* power, int num_candidates, candidate_t heap[], int min_score); - -/// Attempt to decode a message candidate. Extracts the bit probabilities, runs LDPC decoder, checks CRC and unpacks the message in plain text. -/// 尝试解码候选消息。提取比特概率,运行LDPC解码器,检查CRC,并将消息解压为纯文本。 -/// @param[in] power 在消息槽期间收集的瀑布数据。Waterfall data collected during message slot -/// @param[in] cand 要解码的候选人。Candidate to decode -/// @param[out] message 将接收解码消息的message_t结构。message_t structure that will receive the decoded message -/// @param[in] max_iterations 允许的最大LDPC迭代次数(数字越小,解码速度越快,但精度越低)。Maximum allowed LDPC iterations (lower number means faster decode, but less precise) -/// @param[out] status decode_status_t结构,该结构将填充各种解码步骤的状态。decode_status_t structure that will be filled with the status of various decoding steps -/// @return 如果解码成功,则为True,否则为false(查看状态了解详细信息)。True if the decoding was successful, false otherwise (check status for details) -bool ft8_decode(waterfall_t* power, candidate_t* cand, message_t* message, int max_iterations, decode_status_t* status); - -#endif // _INCLUDE_DECODE_H_ diff --git a/ft8CN/app/src/main/cpp/ft8/encode.c b/ft8CN/app/src/main/cpp/ft8/encode.c deleted file mode 100644 index ad4b57d..0000000 --- a/ft8CN/app/src/main/cpp/ft8/encode.c +++ /dev/null @@ -1,197 +0,0 @@ -#include "encode.h" -#include "constants.h" -#include "crc.h" - -#include -#include "../common/debug.h" -// Returns 1 if an odd number of bits are set in x, zero otherwise -static uint8_t parity8(uint8_t x) -{ - x ^= x >> 4; // a b c d ae bf cg dh - x ^= x >> 2; // a b ac bd cae dbf aecg bfdh - x ^= x >> 1; // a ab bac acbd bdcae caedbf aecgbfdh - return x % 2; // modulo 2 -} - -// Encode via LDPC a 91-bit message and return a 174-bit codeword. -// The generator matrix has dimensions (87,87). -// The code is a (174,91) regular LDPC code with column weight 3. -// Arguments: -// [IN] message - array of 91 bits stored as 12 bytes (MSB first) -// [OUT] codeword - array of 174 bits stored as 22 bytes (MSB first) -static void encode174(const uint8_t* message, uint8_t* codeword) -{ - // This implementation accesses the generator bits straight from the packed binary representation in kFTXLDPCGenerator - - // Fill the codeword with message and zeros, as we will only update binary ones later - for (int j = 0; j < FTX_LDPC_N_BYTES; ++j) - { - codeword[j] = (j < FTX_LDPC_K_BYTES) ? message[j] : 0; - } - - // Compute the byte index and bit mask for the first checksum bit - uint8_t col_mask = (0x80u >> (FTX_LDPC_K % 8u)); // bitmask of current byte - uint8_t col_idx = FTX_LDPC_K_BYTES - 1; // index into byte array - - // Compute the LDPC checksum bits and store them in codeword - for (int i = 0; i < FTX_LDPC_M; ++i) - { - // Fast implementation of bitwise multiplication and parity checking - // Normally nsum would contain the result of dot product between message and kFTXLDPCGenerator[i], - // but we only compute the sum modulo 2. - uint8_t nsum = 0; - for (int j = 0; j < FTX_LDPC_K_BYTES; ++j) - { - uint8_t bits = message[j] & kFTXLDPCGenerator[i][j]; // bitwise AND (bitwise multiplication) - nsum ^= parity8(bits); // bitwise XOR (addition modulo 2) - } - - // Set the current checksum bit in codeword if nsum is odd - if (nsum % 2) - { - codeword[col_idx] |= col_mask; - } - - // Update the byte index and bit mask for the next checksum bit - col_mask >>= 1; - if (col_mask == 0) - { - col_mask = 0x80u; - ++col_idx; - } - } -} - -void ft8_encode(const uint8_t* payload, uint8_t* tones) -{ - uint8_t a91[FTX_LDPC_K_BYTES]; // Store 77 bits of payload + 14 bits CRC - - // Compute and add CRC at the end of the message - // a91 contains 77 bits of payload + 14 bits of CRC - ftx_add_crc(payload, a91); - - uint8_t codeword[FTX_LDPC_N_BYTES]; - encode174(a91, codeword); - - - - // Message structure: S7 D29 S7 D29 S7 - // Total symbols: 79 (FT8_NN) - - uint8_t mask = 0x80u; // Mask to extract 1 bit from codeword - int i_byte = 0; // Index of the current byte of the codeword - for (int i_tone = 0; i_tone < FT8_NN; ++i_tone) - { - if ((i_tone >= 0) && (i_tone < 7)) - { - tones[i_tone] = kFT8CostasPattern[i_tone]; - } - else if ((i_tone >= 36) && (i_tone < 43)) - { - tones[i_tone] = kFT8CostasPattern[i_tone - 36]; - } - else if ((i_tone >= 72) && (i_tone < 79)) - { - tones[i_tone] = kFT8CostasPattern[i_tone - 72]; - } - else - { - // Extract 3 bits from codeword at i-th position - uint8_t bits3 = 0; - - if (codeword[i_byte] & mask) - bits3 |= 4; - if (0 == (mask >>= 1)) - { - mask = 0x80u; - i_byte++; - } - if (codeword[i_byte] & mask) - bits3 |= 2; - if (0 == (mask >>= 1)) - { - mask = 0x80u; - i_byte++; - } - if (codeword[i_byte] & mask) - bits3 |= 1; - if (0 == (mask >>= 1)) - { - mask = 0x80u; - i_byte++; - } - - tones[i_tone] = kFT8GrayMap[bits3]; - } - } -} - -void ft4_encode(const uint8_t* payload, uint8_t* tones) -{ - uint8_t a91[FTX_LDPC_K_BYTES]; // Store 77 bits of payload + 14 bits CRC - uint8_t payload_xor[10]; // Encoded payload data - - // '[..] for FT4 only, in order to avoid transmitting a long string of zeros when sending CQ messages, - // the assembled 77-bit message is bitwise exclusive-OR’ed with [a] pseudorandom sequence before computing the CRC and FEC parity bits' - for (int i = 0; i < 10; ++i) - { - payload_xor[i] = payload[i] ^ kFT4XORSequence[i]; - } - - // Compute and add CRC at the end of the message - // a91 contains 77 bits of payload + 14 bits of CRC - ftx_add_crc(payload_xor, a91); - - uint8_t codeword[FTX_LDPC_N_BYTES]; - encode174(a91, codeword); // 91 bits -> 174 bits - - // Message structure: R S4_1 D29 S4_2 D29 S4_3 D29 S4_4 R - // Total symbols: 105 (FT4_NN) - - uint8_t mask = 0x80u; // Mask to extract 1 bit from codeword - int i_byte = 0; // Index of the current byte of the codeword - for (int i_tone = 0; i_tone < FT4_NN; ++i_tone) - { - if ((i_tone == 0) || (i_tone == 104)) - { - tones[i_tone] = 0; // R (ramp) symbol - } - else if ((i_tone >= 1) && (i_tone < 5)) - { - tones[i_tone] = kFT4CostasPattern[0][i_tone - 1]; - } - else if ((i_tone >= 34) && (i_tone < 38)) - { - tones[i_tone] = kFT4CostasPattern[1][i_tone - 34]; - } - else if ((i_tone >= 67) && (i_tone < 71)) - { - tones[i_tone] = kFT4CostasPattern[2][i_tone - 67]; - } - else if ((i_tone >= 100) && (i_tone < 104)) - { - tones[i_tone] = kFT4CostasPattern[3][i_tone - 100]; - } - else - { - // Extract 2 bits from codeword at i-th position - uint8_t bits2 = 0; - - if (codeword[i_byte] & mask) - bits2 |= 2; - if (0 == (mask >>= 1)) - { - mask = 0x80u; - i_byte++; - } - if (codeword[i_byte] & mask) - bits2 |= 1; - if (0 == (mask >>= 1)) - { - mask = 0x80u; - i_byte++; - } - tones[i_tone] = kFT4GrayMap[bits2]; - } - } -} diff --git a/ft8CN/app/src/main/cpp/ft8/encode.h b/ft8CN/app/src/main/cpp/ft8/encode.h deleted file mode 100644 index d5e2759..0000000 --- a/ft8CN/app/src/main/cpp/ft8/encode.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _INCLUDE_ENCODE_H_ -#define _INCLUDE_ENCODE_H_ - -#include - -// typedef struct -// { -// uint8_t tones[FT8_NN]; -// // for waveform readout: -// int n_spsym; // Number of waveform samples per symbol -// float *pulse; // [3 * n_spsym] -// int idx_symbol; // Index of the current symbol -// float f0; // Base frequency, Hertz -// float signal_rate; // Waveform sample rate, Hertz -// } encoder_t; - -// void encoder_init(float signal_rate, float *pulse_buffer); -// void encoder_set_f0(float f0); -// void encoder_process(const message_t *message); // in: message -// void encoder_generate(float *block); // out: block of waveforms - -/// Generate FT8 tone sequence from payload data -/// @param[in] payload - 10 byte array consisting of 77 bit payload -/// @param[out] tones - array of FT8_NN (79) bytes to store the generated tones (encoded as 0..7) -void ft8_encode(const uint8_t* payload, uint8_t* tones); - -/// Generate FT4 tone sequence from payload data -/// @param[in] payload - 10 byte array consisting of 77 bit payload -/// @param[out] tones - array of FT4_NN (105) bytes to store the generated tones (encoded as 0..3) -void ft4_encode(const uint8_t* payload, uint8_t* tones); - -#endif // _INCLUDE_ENCODE_H_ diff --git a/ft8CN/app/src/main/cpp/ft8/hash22.c b/ft8CN/app/src/main/cpp/ft8/hash22.c deleted file mode 100644 index bf9e97b..0000000 --- a/ft8CN/app/src/main/cpp/ft8/hash22.c +++ /dev/null @@ -1,65 +0,0 @@ - - -#include "hash22.h" -#include "stdlib.h" -#include "string.h" -//m为hash的长度,12,22 -//call的长度是12(包括'\0') -uint32_t hashcall(char* call, int m) -{ - const char *chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/"; - char callsign[11]=" "; - - char *temp=call; - - int j=0; - while(temp[0] == ' '){ - ++temp; - if (temp[0]!=' ') - { - break; - } - j++; - } - - for (int i = 0; i < 11-j; i++) - { - if (temp[i]=='\0') - { - break; - }else{ - callsign[i]=temp[i]; - } - - } - - uint64_t x = 0; - for(int i = 0; i < 11; i++){ - - int c = (int)callsign[i]; - const char *p = strchr(chars, c); - if (p==NULL) - { - return 0; - } - - int j = p - chars; - x = 38*x + j; - } - - x = x * 47055833459LL; - x = x >> (64 - m); - - return x; - -} - -uint32_t hashcall_10(char* call){ - return hashcall(call,HASH_10); -} -uint32_t hashcall_12(char* call){ - return hashcall(call,HASH_12); -} -uint32_t hashcall_22(char* call){ - return hashcall(call,HASH_22); -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/hash22.h b/ft8CN/app/src/main/cpp/ft8/hash22.h deleted file mode 100644 index 96ce5ab..0000000 --- a/ft8CN/app/src/main/cpp/ft8/hash22.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - - -#define HASH_10 (10) ///哈希码长度为10 -#define HASH_12 (12) ///哈希码长度为12 -#define HASH_22 (22) ///哈希码长度为12 -uint32_t hashcall(char* call, int m); - -uint32_t hashcall_10(char* call);//返回长度是10的哈希码 -uint32_t hashcall_12(char* call);//返回长度是12的哈希码 -uint32_t hashcall_22(char* call);//返回长度是22的哈希码 \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/ldpc.c b/ft8CN/app/src/main/cpp/ft8/ldpc.c deleted file mode 100644 index 1b3584c..0000000 --- a/ft8CN/app/src/main/cpp/ft8/ldpc.c +++ /dev/null @@ -1,268 +0,0 @@ -// -// LDPC decoder for FT8. -// -// given a 174-bit codeword as an array of log-likelihood of zero, -// return a 174-bit corrected codeword, or zero-length array. -// last 87 bits are the (systematic) plain-text. -// this is an implementation of the sum-product algorithm -// from Sarah Johnson's Iterative Error Correction book. -// codeword[i] = log ( P(x=0) / P(x=1) ) -// -////将174位码字作为对数似然为零的数组, -////返回一个174位已更正的码字或零长度数组。 -////最后87位是(系统)纯文本。 -////这是和积算法的一个实现 -////来自Sarah Johnson的迭代纠错手册。 -////码字[i]=对数(P(x=0)/P(x=1)) - -#include "ldpc.h" -#include "constants.h" - -#include -#include -#include -#include - -static int ldpc_check(uint8_t codeword[]); -static float fast_tanh(float x); -static float fast_atanh(float x); - -// codeword is 174 log-likelihoods. -// plain is a return value, 174 ints, to be 0 or 1. -// max_iters is how hard to try. -// ok == 87 means success. -void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int* ok) -{ - float m[FTX_LDPC_M][FTX_LDPC_N]; // ~60 kB - float e[FTX_LDPC_M][FTX_LDPC_N]; // ~60 kB - int min_errors = FTX_LDPC_M; - - for (int j = 0; j < FTX_LDPC_M; j++) - { - for (int i = 0; i < FTX_LDPC_N; i++) - { - m[j][i] = codeword[i]; - e[j][i] = 0.0f; - } - } - - for (int iter = 0; iter < max_iters; iter++) - { - for (int j = 0; j < FTX_LDPC_M; j++) - { - - for (int ii1 = 0; ii1 < kFTX_LDPCNumRows[j]; ii1++) - { - - int i1 = kFTX_LDPC_Nm[j][ii1] - 1; - float a = 1.0f; - for (int ii2 = 0; ii2 < kFTX_LDPCNumRows[j]; ii2++) - { - - int i2 = kFTX_LDPC_Nm[j][ii2] - 1; - if (i2 != i1) - { - a *= fast_tanh(-m[j][i2] / 2.0f); - } - } - e[j][i1] = -2.0f * fast_atanh(a); - } - } - - for (int i = 0; i < FTX_LDPC_N; i++) - { - float l = codeword[i]; - for (int j = 0; j < 3; j++) - l += e[kFTX_LDPC_Mn[i][j] - 1][i]; - plain[i] = (l > 0) ? 1 : 0; - } - - int errors = ldpc_check(plain); - - if (errors < min_errors) - { - // Update the current best result - min_errors = errors; - - if (errors == 0) - { - break; // Found a perfect answer - } - } - - for (int i = 0; i < FTX_LDPC_N; i++) - { - for (int ji1 = 0; ji1 < 3; ji1++) - { - int j1 = kFTX_LDPC_Mn[i][ji1] - 1; - float l = codeword[i]; - for (int ji2 = 0; ji2 < 3; ji2++) - { - if (ji1 != ji2) - { - int j2 = kFTX_LDPC_Mn[i][ji2] - 1; - l += e[j2][i]; - } - } - m[j1][i] = l; - } - } - } - - *ok = min_errors; -} - -// -// does a 174-bit codeword pass the FT8's LDPC parity checks? -// returns the number of parity errors. -// 0 means total success. -// -static int ldpc_check(uint8_t codeword[]) -{ - int errors = 0; - - for (int m = 0; m < FTX_LDPC_M; ++m) - { - uint8_t x = 0; - for (int i = 0; i < kFTX_LDPCNumRows[m]; ++i) - { - x ^= codeword[kFTX_LDPC_Nm[m][i] - 1]; - } - if (x != 0) - { - ++errors; - } - } - return errors; -} - -//// 码字是174个对数可能性。 -//// plain是一个返回值,174 整数,为0或1。 -//// max_iters是迭代次数。 -//// ok==87表示成功。好像不是哦,==0才是 -void bp_decode(float codeword[], int max_iters, uint8_t plain[], int* ok) -{ - float tov[FTX_LDPC_N][3]; - float toc[FTX_LDPC_M][7]; - - //FTX_LDPC_M=83 - int min_errors = FTX_LDPC_M; - - // initialize message data - //FTX_LDPC_N=174 - for (int n = 0; n < FTX_LDPC_N; ++n) - { - tov[n][0] = tov[n][1] = tov[n][2] = 0; - } - - for (int iter = 0; iter < max_iters; ++iter) - { - // Do a hard decision guess (tov=0 in iter 0) - int plain_sum = 0; - for (int n = 0; n < FTX_LDPC_N; ++n) - {//转换成0和1 - plain[n] = ((codeword[n] + tov[n][0] + tov[n][1] + tov[n][2]) > 0) ? 1 : 0; - plain_sum += plain[n]; - } - - if (plain_sum == 0) - { - // message converged to all-zeros, which is prohibited - //消息聚合到所有零,这是禁止的 - break; - } - - // Check to see if we have a codeword (check before we do any iter) - //向LDPC(稀疏校验矩阵)检测LDPC矩阵是预定义的83行91列的矩阵 - int errors = ldpc_check(plain); - - if (errors < min_errors) - { - // we have a better guess - update the result - min_errors = errors; - - if (errors == 0) - { - break; // Found a perfect answer - } - } - - // Send messages from bits to check nodes - for (int m = 0; m < FTX_LDPC_M; ++m) - { - for (int n_idx = 0; n_idx < kFTX_LDPCNumRows[m]; ++n_idx) - { - int n = kFTX_LDPC_Nm[m][n_idx] - 1; - // for each (n, m) - float Tnm = codeword[n]; - for (int m_idx = 0; m_idx < 3; ++m_idx) - { - if ((kFTX_LDPC_Mn[n][m_idx] - 1) != m) - { - Tnm += tov[n][m_idx]; - } - } - toc[m][n_idx] = fast_tanh(-Tnm / 2); - } - } - - // send messages from check nodes to variable nodes - for (int n = 0; n < FTX_LDPC_N; ++n) - { - for (int m_idx = 0; m_idx < 3; ++m_idx) - { - int m = kFTX_LDPC_Mn[n][m_idx] - 1; - // for each (n, m) - float Tmn = 1.0f; - for (int n_idx = 0; n_idx < kFTX_LDPCNumRows[m]; ++n_idx) - { - if ((kFTX_LDPC_Nm[m][n_idx] - 1) != n) - { - Tmn *= toc[m][n_idx]; - } - } - tov[n][m_idx] = -2 * fast_atanh(Tmn); - } - } - } - - *ok = min_errors; -} - -// Ideas for approximating tanh/atanh: -// * https://varietyofsound.wordpress.com/2011/02/14/efficient-tanh-computation-using-lamberts-continued-fraction/ -// * http://functions.wolfram.com/ElementaryFunctions/ArcTanh/10/0001/ -// * https://mathr.co.uk/blog/2017-09-06_approximating_hyperbolic_tangent.html -// * https://math.stackexchange.com/a/446411 - -static float fast_tanh(float x) -{ - if (x < -4.97f) - { - return -1.0f; - } - if (x > 4.97f) - { - return 1.0f; - } - float x2 = x * x; - // float a = x * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); - // float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); - // float a = x * (10395.0f + x2 * (1260.0f + x2 * 21.0f)); - // float b = 10395.0f + x2 * (4725.0f + x2 * (210.0f + x2)); - float a = x * (945.0f + x2 * (105.0f + x2)); - float b = 945.0f + x2 * (420.0f + x2 * 15.0f); - return a / b; -} - -static float fast_atanh(float x) -{ - float x2 = x * x; - // float a = x * (-15015.0f + x2 * (19250.0f + x2 * (-5943.0f + x2 * 256.0f))); - // float b = (-15015.0f + x2 * (24255.0f + x2 * (-11025.0f + x2 * 1225.0f))); - // float a = x * (-1155.0f + x2 * (1190.0f + x2 * -231.0f)); - // float b = (-1155.0f + x2 * (1575.0f + x2 * (-525.0f + x2 * 25.0f))); - float a = x * (945.0f + x2 * (-735.0f + x2 * 64.0f)); - float b = (945.0f + x2 * (-1050.0f + x2 * 225.0f)); - return a / b; -} diff --git a/ft8CN/app/src/main/cpp/ft8/ldpc.h b/ft8CN/app/src/main/cpp/ft8/ldpc.h deleted file mode 100644 index 5215d4b..0000000 --- a/ft8CN/app/src/main/cpp/ft8/ldpc.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _INCLUDE_LDPC_H_ -#define _INCLUDE_LDPC_H_ - -#include -#include "../common/debug.h" - -//// codeword is 174 log-likelihoods. -//// plain is a return value, 174 ints, to be 0 or 1. -//// iters is how hard to try. -//// ok == 87 means success. -//// 码字是174个对数可能性。 -//// plain是一个返回值,174 整数,为0或1。 -//// max_iters是迭代次数。 -//// ok==87表示成功。??好像不是哦,==0才是 - -void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int* ok); - -void bp_decode(float codeword[], int max_iters, uint8_t plain[], int* ok); - -#endif // _INCLUDE_LDPC_H_ diff --git a/ft8CN/app/src/main/cpp/ft8/pack.c b/ft8CN/app/src/main/cpp/ft8/pack.c deleted file mode 100644 index 9617aa9..0000000 --- a/ft8CN/app/src/main/cpp/ft8/pack.c +++ /dev/null @@ -1,373 +0,0 @@ -#include "pack.h" -#include "text.h" - -#include -#include -#include -#include -#include "../common/debug.h" - -#define NTOKENS ((uint32_t)2063592L) -#define MAX22 ((uint32_t)4194304L) -#define MAXGRID4 ((uint16_t)32400) - -const char A0[] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"; -const char A1[] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const char A2[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const char A3[] = "0123456789"; -const char A4[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -// Pack a special token, a 22-bit hash code, or a valid base call -// into a 28-bit integer. -int32_t pack28(const char* callsign) -{ - // Check for special tokens first - if (starts_with(callsign, "DE ")) - return 0; - if (starts_with(callsign, "QRZ ")) - return 1; - if (starts_with(callsign, "CQ ")) - return 2; - - if (starts_with(callsign, "CQ_")) - { - int nnum = 0, nlet = 0; - - // TODO: - } - - // TODO: Check for <...> callsign - - char c6[6] = { ' ', ' ', ' ', ' ', ' ', ' ' }; - - int length = 0; // strlen(callsign); // We will need it later - while (callsign[length] != ' ' && callsign[length] != 0) - { - length++; - } - - // Copy callsign to 6 character buffer - if (starts_with(callsign, "3DA0") && length <= 7) - { - // Work-around for Swaziland prefix: 3DA0XYZ -> 3D0XYZ - memcpy(c6, "3D0", 3); - memcpy(c6 + 3, callsign + 4, length - 4); - } - else if (starts_with(callsign, "3X") && is_letter(callsign[2]) && length <= 7) - { - // Work-around for Guinea prefixes: 3XA0XYZ -> QA0XYZ - memcpy(c6, "Q", 1); - memcpy(c6 + 1, callsign + 2, length - 2); - } - else - { - if (is_digit(callsign[2]) && length <= 6) - { - // AB0XYZ - memcpy(c6, callsign, length); - } - else if (is_digit(callsign[1]) && length <= 5) - { - // A0XYZ -> " A0XYZ" - memcpy(c6 + 1, callsign, length); - } - } - - // Check for standard callsign - int i0, i1, i2, i3, i4, i5; - if ((i0 = char_index(A1, c6[0])) >= 0 && (i1 = char_index(A2, c6[1])) >= 0 && (i2 = char_index(A3, c6[2])) >= 0 && (i3 = char_index(A4, c6[3])) >= 0 && (i4 = char_index(A4, c6[4])) >= 0 && (i5 = char_index(A4, c6[5])) >= 0) - { - // This is a standard callsign - int32_t n28 = i0; - n28 = n28 * 36 + i1; - n28 = n28 * 10 + i2; - n28 = n28 * 27 + i3; - n28 = n28 * 27 + i4; - n28 = n28 * 27 + i5; - return NTOKENS + MAX22 + n28; - } - - //char text[13]; - //if (length > 13) return -1; - - // TODO: - // Treat this as a nonstandard callsign: compute its 22-bit hash - return -1; -} - -// Check if a string could be a valid standard callsign or a valid -// compound callsign. -// Return base call "bc" and a logical "cok" indicator. -bool chkcall(const char* call, char* bc) -{ - int length = strlen(call); // n1=len_trim(w) - if (length > 11) - return false; - if (0 != strchr(call, '.')) - return false; - if (0 != strchr(call, '+')) - return false; - if (0 != strchr(call, '-')) - return false; - if (0 != strchr(call, '?')) - return false; - if (length > 6 && 0 != strchr(call, '/')) - return false; - - // TODO: implement suffix parsing (or rework?) - - return true; -} - -uint16_t packgrid(const char* grid4) -{ - if (grid4 == 0) - { - // Two callsigns only, no report/grid - return MAXGRID4 + 1; - } - - // Take care of special cases - if (equals(grid4, "RRR")) - return MAXGRID4 + 2; - if (equals(grid4, "RR73")) - return MAXGRID4 + 3; - if (equals(grid4, "73")) - return MAXGRID4 + 4; - - // Check for standard 4 letter grid - if (in_range(grid4[0], 'A', 'R') && in_range(grid4[1], 'A', 'R') && is_digit(grid4[2]) && is_digit(grid4[3])) - { - uint16_t igrid4 = (grid4[0] - 'A'); - igrid4 = igrid4 * 18 + (grid4[1] - 'A'); - igrid4 = igrid4 * 10 + (grid4[2] - '0'); - igrid4 = igrid4 * 10 + (grid4[3] - '0'); - return igrid4; - } - - // Parse report: +dd / -dd / R+dd / R-dd - // TODO: check the range of dd - if (grid4[0] == 'R') - { - int dd = dd_to_int(grid4 + 1, 3); - uint16_t irpt = 35 + dd; - return (MAXGRID4 + irpt) | 0x8000; // ir = 1 - } - else - { - int dd = dd_to_int(grid4, 3); - uint16_t irpt = 35 + dd; - return (MAXGRID4 + irpt); // ir = 0 - } - - return MAXGRID4 + 1; -} - -// Pack Type 1 (Standard 77-bit message) and Type 2 (ditto, with a "/P" call) -int pack77_1(const char* msg, uint8_t* b77) -{ - // Locate the first delimiter - const char* s1 = strchr(msg, ' '); - if (s1 == 0) - return -1; - - const char* call1 = msg; // 1st call - const char* call2 = s1 + 1; // 2nd call - - LOG(LOG_DEBUG,"call1 :%s", call1); - LOG(LOG_DEBUG,"call2 :%s", call2); - - int32_t n28a = pack28(call1); - int32_t n28b = pack28(call2); - LOG(LOG_DEBUG,"n28a %2X",n28a); - LOG(LOG_DEBUG,"n28b %2X",n28b); - - if (n28a < 0 || n28b < 0) - return -1; - - uint16_t igrid4; - - // Locate the second delimiter - const char* s2 = strchr(s1 + 1, ' '); - if (s2 != 0) - { - LOG(LOG_DEBUG,"GRID: %s",s2); - igrid4 = packgrid(s2 + 1); - } - else - { - // Two callsigns, no grid/report - igrid4 = packgrid(0); - } - LOG(LOG_DEBUG,"G15: %x",igrid4); - - uint8_t i3 = 1; // No suffix or /R - - // TODO: check for suffixes - - // Shift in ipa and ipb bits into n28a and n28b - n28a <<= 1; // ipa = 0 - n28b <<= 1; // ipb = 0 - - // Pack into (28 + 1) + (28 + 1) + (1 + 15) + 3 bits - b77[0] = (n28a >> 21); - b77[1] = (n28a >> 13); - b77[2] = (n28a >> 5); - b77[3] = (uint8_t)(n28a << 3) | (uint8_t)(n28b >> 26); - b77[4] = (n28b >> 18); - b77[5] = (n28b >> 10); - b77[6] = (n28b >> 2); - b77[7] = (uint8_t)(n28b << 6) | (uint8_t)(igrid4 >> 10); - b77[8] = (igrid4 >> 2); - b77[9] = (uint8_t)(igrid4 << 6) | (uint8_t)(i3 << 3); - - return 0; -} - -void packtext77(const char* text, uint8_t* b77) -{ - int length = strlen(text); - - // Skip leading and trailing spaces - while (*text == ' ' && *text != 0) - { - ++text; - --length; - } - while (length > 0 && text[length - 1] == ' ') - { - --length; - } - - // Clear the first 72 bits representing a long number - for (int i = 0; i < 9; ++i) - { - b77[i] = 0; - } - - // Now express the text as base-42 number stored - // in the first 72 bits of b77 - for (int j = 0; j < 13; ++j) - { - // Multiply the long integer in b77 by 42 - uint16_t x = 0; - for (int i = 8; i >= 0; --i) - { - x += b77[i] * (uint16_t)42; - b77[i] = (x & 0xFF); - x >>= 8; - } - - // Get the index of the current char - if (j < length) - { - int q = char_index(A0, text[j]); - x = (q > 0) ? q : 0; - } - else - { - x = 0; - } - // Here we double each added number in order to have the result multiplied - // by two as well, so that it's a 71 bit number left-aligned in 72 bits (9 bytes) - x <<= 1; - - // Now add the number to our long number - for (int i = 8; i >= 0; --i) - { - if (x == 0) - break; - x += b77[i]; - b77[i] = (x & 0xFF); - x >>= 8; - } - } - - // Set n3=0 (bits 71..73) and i3=0 (bits 74..76) - b77[8] &= 0xFE; - b77[9] &= 0x00; -} - -int pack77(const char* msg, uint8_t* c77) -{ - // Check Type 1 (Standard 77-bit message) or Type 2, with optional "/P" - if (0 == pack77_1(msg, c77)) - { - return 0; - } - - // TODO: - // Check 0.5 (telemetry) - - // Check Type 4 (One nonstandard call and one hashed call) - - // Default to free text - // i3=0 n3=0 - packtext77(msg, c77); - return 0; -} - -#ifdef UNIT_TEST - -#include - -bool test1() -{ - const char* inputs[] = { - "", - " ", - "ABC", - "A9", - "L9A", - "L7BC", - "L0ABC", - "LL3JG", - "LL3AJG", - "CQ ", - 0 - }; - - for (int i = 0; inputs[i]; ++i) - { - int32_t result = ft8_v2::pack28(inputs[i]); - printf("pack28(\"%s\") = %d\n", inputs[i], result); - } - - return true; -} - -bool test2() -{ - const char* inputs[] = { - "CQ LL3JG", - "CQ LL3JG KO26", - "L0UAA LL3JG KO26", - "L0UAA LL3JG +02", - "L0UAA LL3JG RRR", - "L0UAA LL3JG 73", - 0 - }; - - for (int i = 0; inputs[i]; ++i) - { - uint8_t result[10]; - int rc = ft8_v2::pack77_1(inputs[i], result); - printf("pack77_1(\"%s\") = %d\t[", inputs[i], rc); - for (int j = 0; j < 10; ++j) - { - printf("%02x ", result[j]); - } - printf("]\n"); - } - - return true; -} - -int main() -{ - test1(); - test2(); - return 0; -} - -#endif \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/pack.h b/ft8CN/app/src/main/cpp/ft8/pack.h deleted file mode 100644 index fbe1286..0000000 --- a/ft8CN/app/src/main/cpp/ft8/pack.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _INCLUDE_PACK_H_ -#define _INCLUDE_PACK_H_ - -#include - -// Pack FT8 text message into 72 bits -// [IN] msg - FT8 message (e.g. "CQ TE5T KN01") -// [OUT] c77 - 10 byte array to store the 77 bit payload (MSB first) -int pack77(const char* msg, uint8_t* c77); -void packtext77(const char* text, uint8_t* b77); - -#endif // _INCLUDE_PACK_H_ diff --git a/ft8CN/app/src/main/cpp/ft8/text.c b/ft8CN/app/src/main/cpp/ft8/text.c deleted file mode 100644 index 68393a9..0000000 --- a/ft8CN/app/src/main/cpp/ft8/text.c +++ /dev/null @@ -1,253 +0,0 @@ -#include "text.h" - -#include - -const char* trim_front(const char* str) -{ - // Skip leading whitespace - while (*str == ' ') - { - str++; - } - return str; -} - -void trim_back(char* str) -{ - // Skip trailing whitespace by replacing it with '\0' characters - int idx = strlen(str) - 1; - while (idx >= 0 && str[idx] == ' ') - { - str[idx--] = '\0'; - } -} - -// 1) trims a string from the back by changing whitespaces to '\0' -// 2) trims a string from the front by skipping whitespaces -char* trim(char* str) -{ - str = (char*)trim_front(str); - trim_back(str); - // return a pointer to the first non-whitespace character - return str; -} - -char to_upper(char c) -{ - return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; -} - -bool is_digit(char c) -{ - return (c >= '0') && (c <= '9'); -} - -bool is_letter(char c) -{ - return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')); -} - -bool is_space(char c) -{ - return (c == ' '); -} - -bool in_range(char c, char min, char max) -{ - return (c >= min) && (c <= max); -} - -bool starts_with(const char* string, const char* prefix) -{ - return 0 == memcmp(string, prefix, strlen(prefix)); -} - -bool equals(const char* string1, const char* string2) -{ - return 0 == strcmp(string1, string2); -} - -int char_index(const char* string, char c) -{ - for (int i = 0; *string; ++i, ++string) - { - if (c == *string) - { - return i; - } - } - return -1; // Not found -} - -// Text message formatting: -// - replaces lowercase letters with uppercase -// - merges consecutive spaces into single space -void fmtmsg(char* msg_out, const char* msg_in) -{ - char c; - char last_out = 0; - while ((c = *msg_in)) - { - if (c != ' ' || last_out != ' ') - { - last_out = to_upper(c); - *msg_out = last_out; - ++msg_out; - } - ++msg_in; - } - *msg_out = 0; // Add zero termination -} - -// Parse a 2 digit integer from string -int dd_to_int(const char* str, int length) -{ - int result = 0; - bool negative; - int i; - if (str[0] == '-') - { - negative = true; - i = 1; // Consume the - sign - } - else - { - negative = false; - i = (str[0] == '+') ? 1 : 0; // Consume a + sign if found - } - - while (i < length) - { - if (str[i] == 0) - break; - if (!is_digit(str[i])) - break; - result *= 10; - result += (str[i] - '0'); - ++i; - } - - return negative ? -result : result; -} - -// Convert a 2 digit integer to string -void int_to_dd(char* str, int value, int width, bool full_sign) -{ - if (value < 0) - { - *str = '-'; - ++str; - value = -value; - } - else if (full_sign) - { - *str = '+'; - ++str; - } - - int divisor = 1; - for (int i = 0; i < width - 1; ++i) - { - divisor *= 10; - } - - while (divisor >= 1) - { - int digit = value / divisor; - - *str = '0' + digit; - ++str; - - value -= digit * divisor; - divisor /= 10; - } - *str = 0; // Add zero terminator -} - -// convert integer index to ASCII character according to one of 6 tables: -// table 0: " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?" -// table 1: " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -// table 2: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -// table 3: "0123456789" -// table 4: " ABCDEFGHIJKLMNOPQRSTUVWXYZ" -// table 5: " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/" -char charn(int c, int table_idx) -{ - if (table_idx != 2 && table_idx != 3) - { - if (c == 0) - return ' '; - c -= 1; - } - if (table_idx != 4) - { - if (c < 10) - return '0' + c; - c -= 10; - } - if (table_idx != 3) - { - if (c < 26) - return 'A' + c; - c -= 26; - } - - if (table_idx == 0) - { - if (c < 5) - return "+-./?"[c]; - } - else if (table_idx == 5) - { - if (c == 0) - return '/'; - } - - return '_'; // unknown character, should never get here -} - -// Convert character to its index (charn in reverse) according to a table -int nchar(char c, int table_idx) -{ - int n = 0; - if (table_idx != 2 && table_idx != 3) - { - if (c == ' ') - return n + 0; - n += 1; - } - if (table_idx != 4) - { - if (c >= '0' && c <= '9') - return n + (c - '0'); - n += 10; - } - if (table_idx != 3) - { - if (c >= 'A' && c <= 'Z') - return n + (c - 'A'); - n += 26; - } - - if (table_idx == 0) - { - if (c == '+') - return n + 0; - if (c == '-') - return n + 1; - if (c == '.') - return n + 2; - if (c == '/') - return n + 3; - if (c == '?') - return n + 4; - } - else if (table_idx == 5) - { - if (c == '/') - return n + 0; - } - - // Character not found - return -1; -} diff --git a/ft8CN/app/src/main/cpp/ft8/text.h b/ft8CN/app/src/main/cpp/ft8/text.h deleted file mode 100644 index aac9921..0000000 --- a/ft8CN/app/src/main/cpp/ft8/text.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _INCLUDE_TEXT_H_ -#define _INCLUDE_TEXT_H_ - -#include -#include - -// Utility functions for characters and strings - -const char* trim_front(const char* str); -void trim_back(char* str); -char* trim(char* str); - -char to_upper(char c); -bool is_digit(char c); -bool is_letter(char c); -bool is_space(char c); -bool in_range(char c, char min, char max); -bool starts_with(const char* string, const char* prefix); -bool equals(const char* string1, const char* string2); - -int char_index(const char* string, char c); - -// Text message formatting: -// - replaces lowercase letters with uppercase -// - merges consecutive spaces into single space -void fmtmsg(char* msg_out, const char* msg_in); - -// Parse a 2 digit integer from string -int dd_to_int(const char* str, int length); - -// Convert a 2 digit integer to string -void int_to_dd(char* str, int value, int width, bool full_sign); - -char charn(int c, int table_idx); -int nchar(char c, int table_idx); - -#endif // _INCLUDE_TEXT_H_ diff --git a/ft8CN/app/src/main/cpp/ft8/unpack.c b/ft8CN/app/src/main/cpp/ft8/unpack.c deleted file mode 100644 index 7c12a90..0000000 --- a/ft8CN/app/src/main/cpp/ft8/unpack.c +++ /dev/null @@ -1,626 +0,0 @@ -#ifdef __linux__ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#endif - -#include "unpack.h" - -#include "text.h" -// #include //为防止警告 -#include -#include "hash22.h" - -#define MAX22 ((uint32_t)4194304L) -#define NTOKENS ((uint32_t)2063592L) -#define MAXGRID4 ((uint16_t)32400L) - - -// n28 is a 28-bit integer, e.g. n28a or n28b, containing all the -// call sign bits from a packed message. -int unpack_callsign(uint32_t n28, uint8_t ip, uint8_t i3, char *result,hashCode * hash) { - // Check for special tokens DE, QRZ, CQ, CQ_nnn, CQ_aaaa - hash->hash10=0; - hash->hash12=0; - hash->hash22=0; - if (n28 < NTOKENS) { - if (n28 <= 2) { - if (n28 == 0) - strcpy(result, "DE"); - if (n28 == 1) - strcpy(result, "QRZ"); - if (n28 == 2) - strcpy(result, "CQ"); - return 0; // Success - } - if (n28 <= 1002) { - // CQ_nnn with 3 digits - strcpy(result, "CQ "); - int_to_dd(result + 3, n28 - 3, 3, false); - return 0; // Success - } - if (n28 <= 532443L) { - // CQ_aaaa with 4 alphanumeric symbols - uint32_t n = n28 - 1003; - char aaaa[5]; - - aaaa[4] = '\0'; - for (int i = 3; /* */; --i) { - aaaa[i] = charn(n % 27, 4); - if (i == 0) - break; - n /= 27; - } - - strcpy(result, "CQ "); - strcat(result, trim_front(aaaa)); - return 0; // Success - } - // ? TODO: unspecified in the WSJT-X code - return -1; - } - - n28 = n28 - NTOKENS; - if (n28 < MAX22) { - hash->hash10=n28;//把哈希值保存下来 - hash->hash12=n28;//把哈希值保存下来 - hash->hash22=n28;//把哈希值保存下来 - - LOG_PRINTF("N28 HASH: %0x",n28); - - // This is a 22-bit hash of a result - // TODO: implement - strcpy(result, "<...>"); - // result[0] = '<'; - // int_to_dd(result + 1, n28, 7, false); - // result[8] = '>'; - // result[9] = '\0'; - return 0; - } - - // Standard callsign - uint32_t n = n28 - MAX22; - - char callsign[7]; - callsign[6] = '\0'; - callsign[5] = charn(n % 27, 4); - n /= 27; - callsign[4] = charn(n % 27, 4); - n /= 27; - callsign[3] = charn(n % 27, 4); - n /= 27; - callsign[2] = charn(n % 10, 3); - n /= 10; - callsign[1] = charn(n % 36, 2); - n /= 36; - callsign[0] = charn(n % 37, 1); - - // Skip trailing and leading whitespace in case of a short callsign - //短呼号时跳过尾随和前导空格 - strcpy(result, trim(callsign)); - if (strlen(result) == 0) - return -1; - - hash->hash10=hashcall_10(result);//对呼号进行22位的哈希 - hash->hash12=hashcall_12(result);//对呼号进行22位的哈希 - hash->hash22=hashcall_22(result);//对呼号进行22位的哈希 - // Check if we should append /R or /P suffix - //检查是否应附加/R或/P后缀 - if (ip) { - if (i3 == 1) { - strcat(result, "/R"); - } else if (i3 == 2) { - strcat(result, "/P"); - } - } - - return 0; // Success -} - -//int unpack_type1(const uint8_t *a77, uint8_t i3, char *call_to, char *call_de, char *extra) { -// uint32_t n28a, n28b; -// uint16_t igrid4; -// uint8_t ir; -// -// // Extract packed fields -// n28a = (a77[0] << 21); -// n28a |= (a77[1] << 13); -// n28a |= (a77[2] << 5); -// n28a |= (a77[3] >> 3); -// n28b = ((a77[3] & 0x07) << 26); -// n28b |= (a77[4] << 18); -// n28b |= (a77[5] << 10); -// n28b |= (a77[6] << 2); -// n28b |= (a77[7] >> 6); -// ir = ((a77[7] & 0x20) >> 5); -// igrid4 = ((a77[7] & 0x1F) << 10); -// igrid4 |= (a77[8] << 2); -// igrid4 |= (a77[9] >> 6); -// -// // Unpack both callsigns -// if (unpack_callsign(n28a >> 1, n28a & 0x01, i3, call_to) < 0) { -// return -1; -// } -// if (unpack_callsign(n28b >> 1, n28b & 0x01, i3, call_de) < 0) { -// return -2; -// } -// // Fix "CQ_" to "CQ " -> already done in unpack_callsign() -// -// // TODO: add to recent calls -// // if (call_to[0] != '<' && strlen(call_to) >= 4) { -// // save_hash_call(call_to) -// // } -// // if (call_de[0] != '<' && strlen(call_de) >= 4) { -// // save_hash_call(call_de) -// // } -// -// char *dst = extra; -// -// if (igrid4 <= MAXGRID4) { -// // Extract 4 symbol grid locator -// if (ir > 0) { -// // In case of ir=1 add an "R" before grid -// //dst = stpcpy(dst, "R ");//除错 -// dst = strcpy(dst, "R "); -// dst += 3; -// } -// -// uint16_t n = igrid4; -// dst[4] = '\0'; -// dst[3] = '0' + (n % 10); -// n /= 10; -// dst[2] = '0' + (n % 10); -// n /= 10; -// dst[1] = 'A' + (n % 18); -// n /= 18; -// dst[0] = 'A' + (n % 18); -// // if (ir > 0 && strncmp(call_to, "CQ", 2) == 0) return -1; -// } else { -// // Extract report -// int irpt = igrid4 - MAXGRID4; -// -// // Check special cases first (irpt > 0 always) -// switch (irpt) { -// case 1: -// extra[0] = '\0'; -// break; -// case 2: -// strcpy(dst, "RRR"); -// break; -// case 3: -// strcpy(dst, "RR73"); -// break; -// case 4: -// strcpy(dst, "73"); -// break; -// default: -// // Extract signal report as a two digit number with a + or - sign -// if (ir > 0) { -// *dst++ = 'R'; // Add "R" before report -// } -// int_to_dd(dst, irpt - 35, 2, true); -// break; -// } -// // if (irpt >= 2 && strncmp(call_to, "CQ", 2) == 0) return -1; -// } -// -// return 0; // Success -//} - - -int unpack_type1_(const uint8_t *a77, message_t *message) { - uint32_t n28a, n28b; - uint16_t igrid4; - uint8_t ir; - - // Extract packed fields - n28a = (a77[0] << 21); - n28a |= (a77[1] << 13); - n28a |= (a77[2] << 5); - n28a |= (a77[3] >> 3); - n28b = ((a77[3] & 0x07) << 26); - n28b |= (a77[4] << 18); - n28b |= (a77[5] << 10); - n28b |= (a77[6] << 2); - n28b |= (a77[7] >> 6); - ir = ((a77[7] & 0x20) >> 5); - igrid4 = ((a77[7] & 0x1F) << 10); - igrid4 |= (a77[8] << 2); - igrid4 |= (a77[9] >> 6); - - - - // Unpack both callsigns - if (unpack_callsign(n28a >> 1, n28a & 0x01, message->i3, message->call_to,&message->call_to_hash) < 0) { - return -1; - } - if (unpack_callsign(n28b >> 1, n28b & 0x01, message->i3, message->call_de,&message->call_de_hash) < 0) { - return -2; - } - // Fix "CQ_" to "CQ " -> already done in unpack_callsign() - - // TODO: add to recent calls - // if (call_to[0] != '<' && strlen(call_to) >= 4) { - // save_hash_call(call_to) - // } - // if (call_de[0] != '<' && strlen(call_de) >= 4) { - // save_hash_call(call_de) - // } - - char *dst = message->extra; - message->report=-100;//-100说明没有信号报告 - message->maidenGrid[0]='\0'; - if (igrid4 <= MAXGRID4) { - // // 解码4字符的梅登海德网格,!!!网格数据优先于信号报告 - if (ir > 0) { - // In case of ir=1 add an "R" before grid - dst = strcpy(dst, "R "); - dst += 3; - } - - uint16_t n = igrid4; - dst[4] = '\0'; - dst[3] = '0' + (n % 10); - n /= 10; - dst[2] = '0' + (n % 10); - n /= 10; - dst[1] = 'A' + (n % 18); - n /= 18; - dst[0] = 'A' + (n % 18); - strcpy(message->maidenGrid, dst);//把网格内容复制出来 - - - // if (ir > 0 && strncmp(call_to, "CQ", 2) == 0) return -1; - } else { - // 解码信号报告,数值-35是报告。 - // 网格数据优先于信号报告 - message->report = igrid4 - MAXGRID4 - 35; - - // Check special cases first (irpt > 0 always) - switch (message->report) { - case 1 - 35: - message->extra[0] = '\0'; - break; - case 2 - 35: - strcpy(dst, "RRR"); - break; - case 3 - 35: - strcpy(dst, "RR73"); - break; - case 4 - 35: - strcpy(dst, "73"); - break; - default: - // Extract signal report as a two digit number with a + or - sign - if (ir > 0) { - *dst++ = 'R'; // Add "R" before report - } - int_to_dd(dst, message->report, 2, true); - break; - } - // if (irpt >= 2 && strncmp(call_to, "CQ", 2) == 0) return -1; - } - - - - return 0; // Success -} - - -int unpack_text(const uint8_t *a71, char *text) { - // TODO: test - uint8_t b71[9]; - - // Shift 71 bits right by 1 bit, so that it's right-aligned in the byte array - uint8_t carry = 0; - for (int i = 0; i < 9; ++i) { - b71[i] = carry | (a71[i] >> 1); - carry = (a71[i] & 1) ? 0x80 : 0; - } - - char c14[14]; - c14[13] = 0; - for (int idx = 12; idx >= 0; --idx) { - // Divide the long integer in b71 by 42 - uint16_t rem = 0; - for (int i = 0; i < 9; ++i) { - rem = (rem << 8) | b71[i]; - b71[i] = rem / 42; - rem = rem % 42; - } - c14[idx] = charn(rem, 0); - } - - strcpy(text, trim(c14)); - return 0; // Success -} - -int unpack_telemetry(const uint8_t *a71, char *telemetry) { - uint8_t b71[9]; - - // Shift bits in a71 right by 1 bit - uint8_t carry = 0; - for (int i = 0; i < 9; ++i) { - b71[i] = (carry << 7) | (a71[i] >> 1); - carry = (a71[i] & 0x01); - } - - // Convert b71 to hexadecimal string - for (int i = 0; i < 9; ++i) { - uint8_t nibble1 = (b71[i] >> 4); - uint8_t nibble2 = (b71[i] & 0x0F); - char c1 = (nibble1 > 9) ? (nibble1 - 10 + 'A') : nibble1 + '0'; - char c2 = (nibble2 > 9) ? (nibble2 - 10 + 'A') : nibble2 + '0'; - telemetry[i * 2] = c1; - telemetry[i * 2 + 1] = c2; - } - - telemetry[18] = '\0'; - return 0; -} - -//none standard for wsjt-x 2.0 -//by KD8CEC -int unpack_nonstandard(const uint8_t *a77, message_t *message) { - uint32_t n12, iflip, nrpt, icq; - uint64_t n58; - n12 = (a77[0] << 4); //11 ~4 : 8 - n12 |= (a77[1] >> 4); //3~0 : 12 - uint32_t h12=a77[0]; - - - - - n58 = ((uint64_t) (a77[1] & 0x0F) << 54); //57 ~ 54 : 4 - n58 |= ((uint64_t) a77[2] << 46); //53 ~ 46 : 12 - n58 |= ((uint64_t) a77[3] << 38); //45 ~ 38 : 12 - n58 |= ((uint64_t) a77[4] << 30); //37 ~ 30 : 12 - n58 |= ((uint64_t) a77[5] << 22); //29 ~ 22 : 12 - n58 |= ((uint64_t) a77[6] << 14); //21 ~ 14 : 12 - n58 |= ((uint64_t) a77[7] << 6); //13 ~ 6 : 12 - n58 |= ((uint64_t) a77[8] >> 2); //5 ~ 0 : 765432 10 - - - iflip = (a77[8] >> 1) & 0x01; //76543210 - nrpt = ((a77[8] & 0x01) << 1); - nrpt |= (a77[9] >> 7); //76543210 - icq = ((a77[9] >> 6) & 0x01); - - - if (iflip==1){//h1==1 - message->call_de_hash.hash12=n12; - } else{ - message->call_to_hash.hash12=n12; - } - - char c11[12]; - c11[11] = '\0'; - - for (int i = 10; /* no condition */; --i) { - c11[i] = charn(n58 % 38, 5); - if (i == 0) - break; - n58 /= 38; - } - - char call_3[15]; - // should replace with hash12(n12, call_3); - strcpy(call_3, "<...>"); - // call_3[0] = '<'; - // int_to_dd(call_3 + 1, n12, 4, false); - // call_3[5] = '>'; - // call_3[6] = '\0'; - - char *call_1 = (iflip) ? c11 : call_3; - char *call_2 = (iflip) ? call_3 : c11; - //save_hash_call(c11_trimmed); - - - - if (icq == 0) { - strcpy(message->call_to, trim(call_1)); - if (nrpt == 1) - strcpy(message->extra, "RRR"); - else if (nrpt == 2) - strcpy(message->extra, "RR73"); - else if (nrpt == 3) - strcpy(message->extra, "73"); - else { - message->extra[0] = '\0'; - } - } else { - strcpy(message->call_to, "CQ"); - message->extra[0] = '\0'; - } - strcpy(message->call_de, trim(call_2)); - - return 0; -} - -//int unpack77_fields(const uint8_t *a77, char *call_to, char *call_de, char *extra) { -// call_to[0] = call_de[0] = extra[0] = '\0'; -// -// // Extract i3 (bits 74..76) -// uint8_t i3 = (a77[9] >> 3) & 0x07; -// -// if (i3 == 0) { -// // Extract n3 (bits 71..73) -// uint8_t n3 = ((a77[8] << 2) & 0x04) | ((a77[9] >> 6) & 0x03); -// -// if (n3 == 0) { -// // 0.0 Free text -// return unpack_text(a77, extra); -// } -// // else if (i3 == 0 && n3 == 1) { -// // // 0.1 K1ABC RR73; W9XYZ -11 28 28 10 5 71 DXpedition Mode -// // } -// // else if (i3 == 0 && n3 == 2) { -// // // 0.2 PA3XYZ/P R 590003 IO91NP 28 1 1 3 12 25 70 EU VHF contest -// // } -// // else if (i3 == 0 && (n3 == 3 || n3 == 4)) { -// // // 0.3 WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ARRL Field Day -// // // 0.4 WA9XYZ KA1ABC R 32A EMA 28 28 1 4 3 7 71 ARRL Field Day -// // } -// else if (n3 == 5) { -// // 0.5 0123456789abcdef01 71 71 Telemetry (18 hex) -// return unpack_telemetry(a77, extra); -// } -// } else if (i3 == 1 || i3 == 2) { -// // Type 1 (standard message) or Type 2 ("/P" form for EU VHF contest) -// return unpack_type1(a77, i3, call_to, call_de, extra); -// } -// // else if (i3 == 3) { -// // // Type 3: ARRL RTTY Contest -// // } -// else if (i3 == 4) { -// // // Type 4: Nonstandard calls, e.g. PJ4/KA1ABC RR73 -// // // One hashed call or "CQ"; one compound or nonstandard call with up -// // // to 11 characters; and (if not "CQ") an optional RRR, RR73, or 73. -// return unpack_nonstandard(a77, call_to, call_de, extra); -// } -// // else if (i3 == 5) { -// // // Type 5: TU; W9XYZ K1ABC R-09 FN 1 28 28 1 7 9 74 WWROF contest -// // } -// -// // unknown type, should never get here -// return -1; -//} -// - - - - -//int unpack77(const uint8_t* a77, char* message) -//{ -// char call_to[14]; -// char call_de[14]; -// char extra[19]; -// -// //// TO-DO:在此处修改。把Message的格式修改成i3,n3,from,to,extra,方便消息显示。 -// int rc = unpack77_fields(a77, call_to, call_de, extra); -// if (rc < 0) -// return rc; -// -// // int msg_sz = strlen(call_to) + strlen(call_de) + strlen(extra) + 2; -// char* dst = message; -// -// dst[0] = '\0'; -// -// if (call_to[0] != '\0') -// { -// // dst = stpcpy(dst, call_to); //除错 -// dst = strcpy(dst, call_to); -// dst +=strlen(call_to); -// *dst++ = ' '; -// } -// -// if (call_de[0] != '\0') -// { -// // dst = stpcpy(dst, call_de);//除错 -// dst = strcpy(dst, call_de); -// dst +=strlen(call_de); -// *dst++ = ' '; -// } -// -// // dst = stpcpy(dst, extra);//除错 -// dst = strcpy(dst, extra); -// dst += strlen(extra); -// *dst = '\0'; -// -// return 0; -//} - - - -int unpack77_fields_(const uint8_t *a77, message_t *message) { - - //获取指令类型i3.n3 - message->i3 = (a77[9] >> 3) & 0x07; - message->n3 = 0; - - if (message->i3 == 0) { - //n3指令 - message->n3 = ((a77[8] << 2) & 0x04) | ((a77[9] >> 6) & 0x03); - - if (message->n3 == 0) { - // 0.0 Free text - return unpack_text(a77, message->extra); - } - // else if (i3 == 0 && n3 == 1) { - // // 0.1 K1ABC RR73; W9XYZ -11 28 28 10 5 71 DXpedition Mode - // } - // else if (i3 == 0 && n3 == 2) { - // // 0.2 PA3XYZ/P R 590003 IO91NP 28 1 1 3 12 25 70 EU VHF contest - // } - // else if (i3 == 0 && (n3 == 3 || n3 == 4)) { - // // 0.3 WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ARRL Field Day - // // 0.4 WA9XYZ KA1ABC R 32A EMA 28 28 1 4 3 7 71 ARRL Field Day - // } - else if (message->n3 == 5) { - // 0.5 0123456789abcdef01 71 71 Telemetry (18 hex) - return unpack_telemetry(a77, message->extra); - } - } else if (message->i3 == 1 || message->i3 == 2) { - // Type 1 (standard message) or Type 2 ("/P" form for EU VHF contest) - return unpack_type1_(a77, message); - } - // else if (i3 == 3) { - // // Type 3: ARRL RTTY Contest - // } - else if (message->i3 == 4) { - // // Type 4: Nonstandard calls, e.g. PJ4/KA1ABC RR73 - // // One hashed call or "CQ"; one compound or nonstandard call with up - // // to 11 characters; and (if not "CQ") an optional RRR, RR73, or 73. - //return unpack_nonstandard(a77, message->call_to, message->call_de, message->extra); - return unpack_nonstandard(a77, message); - } - // else if (i3 == 5) { - // // Type 5: TU; W9XYZ K1ABC R-09 FN 1 28 28 1 7 9 74 WWROF contest - // } - - // unknown type, should never get here - return -1; - - -} - - -//把77位消息解码到message_t -int unpackToMessage_t(const uint8_t *a77, message_t *message) { - //char call_to[14]; - //char call_de[14]; - //char extra[19]; - - //// TO-DO:在此处修改。把Message的格式修改成i3,n3,from,to,extra,方便消息显示。 - int rc = unpack77_fields_(a77, message); - - if (rc < 0) - return rc; - - - // int msg_sz = strlen(call_to) + strlen(call_de) + strlen(extra) + 2; - char *dst = message->text; - - message->text[0] = '\0'; - - if (message->call_to[0] != '\0') { - // dst = stpcpy(dst, call_to); //除错 - dst = strcpy(dst, message->call_to); - dst += strlen(message->call_to); - *dst++ = ' '; - } - - if (message->call_de[0] != '\0') { - // dst = stpcpy(dst, call_de);//除错 - dst = strcpy(dst, message->call_de); - dst += strlen(message->call_de); - *dst++ = ' '; - } - - // dst = stpcpy(dst, extra);//除错 - dst = strcpy(dst, message->extra); - dst += strlen(message->extra); - *dst = '\0'; - - return 0; -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8/unpack.h b/ft8CN/app/src/main/cpp/ft8/unpack.h deleted file mode 100644 index 2c716f6..0000000 --- a/ft8CN/app/src/main/cpp/ft8/unpack.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _INCLUDE_UNPACK_H_ -#define _INCLUDE_UNPACK_H_ - -#include -#include "decode.h" -// field1 - at least 14 bytes -// field2 - at least 14 bytes -// field3 - at least 7 bytes - -//int unpack77_fields(const uint8_t* a77, char* field1, char* field2, char* field3); - -// message should have at least 35 bytes allocated (34 characters + zero terminator) -/// 消息应至少分配35个字节(34个字符+零终止符) -int unpack77(const uint8_t* a77, char* message); - -//新增的函数,把消息解码成message_t -int unpackToMessage_t(const uint8_t* a77, message_t* message); - -#endif // _INCLUDE_UNPACK_H_ diff --git a/ft8CN/app/src/main/cpp/ft8Decoder.c b/ft8CN/app/src/main/cpp/ft8Decoder.c deleted file mode 100644 index 5f59ad1..0000000 --- a/ft8CN/app/src/main/cpp/ft8Decoder.c +++ /dev/null @@ -1,292 +0,0 @@ -// -// Created by jmsmf on 2022/4/24. -// - -#include "ft8Decoder.h" - -#define LOG_LEVEL LOG_INFO -//decoder_t decoder; - -// Hanning窗(汉宁窗)适用于95%的情况。 -static float hann_i(int i, int N) { - float x = sinf((float) M_PI * i / N); - return x * x; -} - -//把信号FFT,在解码decoder中减去信号 -void signalToFFT(decoder_t *decoder, float signal[], int sample_rate) { - int nfft = kFreq_osr * (int) (sample_rate * FT8_SYMBOL_PERIOD);//nfft=一个FSK符号的样本数*频率过采样率 - float fft_norm = 2.0f / nfft;//< FFT归一化因子。FFT normalization factor - float *window = (float *) malloc( - nfft * sizeof(window[0]));// 申请窗空间,大小是fft块大小*sizeof(me->windows[0]) - for (int i = 0; i < nfft; ++i) { - window[i] = hann_i(i, nfft);// 使用Hanning窗 - // window[i] = blackman_i(i, me->nfft);// Blackman-Harris窗 - // window[i] = hamming_i(i, me->nfft);// Hamming窗 - // window[i] = (i < len_window) ? hann_i(i, len_window) : 0; - } - - // 申请当前STFT(短时傅氏变换)分析框架(nfft样本)的空间。 - //last_frame:申请傅里叶变换分析框架用的(nfft样本)。 - // 空间大小=时域数据量*数据类型占用的空间=一个FSK符号占用的采样数据量*频率过采样率=12000*0.16*2*SizeOf(float) - float *last_frame = (float *) malloc(nfft * sizeof(last_frame[0])); - - size_t fft_work_size; - // 第一步,获取可以用的FFT工作区域的大小到fft_work_size - //nfft=一个FSK符号的样本数*频率过采样率=0.16*12000*2=3840 - kiss_fftr_alloc(nfft, 0, 0, &fft_work_size); - - // 申请FFT工作区域的内存,38676个 - void *fft_work = malloc(fft_work_size); - //第二步,返回fft的设置信息 - kiss_fftr_cfg fft_cfg = kiss_fftr_alloc(nfft, 0, fft_work, &fft_work_size); - - - free(fft_work); - free(window); - free(last_frame); - -} - -void *init_decoder(int64_t utcTime, int sample_rate, int num_samples, bool is_ft8) { - - //此处,改为一个变量,不是以指针,申请新内存的方式处理了。 - //其实这种方式要注意一个问题,在一个周期之内,必须解码完毕,否则新的解码又要开始了 - - //此处不用申请内存的方式解决 -// decoder.utcTime = utcTime; -// decoder.num_samples = num_samples; -// decoder.mon_cfg = (monitor_config_t) { -// .f_min = 100,//分析的最低频率边界 -// .f_max = 3000,//分析的最大频率边界 -// .sample_rate = sample_rate,//采样率12000Hz -// .time_osr = kTime_osr,//时间过采样率=2 -// .freq_osr = kFreq_osr,//频率过采样率=2 -// .protocol = is_ft8 ? PROTO_FT8 : PROTO_FT4 -// }; -// //LOGD("Init decoder . address : %lld", decoder); -// monitor_init(&decoder.mon, &decoder.mon_cfg); -// -// -// return &decoder; - - //此部分,是老的解决方式,是动态申请内存。 - decoder_t *decoder; - decoder = malloc(sizeof(decoder_t)); - decoder->utcTime = utcTime; - decoder->num_samples = num_samples; - decoder->mon_cfg = (monitor_config_t) { - .f_min = 100,//分析的最低频率边界 - .f_max = 3000,//分析的最大频率边界 - .sample_rate = sample_rate,//采样率12000Hz - .time_osr = kTime_osr,//时间过采样率=2 - .freq_osr = kFreq_osr,//频率过采样率=2 - .protocol = is_ft8 ? PROTO_FT8 : PROTO_FT4 - }; - - decoder->kLDPC_iterations = fast_kLDPC_iterations; - //LOGD("Init decoder . address : %lld", decoder); - monitor_init(&decoder->mon, &decoder->mon_cfg); - - return decoder; -} - -void delete_decoder(decoder_t *decoder) { - //LOGD("Free decoder , address:%lld", decoder); - monitor_free(&decoder->mon); - free(decoder); -} - -void decoder_monitor_press(float signal[], decoder_t *decoder) { - - // 以每一个FSK符号占用的数据量为单位循环。 - //block_size每个符号的样本数12000*0.16=1920 - - for (int frame_pos = 0; - frame_pos + decoder->mon.block_size <= - decoder->num_samples; frame_pos += decoder->mon.block_size) { - // Process the waveform data frame by frame - you could have a live loop here with data from an audio device - // 逐帧处理波形数据,这个位置可以使用音频设备的数据环。 - //以每一个符号时间长度(0.16)内的数据做瀑布数据,最后会形成一个信号量mag数组。 - // mag数组的总长度是:最大符号块数93*时间过采样率2*频率过采样率2*分析块960,也就是Waterfall size = 357120 - //一次调用monitor_process,处理的是一个符号长度的信号量数据,生成2*2*960=3840个mag数据。 - //一共有93个符号的循环,mag数组的大小:2*2*960*93=357120 - //mag数据保存在monitor.wf.mag中。 - monitor_process(&decoder->mon, signal + frame_pos); - } - - // /data/user/0/com.bg7yoz.ft8cn/cache/ - - //把fft数据保存下来 - //FILE * fp2 = fopen("/data/user/0/com.bg7yoz.ft8cn/cache/fft001.txt", "w");//打开输出文件 - //for (int i = 0; i < 3840; ++i) { - // for (int j = 0; j < 93; ++j) { - // fprintf (fp2,"%d\n", decoder->mon.wf.mag[i*j]);//把数组a逆序写入到输出文件当中 - // } - //} - //fclose(fp2);//关闭输出文件,相当于保存 - - - - LOG(LOG_DEBUG, "Waterfall accumulated %d symbols\n", decoder->mon.wf.num_blocks);//积累的信号 - LOG(LOG_INFO, "Max magnitude: %.1f dB\n", decoder->mon.max_mag);//最大信号值dB - -} - -int decoder_ft8_find_sync(decoder_t *decoder) { - //检测ft8信号,kMax_candidates最大候选人数量=120,candidate_list候选人列表(size=120),kMin_score候选人的最低同步分数阈值=10 - decoder->num_candidates = ft8_find_sync(&decoder->mon.wf, kMax_candidates, - decoder->candidate_list, kMin_score); - LOG(LOG_DEBUG, "ft8_find_sync finished. %d candidates\n", decoder->num_candidates); - - - // Hash table for decoded messages (to check for duplicates) - // 解码消息的哈希表(用于检查重复项) - //int num_decoded = 0; - //message_t decoded[kMax_decoded_messages];//kMax_decoded_messages=50 - // 哈希表指针列表(指针数组) - //message_t *decoded_hashtable[kMax_decoded_messages]; - - // Initialize hash table pointers - // 初始化哈希表指针列表 - for (int i = 0; i < kMax_decoded_messages; ++i) { - decoder->decoded_hashtable[i] = NULL; - } - return decoder->num_candidates; -} - - -ft8_message decoder_ft8_analysis(int idx, decoder_t *decoder) { - - ft8_message ft8Message; - ft8Message.isValid = false; - ft8Message.utcTime = decoder->utcTime; - // 候选列表candidate_list,已经从ft8_fing_sync获得。 - ft8Message.candidate = decoder->candidate_list[idx]; - - - if (ft8Message.candidate.score < kMin_score) { - //ft8Message.isValid = false; - return ft8Message; - } - - ft8Message.freq_hz = - (ft8Message.candidate.freq_offset + - (float) ft8Message.candidate.freq_sub / decoder->mon.wf.freq_osr) / - decoder->mon.symbol_period; - ft8Message.time_sec = - ((ft8Message.candidate.time_offset + (float) ft8Message.candidate.time_sub) - * decoder->mon.symbol_period) / decoder->mon.wf.time_osr; - - //ft8Message.snr=ft8Message.candidate.snr; - //这是原来代码的时间偏移,同样的数据与JTDX的时间差异很大,改用上面的代码,稍微接近一些 - //(ft8Message.candidate.time_offset + - //(float) ft8Message.candidate.time_sub / decoder->mon.wf.time_osr) * - //decoder->mon.symbol_period; - - - // 如果解码失败,跳到下一次循环 kLDPC_iterations=20 LDPC(低密度奇偶校验)的迭代次数。 - if (!ft8_decode(&decoder->mon.wf, &ft8Message.candidate - //, &ft8Message.message, kLDPC_iterations, - , &ft8Message.message, decoder->kLDPC_iterations, - &ft8Message.status)) { - // printf("000000 %3d %+4.2f %4.0f ~ ---\n", cand->score, time_sec, freq_hz); - if (ft8Message.status.ldpc_errors > 0) { - // LDPC:低密度奇偶校验 - LOG(LOG_DEBUG, "LDPC decode: %d errors\n", ft8Message.status.ldpc_errors); - } else if (ft8Message.status.crc_calculated != ft8Message.status.crc_extracted) { - LOG(LOG_DEBUG, "CRC mismatch!\n"); - } else if (ft8Message.status.unpack_status != 0) { - LOG(LOG_DEBUG, "Error while unpacking!\n"); - } - //ft8Message.isValid = false; - return ft8Message; - } - - ft8Message.snr = ft8Message.candidate.snr; - - LOG(LOG_DEBUG, "Checking hash table for %4.1fs / %4.1fHz [%d]...\n", ft8Message.time_sec, - ft8Message.freq_hz, - ft8Message.candidate.score); - - int idx_hash = - ft8Message.message.hash % kMax_decoded_messages;//为啥是取模?稍后研究kMax_decoded_messages=50 - - bool found_empty_slot = false; - bool found_duplicate = false; - //检查哈希表,只有空插槽,或重复插槽(哈希值相同,并且消息相同) - do { - if (decoder->decoded_hashtable[idx_hash] == NULL) { - LOG(LOG_DEBUG, "Found an empty slot\n"); - found_empty_slot = true; - } else if ((decoder->decoded_hashtable[idx_hash]->hash == ft8Message.message.hash) && - (0 == - strcmp(decoder->decoded_hashtable[idx_hash]->text, ft8Message.message.text))) { - LOG(LOG_DEBUG, "Found a duplicate [%s]\n", ft8Message.message.text); - found_duplicate = true; - } else { - LOG(LOG_DEBUG, "Hash table clash!\n"); - // Move on to check the next entry in hash table - idx_hash = (idx_hash + 1) % kMax_decoded_messages; - } - } while (!found_empty_slot && !found_duplicate); - - - if (found_empty_slot) { - // Fill the empty hashtable slot - memcpy(&decoder->decoded[idx_hash], &ft8Message.message, sizeof(ft8Message.message)); - decoder->decoded_hashtable[idx_hash] = &decoder->decoded[idx_hash]; - ++decoder->num_decoded; - - - ft8Message.isValid = true; - - LOG_PRINTF("%3d %+4.2f %4.0f ~ %s report:%d grid:%s,toHash:%x,fromHash:%x", - ft8Message.snr, - ft8Message.time_sec, ft8Message.freq_hz, ft8Message.message.text, - ft8Message.message.report, ft8Message.message.maidenGrid, - ft8Message.message.call_to_hash.hash12, ft8Message.message.call_de_hash.hash12); - } - memcpy(decoder->a91, ft8Message.message.a91, FTX_LDPC_K_BYTES); - return ft8Message; -} - -void decoder_ft8_reset(decoder_t *decoder, long utcTime, int num_samples) { - LOG(LOG_DEBUG, "Monitor is resetting..."); - decoder->mon.wf.num_blocks = 0; - //decoder->mon.max_mag = 0; - decoder->mon.max_mag = -120.0f; - decoder->utcTime = utcTime; - decoder->num_samples = num_samples; -} - -/** - * 对174码,重新编生成79码 - * @param a174 174个int - * @param a79 79个int - */ -void recode(int a174[], int a79[]) { - int i174 = 0; - //int costas[] = { 3, 1, 4, 0, 6, 5, 2 }; - //std::vector out79; - for (int i79 = 0; i79 < 79; i79++) { - if (i79 < 7) { - //out79.push_back(costas[i79]); - a79[i79] = kFT8CostasPattern[i79]; - } else if (i79 >= 36 && i79 < 36 + 7) { - //out79.push_back(costas[i79-36]); - a79[i79] = kFT8CostasPattern[i79 - 36]; - } else if (i79 >= 72) { - //out79.push_back(costas[i79-72]); - a79[i79] = kFT8CostasPattern[i79 - 72]; - } else { - int sym = (a174[i174 + 0] << 2) | (a174[i174 + 1] << 1) | (a174[i174 + 2] << 0); - i174 += 3; - // gray code - int map[] = {0, 1, 3, 2, 5, 6, 4, 7}; - sym = map[sym]; - //out79.push_back(sym); - a79[i79] = sym; - } - } -}; diff --git a/ft8CN/app/src/main/cpp/ft8Decoder.h b/ft8CN/app/src/main/cpp/ft8Decoder.h deleted file mode 100644 index d8e88e1..0000000 --- a/ft8CN/app/src/main/cpp/ft8Decoder.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Created by jmsmf on 2022/4/24. -// -// -#include "ft8/decode.h" -#include "monitor_opr.h" -#include "ft8/constants.h" -#include - -//const int kMin_score = 10; // 候选人的最低同步分数阈值。Minimum sync score threshold for candidates -const int kMax_candidates = 120;//最大候选人数量 - -const int kMax_decoded_messages = 100; -//const int kMax_decoded_messages = 50; -const int kLDPC_iterations = 20;//LDPC(低密度奇偶校验)的迭代次数,数值越大,精度越高,速度越慢 -const int deep_kLDPC_iterations = 200;//LDPC(低密度奇偶校验)的迭代次数 -const int fast_kLDPC_iterations = 20;//LDPC(低密度奇偶校验)的迭代次数 - -typedef struct { - long long utcTime;//UTC时间 - int num_samples;//采样率 - int num_candidates; - int num_decoded; - message_t decoded[kMax_decoded_messages];//kMax_decoded_messages=50 - // 哈希表指针列表(指针数组) - message_t *decoded_hashtable[kMax_decoded_messages]; - - // Find top candidates by Costas sync score and localize them in time and frequency - // 从科斯塔斯阵列(Costas)寻找最佳候选,并在时间和频率上对其进行本地化。候选数组最大120个 - // candidate_t定义在decode.h - candidate_t candidate_list[kMax_candidates];//kMax_candidates=120 - - monitor_t mon; - monitor_config_t mon_cfg; - uint8_t a91[FTX_LDPC_K_BYTES];//用于生成减法代码的数据 - int kLDPC_iterations;//ldpc 迭代次数,数值越大,精度越高,速度越慢:20或100 -} decoder_t; - -typedef struct { - int64_t utcTime;//消息的UTC时间 - bool isValid;//是否为有效消息 - int snr;//信噪比 - candidate_t candidate;//消息的原始信号数据 - float time_sec;//时间偏移值 - float freq_hz;//频率偏移值 - message_t message;//解码后的消息 - decode_status_t status; -} ft8_message; - -static const int kFreq_osr = 2; // 频率过采样率。Frequency oversampling rate (bin subdivision) -static const int kTime_osr = 2; // 时间过采样率。Time oversampling rate (symbol subdivision) - -//把信号FFT,在解码decoder中减去信号 -void signalToFFT(decoder_t *decoder,float signal[], int sample_rate); -//初始化解码器所需要的参数,最后通过指针的方式传递给java -void *init_decoder(int64_t utcTime, int sample_rate, int num_samples, bool is_ft8); - -void delete_decoder(decoder_t *decoder); - -void decoder_monitor_press(float signal[], decoder_t *decoder); - -int decoder_ft8_find_sync(decoder_t *decoder); - -ft8_message decoder_ft8_analysis(int idx, decoder_t *decoder); - -void decoder_ft8_reset(decoder_t *decoder,long utcTime,int num_samples); - -void recode(int a174[],int a79[]); - diff --git a/ft8CN/app/src/main/cpp/ft8Encoder.c b/ft8CN/app/src/main/cpp/ft8Encoder.c deleted file mode 100644 index 9363e51..0000000 --- a/ft8CN/app/src/main/cpp/ft8Encoder.c +++ /dev/null @@ -1,150 +0,0 @@ -// -// Created by jmsmf on 2022/6/1. -// - -#include "ft8Encoder.h" - -//#define LOG_LEVEL LOG_INFO - -#define FT8_SYMBOL_BT 2.0f /// 符号平滑滤波器带宽因子(BT) -#define FT4_SYMBOL_BT 1.0f /// 符号平滑滤波器带宽因子(BT) -#define GFSK_CONST_K 5.336446f ///< == pi * sqrt(2 / log(2)) - - -/// 生成高斯平滑脉冲 -/// 脉冲理论上是无限长的,然而,这里它被截断为符号长度的3倍。 -/// 这意味着脉冲阵列必须有空间容纳3*n_spsym元素。 -/// @param[in] n_spsym 每个符号的样本数 Number of samples per symbol -/// @param[in] b 形状参数(为FT8/FT4定义的值) -/// @param[out] pulse 脉冲采样输出阵列 -/// -void gfsk_pulse(int n_spsym, float symbol_bt, float *pulse) { - for (int i = 0; i < 3 * n_spsym; ++i) { - float t = i / (float) n_spsym - 1.5f; - float arg1 = GFSK_CONST_K * symbol_bt * (t + 0.5f); - float arg2 = GFSK_CONST_K * symbol_bt * (t - 0.5f); - pulse[i] = (erff(arg1) - erff(arg2)) / 2; - } -} - - -/// 使用GFSK相位整形合成波形数据。 -/// 输出波形将包含n_sym个符号。 -/// @param[in] symbols 符号(音调)数组 (0-7 for FT8) -/// @param[in] n_sym 符号数组中的符号数 -/// @param[in] f0 符号0的音频频率(赫兹) (载波频率) -/// @param[in] symbol_bt 符号平滑滤波器带宽 (2 for FT8, 1 for FT4) -/// @param[in] symbol_period 符号周期(持续时间),秒 -/// @param[in] signal_rate 合成信号的采样率,赫兹 -/// @param[out] signal 信号波形样本的输出阵列(应为n_sym*n_spsym样本留出空间) -/// -void synth_gfsk(const uint8_t *symbols, int n_sym, float f0, float symbol_bt, float symbol_period, - int signal_rate, float *signal) { - int n_spsym = (int) (0.5f + (float)signal_rate * symbol_period); // 每个符号的样本数12000*0.16=1920 - int n_wave = n_sym * n_spsym; // 输出样本数79*1920=151680 - float hmod = 1.0f; - - - // 计算平滑的频率波形。 - // Length = (nsym+2)*n_spsym samples, 首个和最后一个扩展符号 - float dphi_peak = 2 * M_PI * hmod / n_spsym; - - //此处是与采样率有关,采样率提高后,可能会有闪退的问题 - float *dphi;//此处使用内存申请的方式,而不是原来数组的方式,因为是采样率过高时,会报内存出错。 - dphi = malloc(sizeof(float) * (n_wave + 2 * n_spsym)); - if (dphi==0) return;//内存申请失败 - //float dphi[n_wave + 2 * n_spsym];//原来的方式 - - // 频率上移f0 - for (int i = 0; i < n_wave + 2 * n_spsym; ++i) { - dphi[i] = 2 * M_PI * f0 / signal_rate; - } - - //float pulse[3 * n_spsym]; - float *pulse=(float *) malloc(sizeof(float)*3 * n_spsym); - gfsk_pulse(n_spsym, symbol_bt, pulse); - - for (int i = 0; i < n_sym; ++i) { - int ib = i * n_spsym; - for (int j = 0; j < 3 * n_spsym; ++j) { - dphi[j + ib] += dphi_peak * symbols[i] * pulse[j]; - } - } - // 在开头和结尾添加伪符号,音调值分别等于第一个符号和最后一个符号 - for (int j = 0; j < 2 * n_spsym; ++j) { - dphi[j] += dphi_peak * pulse[j + n_spsym] * symbols[0]; - dphi[j + n_sym * n_spsym] += dphi_peak * pulse[j] * symbols[n_sym - 1]; - } - // 计算并插入音频波形 - float phi = 0; - for (int k = 0; k < n_wave; ++k) { // 不包括虚拟符号 - signal[k] = sinf(phi); - phi = fmodf(phi + dphi[k + n_spsym], 2 * M_PI); - } - // 对第一个和最后一个符号应用封套成形,此处是前后增加斜坡函数, - int n_ramp = n_spsym / 8;//240个样本,20毫秒,T/8 - for (int i = 0; i < n_ramp; ++i) { - float env = (1 - cosf(2 * M_PI * i / (2 * n_ramp))) / 2; - signal[i] *= env; - signal[n_wave - 1 - i] *= env; - } - free(pulse); - free(dphi);//要释放掉内存 -} - -//此代码已经弃用 -void generateFt8ToBuffer(char *message, float frequency, short *buffer) { -// 首先,将文本数据打包为二进制消息 - uint8_t packed[FTX_LDPC_K_BYTES];//91位,包括CRC。 - int rc = pack77(message, packed);//生成数据 - if (rc < 0) { - //LOGE("Cannot parse message!\n"); - //LOGE("RC = %d\n", rc); - return; - } - - - //int num_tones = FT8_NN;//符号数量:FT8是79个,FT4是105个。 - //float symbol_period = FT8_SYMBOL_PERIOD;//FT8_SYMBOL_PERIOD=0.160f - float symbol_bt = FT8_SYMBOL_BT;//FT8_SYMBOL_BT=2.0f - float slot_time = FT8_SLOT_TIME;//FT8_SLOT_TIME=15f - - // 其次,将二进制消息编码为FSK音调序列 - uint8_t tones[FT8_NN]; // 79音调(符号)数组 - ft8_encode(packed, tones); - - - - // 第三,将FSK音调转换为音频信号b - //int sample_rate = FT8_SAMPLE_RATE;//采样率 - int num_samples = (int) (0.5f + FT8_NN * FT8_SYMBOL_PERIOD * - FT8_SAMPLE_RATE); // 数据信号中的采样数0.5+79*0.16*12000 - //int num_silence = (slot_time * sample_rate - num_samples) / 2; // 两端填充静音到15秒(15*12000-num_samples)/2(1.18秒的样本数) - int num_silence = 20;//把前面的静音时长缩短为20毫秒,留出时间给解码 - //int num_total_samples = num_silence + num_samples + num_silence; // 填充信号中的样本数2.36秒+12.64秒=15秒的样本数 - float signal[Ft8num_samples]; - //Ft8num_sampleFT8声音的总采样数,不是字节数。15*12000 - for (int i = 0; i < Ft8num_samples; i++)//把数据全部静音。 - { - signal[i] = 0; - //buffer[i + num_samples + num_silence] = 0; - } - - // 合成波形数据(信号)并将其保存为WAV文件 - synth_gfsk(tones, FT8_NN, frequency, symbol_bt, FT8_SYMBOL_PERIOD, FT8_SAMPLE_RATE, - signal + num_silence); - - - for (int i = 0; i < Ft8num_samples; i++) { - float x = signal[i]; - if (x > 1.0) - x = 1.0; - else if (x < -1.0) - x = -1.0; - buffer[i] = (short) (0.5 + (x * 32767.0)); - } - - - //save_wav(signal, num_total_samples, sample_rate, wav_path); - -} diff --git a/ft8CN/app/src/main/cpp/ft8Encoder.h b/ft8CN/app/src/main/cpp/ft8Encoder.h deleted file mode 100644 index b33cdac..0000000 --- a/ft8CN/app/src/main/cpp/ft8Encoder.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by jmsmf on 2022/6/1. -// - -#ifndef FT8CN_FT8ENCODER_H -#define FT8CN_FT8ENCODER_H - -#endif //FT8CN_FT8ENCODER_H -#include -#include -#include -#include -#include - -#include "common/common.h" -//#include "common/wave.h" -#include "common/debug.h" -#include "ft8/pack.h" -#include "ft8/encode.h" -#include "ft8/constants.h" - -const int Ft8num_samples = 15*12000;//FT8采样数,不是字节数,16bit,字节数要乘以2 -//void generateFt8ToFile(char* message,float frequency,char* wav_path,bool is_ft4); -void generateFt8ToBuffer(char* message,float frequency,short * buffer); -void synth_gfsk(const uint8_t* symbols, int n_sym, float f0, float symbol_bt, float symbol_period, int signal_rate, float* signal); \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8Listener.cpp b/ft8CN/app/src/main/cpp/ft8Listener.cpp deleted file mode 100644 index 0280973..0000000 --- a/ft8CN/app/src/main/cpp/ft8Listener.cpp +++ /dev/null @@ -1,333 +0,0 @@ -// -// Created by jmsmf on 2022/6/2. -// - -#include -#include - - -extern "C" { -#include "common/debug.h" -#include "ft8Decoder.h" -#include "ft8Encoder.h" -} - -// -////将char类型转换成jstring类型 -//jstring CStr2Jstring(JNIEnv *env, const char *pat) { -// // 定义java String类 strClass -// jclass strClass = (env)->FindClass("java/lang/String"); -// // 获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String -// jmethodID ctorID = (env)->GetMethodID(strClass, "", "([BLjava/lang/String;)V"); -// // 建立byte数组 -// jbyteArray bytes = (env)->NewByteArray((jsize) strlen(pat)); -// // 将char* 转换为byte数组 -// (env)->SetByteArrayRegion(bytes, 0, (jsize) strlen(pat), (jbyte *) pat); -// //设置String, 保存语言类型,用于byte数组转换至String时的参数 -// jstring encoding = (env)->NewStringUTF("GB2312"); -// //将byte数组转换为java String,并输出 -// return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding); -// -//} -// -//char *Jstring2CStr(JNIEnv *env, jstring jstr) { -// char *rtn = NULL; -// jclass clsstring = env->FindClass("java/lang/String"); -// jstring strencode = env->NewStringUTF("GB2312"); -// jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); -// jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); -// jsize alen = env->GetArrayLength(barr); -// jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE); -// if (alen > 0) { -// rtn = (char *) malloc(alen + 1); //new char[alen+1]; -// memcpy(rtn, ba, alen); -// rtn[alen] = 0; -// } -// env->ReleaseByteArrayElements(barr, ba, 0); -// -// return rtn; -//} - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderFt8Reset(JNIEnv *env, jobject thiz, - jlong decoder, jlong utcTime, - jint num_samples) { - decoder_t *dd; - dd = (decoder_t *) decoder; - decoder_ft8_reset(dd, utcTime, num_samples); - //dd->utcTime=utcTime; -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DeleteDecoder(JNIEnv *env, jobject, - jlong decoder) { - decoder_t *dd; - dd = (decoder_t *) decoder; - delete_decoder(dd); -} -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderFt8Analysis(JNIEnv *env, jobject, - jint idx, - jlong decoder, - jobject ft8Message) { - decoder_t *dd; - dd = (decoder_t *) decoder; - - - ft8_message message = decoder_ft8_analysis(idx, dd); - - - jclass objectClass = env->FindClass("com/bg7yoz/ft8cn/Ft8Message"); - - jfieldID utcTime = env->GetFieldID(objectClass, "utcTime", "J"); - jfieldID isValid = env->GetFieldID(objectClass, "isValid", "Z"); - jfieldID time_sec = env->GetFieldID(objectClass, "time_sec", "F"); - jfieldID freq_hz = env->GetFieldID(objectClass, "freq_hz", "F"); - jfieldID score = env->GetFieldID(objectClass, "score", "I"); - jfieldID snr = env->GetFieldID(objectClass, "snr", "I"); - jfieldID messageHash = env->GetFieldID(objectClass, "messageHash", "I"); - env->SetBooleanField(ft8Message, isValid, message.isValid); - - jfieldID i3 = env->GetFieldID(objectClass, "i3", "I"); - jfieldID n3 = env->GetFieldID(objectClass, "n3", "I"); - jfieldID callsignFrom = env->GetFieldID(objectClass, "callsignFrom", "Ljava/lang/String;"); - jfieldID callsignTo = env->GetFieldID(objectClass, "callsignTo", "Ljava/lang/String;"); - jfieldID extraInfo = env->GetFieldID(objectClass, "extraInfo", "Ljava/lang/String;"); - jfieldID maidenGrid = env->GetFieldID(objectClass, "maidenGrid", "Ljava/lang/String;"); - jfieldID report = env->GetFieldID(objectClass, "report", "I"); - jfieldID callFromHash10 = env->GetFieldID(objectClass, "callFromHash10", "J"); - jfieldID callFromHash12 = env->GetFieldID(objectClass, "callFromHash12", "J"); - jfieldID callFromHash22 = env->GetFieldID(objectClass, "callFromHash22", "J"); - jfieldID callToHash10 = env->GetFieldID(objectClass, "callToHash10", "J"); - jfieldID callToHash12 = env->GetFieldID(objectClass, "callToHash12", "J"); - jfieldID callToHash22 = env->GetFieldID(objectClass, "callToHash22", "J"); - - - if (message.isValid) { - - env->SetLongField(ft8Message, utcTime, message.utcTime); - env->SetFloatField(ft8Message, time_sec, message.time_sec); - env->SetFloatField(ft8Message, freq_hz, message.freq_hz); - env->SetIntField(ft8Message, score, message.candidate.score); - env->SetIntField(ft8Message, snr, message.snr); - //env->SetObjectField(ft8Message,messageText,env->NewStringUTF(message.message.text)); - env->SetIntField(ft8Message, messageHash, message.message.hash); - - env->SetIntField(ft8Message, i3, message.message.i3); - env->SetIntField(ft8Message, n3, message.message.n3); - env->SetObjectField(ft8Message, callsignFrom, env->NewStringUTF(message.message.call_de)); - env->SetObjectField(ft8Message, callsignTo, env->NewStringUTF(message.message.call_to)); - env->SetObjectField(ft8Message, extraInfo, env->NewStringUTF(message.message.extra)); - env->SetObjectField(ft8Message, maidenGrid, env->NewStringUTF(message.message.maidenGrid)); - env->SetIntField(ft8Message, report, message.message.report); - env->SetLongField(ft8Message, callFromHash10, - (long long) message.message.call_de_hash.hash10); - env->SetLongField(ft8Message, callFromHash12, - (long long) message.message.call_de_hash.hash12); - env->SetLongField(ft8Message, callFromHash22, - (long long) message.message.call_de_hash.hash22); - env->SetLongField(ft8Message, callToHash10, - (long long) message.message.call_to_hash.hash10); - env->SetLongField(ft8Message, callToHash12, - (long long) message.message.call_to_hash.hash12); - env->SetLongField(ft8Message, callToHash22, - (long long) message.message.call_to_hash.hash22); - - } - return message.isValid; -} -extern "C" -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderFt8FindSync(JNIEnv *env, jobject, - jlong decoder) { - decoder_t *dd; - dd = (decoder_t *) decoder; - return decoder_ft8_find_sync(dd); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderMonitorPress(JNIEnv *env, jobject, - jintArray buffer, - jlong decoder) { - decoder_t *dd; - dd = (decoder_t *) decoder; - - - // jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(buffer, NULL); -// decoder_monitor_press(arr, dd); - int arr_len = env->GetArrayLength(buffer); - //将java数组复制到c数组中 - auto *c_array = (jint *) malloc(arr_len * sizeof(arr_len)); - - //env->GetFloatArrayRegion(buffer,0,arr_len,c_array); - (*env).GetIntArrayRegion(buffer, 0, arr_len, c_array); - auto *raw_data = (float_t *) malloc(sizeof(float_t) * arr_len); - - for (int i = 0; i < arr_len; i++) { - raw_data[i] = c_array[i] / 32768.0f; - } - - decoder_monitor_press(raw_data, dd); - free(raw_data); - free(c_array); - - - -// jint *arr; -// jint length; -// arr = (*env).GetIntArrayElements(buffer, nullptr); -// length = (*env).GetArrayLength(buffer); -// auto *raw_data = (float_t *) malloc(sizeof(float_t) * length); -// -// for (int i = 0; i < length; i++) { -// raw_data[i] = arr[i] / 32768.0f; -// } -// -// decoder_monitor_press(raw_data, dd); -// -// free(raw_data); - -} -extern "C" -JNIEXPORT jlong JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_InitDecoder(JNIEnv *env, jobject, jlong utcTime, - jint sampleRate, jint num_samples, - jboolean isFt8) { - return (long) init_decoder(utcTime, sampleRate, num_samples, isFt8); -} - - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderMonitorPressFloat(JNIEnv *env, - jobject thiz, - jfloatArray buffer, - jlong decoder) { - decoder_t *dd; - dd = (decoder_t *) decoder; - - -// jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(buffer, NULL); -// decoder_monitor_press(arr, dd); - int arr_len = env->GetArrayLength(buffer); - //将java数组复制到c数组中 - auto *c_array = (jfloat *) malloc(arr_len * sizeof(arr_len)); - - //env->GetFloatArrayRegion(buffer,0,arr_len,c_array); - (*env).GetFloatArrayRegion(buffer, 0, arr_len, c_array); - decoder_monitor_press(c_array, dd); - free(c_array); - -} - -extern "C" -JNIEXPORT jbyteArray JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_DecoderGetA91(JNIEnv *env, jobject thiz, - jlong decoder) { - decoder_t *dd; - dd = (decoder_t *) decoder; - - jbyteArray array; - array = env->NewByteArray(FTX_LDPC_K_BYTES); - - jbyte buf[FTX_LDPC_K_BYTES]; - memcpy(buf, dd->a91, FTX_LDPC_K_BYTES); - - // 使用 setIntArrayRegion 来赋值 - env->SetByteArrayRegion(array, 0, FTX_LDPC_K_BYTES, buf); - return array; -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_FT8SignalListener_setDecodeMode(JNIEnv *env, jobject thiz, - jlong decoder, jboolean is_deep) { - decoder_t *dd; - dd = (decoder_t *) decoder; - if (is_deep) { - dd->kLDPC_iterations = deep_kLDPC_iterations; - } else { - dd->kLDPC_iterations = fast_kLDPC_iterations; - } -} - -/** - * 把频率减去 - * @param dd - * @param index - * @param max_block_size - */ -void setMagToZero(decoder_t * dd ,int index,int max_block_size){ - if (index>0 && indexmon.wf.mag[index]=0; - } -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8listener_ReBuildSignal_doSubtractSignal(JNIEnv *env, jclass clazz, - jlong decoder, - jbyteArray payload, - jint sample_rate, - jfloat frequency, - jfloat time_sec) { - decoder_t *dd; - dd = (decoder_t *) decoder; - - int arr_len = env->GetArrayLength(payload); - //将java数组复制到c数组中 - auto *c_array = (jbyte *) malloc(arr_len * sizeof(arr_len)); - - - //env->GetFloatArrayRegion(buffer,0,arr_len,c_array); - (*env).GetByteArrayRegion(payload, 0, arr_len, c_array); - - uint8_t tones[FT8_NN];// 79音调(符号)数组, - //此处是12个字节(91+7)/8,可以使用a91生成音频 - ft8_encode((uint8_t *) c_array, tones); - - //相当于二维数组,freq优先 - int max_block_size=(int) (FT8_SLOT_TIME / FT8_SYMBOL_PERIOD) * kTime_osr * kFreq_osr - * (int) (sample_rate * FT8_SYMBOL_PERIOD / 2); - LOG_PRINTF("max_block_size:%d",max_block_size); - int block_size = FT8_SYMBOL_PERIOD * dd->mon_cfg.sample_rate;//1920,一个0.08秒的数据块大小,x轴的总长度 - LOG_PRINTF("block_size +++:%d", block_size); - int freq_offset = (int) (frequency * FT8_SYMBOL_PERIOD) * kFreq_osr;//频率的偏移量,x轴 - int time_offset = (int) ((time_sec / FT8_SYMBOL_PERIOD) * kTime_osr+0.5f);// + 0.5);,y轴 - LOG_PRINTF("freq_offset +++:%f,%d", (frequency * FT8_SYMBOL_PERIOD) * kFreq_osr, freq_offset); - LOG_PRINTF("time_offset +++:%f ,%d,time_offset:%d, time_sec:%f, freq_offset:%d, freq:%f", - (time_sec / 0.08), - (int) (time_sec / 0.08 + 0.5), time_offset, time_sec, freq_offset, frequency); - for (int i = 0; i < FT8_NN; ++i) {//y轴自增循环 - int index = (i + time_offset) * 2; - int index1 = index * block_size + freq_offset+tones[i]; - int index2 = (index + 1) * block_size + freq_offset+tones[i]; - int index3 =index1+1; - int index4 =index2+1; - int index5 =index1-1; - int index6 =index2-1; - int index7 =index1-2; - int index8 =index2-2; - int index9 =index1+2; - int index10 =index2+2; - - setMagToZero(dd,index1,max_block_size); - setMagToZero(dd,index2,max_block_size); - setMagToZero(dd,index3,max_block_size); - setMagToZero(dd,index4,max_block_size); - setMagToZero(dd,index5,max_block_size); - setMagToZero(dd,index6,max_block_size); - setMagToZero(dd,index7,max_block_size); - setMagToZero(dd,index8,max_block_size); - setMagToZero(dd,index9,max_block_size); - setMagToZero(dd,index10,max_block_size); - - } - free(c_array); - -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/ft8Spectrum.cpp b/ft8CN/app/src/main/cpp/ft8Spectrum.cpp deleted file mode 100644 index 206d334..0000000 --- a/ft8CN/app/src/main/cpp/ft8Spectrum.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include - -// -// Created by jmsmf on 2022/6/11. -// - -extern "C" { -#include "common/debug.h" -#include "spectrum_data.h" -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumFragment_getFFTData(JNIEnv *env, jobject thiz, jintArray data, - jintArray fft_data) { - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto c_array=(jint *) malloc(arr_len * sizeof(arr_len)); - - env->GetIntArrayRegion(data,0,arr_len,c_array); - auto *raw_data = (float *) malloc(sizeof(float) * arr_len); - for (int i = 0; i < arr_len; i++) { - raw_data[i] = c_array[i] / 32768.0f; - } - - - jint temp[arr_len/2]; - - do_fftr(raw_data,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - free(raw_data); - -// -// jint *arr; -// jint length; -// arr = (*env).GetIntArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// float *raw_data = (float *) malloc(sizeof(float) * length); -// for (int i = 0; i < length; i++) { -// raw_data[i] = arr[i] / 32768.0f; -// } -// -// jint temp[length/2]; -// -// do_fftr(raw_data,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -// free(raw_data); -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumFragment_getFFTDataRaw(JNIEnv *env, jobject thiz, jintArray data, - jintArray fft_data) { - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto c_array=(jint *) malloc(arr_len * sizeof(arr_len)); - - env->GetIntArrayRegion(data,0,arr_len,c_array); - auto *raw_data = (float *) malloc(sizeof(float) * arr_len); - for (int i = 0; i < arr_len; i++) { - raw_data[i] = c_array[i] / 32768.0f; - } - - - jint temp[arr_len/2]; - - do_fftr_raw(raw_data,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - free(raw_data); - - -// -// jint *arr; -// jint length; -// arr = (*env).GetIntArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// float *raw_data = (float *) malloc(sizeof(float) * length); -// for (int i = 0; i < length; i++) { -// raw_data[i] = arr[i] / 32768.0f; -// } -// -// jint temp[length/2]; -// -// do_fftr_raw(raw_data,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -// free(raw_data); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumView_getFFTData(JNIEnv *env, jobject thiz, jintArray data, - jintArray fft_data) { - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto c_array=(jint *) malloc(arr_len * sizeof(arr_len)); - - env->GetIntArrayRegion(data,0,arr_len,c_array); - auto *raw_data = (float *) malloc(sizeof(float) * arr_len); - for (int i = 0; i < arr_len; i++) { - raw_data[i] = c_array[i] / 32768.0f; - } - - - jint temp[arr_len/2]; - - do_fftr(raw_data,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - free(raw_data); - - -// jint *arr; -// jint length; -// arr = (*env).GetIntArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// float *raw_data = (float *) malloc(sizeof(float) * length); -// for (int i = 0; i < length; i++) { -// raw_data[i] = arr[i] / 32768.0f; -// } -// -// jint temp[length/2]; -// -// do_fftr(raw_data,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -// free(raw_data); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumView_getFFTDataRaw(JNIEnv *env, jobject thiz, jintArray data, - jintArray fft_data) { - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto c_array=(jint *) malloc(arr_len * sizeof(arr_len)); - - env->GetIntArrayRegion(data,0,arr_len,c_array); - auto *raw_data = (float *) malloc(sizeof(float) * arr_len); - for (int i = 0; i < arr_len; i++) { - raw_data[i] = c_array[i] / 32768.0f; - } - - - jint temp[arr_len/2]; - - do_fftr_raw(raw_data,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - free(raw_data); - -// jint *arr; -// jint length; -// arr = (*env).GetIntArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// float *raw_data = (float *) malloc(sizeof(float) * length); -// for (int i = 0; i < length; i++) { -// raw_data[i] = arr[i] / 32768.0f; -// } -// -// jint temp[length/2]; -// //jint *fftdata; -// //fftdata=(*env).GetIntArrayElements(fft_data, NULL); -// -// do_fftr_raw(raw_data,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -// free(raw_data); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumFragment_getFFTDataFloat(JNIEnv *env, jobject thiz, - jfloatArray data, jintArray fft_data) { - - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto *c_array=(jfloat *) malloc(arr_len * sizeof(arr_len)); - - env->GetFloatArrayRegion(data,0,arr_len,c_array); - jint temp[arr_len/2]; - - do_fftr(c_array,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - - - -// jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// -// jint temp[length/2]; -// -// do_fftr(arr,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumFragment_getFFTDataRawFloat(JNIEnv *env, jobject thiz, - jfloatArray data, jintArray fft_data) { - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto *c_array=(jfloat *) malloc(arr_len * sizeof(arr_len)); - - env->GetFloatArrayRegion(data,0,arr_len,c_array); - jint temp[arr_len/2]; - - do_fftr_raw(c_array,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - - - -// jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// -// jint temp[length/2]; -// do_fftr_raw(arr,length,temp); - -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumView_getFFTDataFloat(JNIEnv *env, jobject thiz, jfloatArray data, - jintArray fft_data) { - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto *c_array=(jfloat *) malloc(arr_len * sizeof(arr_len)); - - //env->GetFloatArrayRegion(data,0,arr_len,c_array); - (*env).GetFloatArrayRegion(data,0,arr_len,c_array); - jint temp[arr_len/2]; - - do_fftr(c_array,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - free(c_array); - -// jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// -// jint temp[length/2]; -// -// do_fftr(arr,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ui_SpectrumView_getFFTDataRawFloat(JNIEnv *env, jobject thiz, - jfloatArray data, jintArray fft_data) { - - - int arr_len=env->GetArrayLength(data); - //将java数组复制到c数组中 - auto *c_array=(jfloat *) malloc(arr_len * sizeof(arr_len)); - - //env->GetFloatArrayRegion(data,0,arr_len,c_array); - (*env).GetFloatArrayRegion(data,0,arr_len,c_array); - jint temp[arr_len/2]; - - do_fftr_raw(c_array,arr_len,temp); - (*env).SetIntArrayRegion(fft_data,0,arr_len/2,temp); - - free(c_array); - -// jfloat *arr; -// jint length; -// arr = (*env).GetFloatArrayElements(data, NULL); -// length = (*env).GetArrayLength(data); -// -// jint temp[length/2]; -// -// do_fftr_raw(arr,length,temp); -// -// (*env).SetIntArrayRegion(fft_data,0,length/2,temp); -} diff --git a/ft8CN/app/src/main/cpp/generate_ft8.cpp b/ft8CN/app/src/main/cpp/generate_ft8.cpp deleted file mode 100644 index 7d460f1..0000000 --- a/ft8CN/app/src/main/cpp/generate_ft8.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Created by jmsmf on 2022/6/1. -// -#include -#include - -extern "C" { -#include "common/debug.h" -#include "ft8Encoder.h" -#include "ft8/pack.h" -#include "ft8/encode.h" -#include "ft8/hash22.h" -} -#define GFSK_CONST_K 5.336446f ///< == pi * sqrt(2 / log(2)) - -char *Jstring2CStr(JNIEnv *env, jstring jstr) { - char *rtn = nullptr; - jclass clsstring = env->FindClass("java/lang/String"); - jstring strencode = env->NewStringUTF("GB2312"); - jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); - auto barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); - int alen = env->GetArrayLength(barr); - jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE); - if (alen > 0) { - rtn = (char *) malloc(alen + 1); //new char[alen+1]; - memcpy(rtn, ba, alen); - rtn[alen] = 0; - } - env->ReleaseByteArrayElements(barr, ba, 0); - - return rtn; -} - - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_FT8TransmitSignal_GenerateFt8(JNIEnv *env, jobject, - jstring message, - jfloat frequency, - jshortArray buffer) { - jshort *_buffer; - _buffer = (*env).GetShortArrayElements(buffer, nullptr); - char *str=Jstring2CStr(env, message); - generateFt8ToBuffer(str, frequency, _buffer); - (*env).ReleaseShortArrayElements(buffer,_buffer,JNI_COMMIT); - free(str); -} - -extern "C" -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_GenerateFT8_pack77(JNIEnv *env, jclass, jstring msg, - jbyteArray c77) { - jbyte *_buffer; - _buffer = (*env).GetByteArrayElements(c77, nullptr); - char *str=Jstring2CStr(env, msg); - int result=pack77(str,(uint8_t *)_buffer); - (*env).ReleaseByteArrayElements(c77,_buffer,JNI_COMMIT); - free(str); - return result; -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_GenerateFT8_ft8_1encode(JNIEnv *env, jclass clazz, - jbyteArray payload, jbyteArray tones) { - jbyte *_payload; - jbyte *_tones; - _payload = (*env).GetByteArrayElements(payload, nullptr); - _tones = (*env).GetByteArrayElements(tones, nullptr); - ft8_encode((uint8_t *)_payload,(uint8_t *)_tones); - (*env).ReleaseByteArrayElements(payload,_payload,JNI_COMMIT); - (*env).ReleaseByteArrayElements(tones,_tones,JNI_COMMIT); - - -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_GenerateFT8_gfsk_1pulse(JNIEnv *env, jclass clazz, jint n_spsym, - jfloat symbol_bt, jfloatArray pulse) { - jfloat *_pulse; - _pulse=(*env).GetFloatArrayElements(pulse, nullptr); - - for (int i = 0; i < 3 * n_spsym; ++i) - { - float t = i / (float)n_spsym - 1.5f; - float arg1 = GFSK_CONST_K * symbol_bt * (t + 0.5f); - float arg2 = GFSK_CONST_K * symbol_bt * (t - 0.5f); - _pulse[i] = (erff(arg1) - erff(arg2)) / 2; - } - (*env).ReleaseFloatArrayElements(pulse,_pulse,JNI_COMMIT); - -} -extern "C" -JNIEXPORT void JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_GenerateFT8_synth_1gfsk(JNIEnv *env, jclass clazz, - jbyteArray symbols, jint n_sym, jfloat f0, - jfloat symbol_bt, jfloat symbol_period, - jint signal_rate, jfloatArray signal, - jint offset) { - jbyte *_symbols; - jfloat *_signal; - _symbols = (*env).GetByteArrayElements(symbols, nullptr); - _signal = (*env).GetFloatArrayElements(signal, nullptr); - synth_gfsk((uint8_t *)_symbols,n_sym,f0,symbol_bt,symbol_period,signal_rate,_signal+offset); - - (*env).ReleaseByteArrayElements(symbols,_symbols,JNI_COMMIT); - (*env).ReleaseFloatArrayElements(signal,_signal,JNI_COMMIT); - -} -extern "C" -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8signal_FT8Package_getHash12(JNIEnv *env, jclass clazz, jstring callsign) { - char *str=Jstring2CStr(env, callsign); - uint32_t hash=hashcall_12(str); - free(str); - return hash; -} -extern "C" - - -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8transmit_GenerateFT8_packFreeTextTo77(JNIEnv *env, jclass clazz, - jstring msg, jbyteArray c77) { - - jbyte *_buffer; - _buffer = (*env).GetByteArrayElements(c77, nullptr); - char *str=Jstring2CStr(env, msg); - packtext77(str,(uint8_t *)_buffer); - (*env).ReleaseByteArrayElements(c77,_buffer,JNI_COMMIT); - free(str); - return 0; -} -extern "C" -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8signal_FT8Package_getHash10(JNIEnv *env, jclass clazz, jstring callsign) { - char *str=Jstring2CStr(env, callsign); - uint32_t hash=(hashcall_10(str)); - free(str); - return hash; -} -extern "C" -JNIEXPORT jint JNICALL -Java_com_bg7yoz_ft8cn_ft8signal_FT8Package_getHash22(JNIEnv *env, jclass clazz, jstring callsign) { - char *str=Jstring2CStr(env, callsign); - u_int32_t hash=hashcall_22(str); - free(str); - return hash; -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/monitor_opr.c b/ft8CN/app/src/main/cpp/monitor_opr.c deleted file mode 100644 index 8cdaaae..0000000 --- a/ft8CN/app/src/main/cpp/monitor_opr.c +++ /dev/null @@ -1,257 +0,0 @@ -// -// Created by jmsmf on 2022/4/22. -// - -#include "monitor_opr.h" -#include "ft8/constants.h" -//#define LOG_LEVEL LOG_DEBUG -#define LOG_LEVEL LOG_FATAL - - -// FFT转换,采用加窗函数,减少频谱泄露的问题。 -// Hanning窗(汉宁窗)适用于95%的情况。 -static float hann_i(int i, int N) { - float x = sinf((float) M_PI * i / N); - return x * x; -} - -static float hamming_i(int i, int N) { - const float a0 = (float) 25 / 46; - const float a1 = 1 - a0; - - float x1 = cosf(2 * (float) M_PI * i / N); - return a0 - a1 * x1; -} - -static float blackman_i(int i, int N) { - const float alpha = 0.16f; // or 2860/18608 - const float a0 = (1 - alpha) / 2; - const float a1 = 1.0f / 2; - const float a2 = alpha / 2; - - float x1 = cosf(2 * (float) M_PI * i / N); - float x2 = 2 * x1 * x1 - 1; // Use double angle formula - - return a0 - a1 * x1 + a2 * x2; -} - -static void -waterfall_init(waterfall_t *me, int max_blocks, int num_bins, int time_osr, int freq_osr) { - //mag_size,信号量数组的大小。最大块数93*时间过采样率2*频率过采样率2*分析块960*sizeOf(U_int8) - size_t mag_size = max_blocks * time_osr * freq_osr * num_bins * sizeof(me->mag[0]); - me->max_blocks = max_blocks; - me->num_blocks = 0; - me->num_bins = num_bins;//num_bins = 12000 * 0.16 / 2 = 960 - me->time_osr = time_osr; - me->freq_osr = freq_osr; - me->block_stride = (time_osr * freq_osr * num_bins); - me->mag = (uint8_t *) malloc(mag_size);//申请信号量数组,用于计算得分,357120个 - me->mag2 = (float *) malloc(mag_size * sizeof(float));//申请信号量数组,用于计算信噪比 - LOG(LOG_DEBUG, "Waterfall size = %zu\n", mag_size); -} - -static void waterfall_free(waterfall_t *me) { - free(me->mag); - free(me->mag2); -} - - -void monitor_init(monitor_t *me, const monitor_config_t *cfg) { - LOG(LOG_DEBUG, "Monitor is initializing..."); - //协议的时长,FT8_SLOT_TIME=15.0f,FT4_SLOT_TIME=7.5f - float slot_time = (cfg->protocol == PROTO_FT4) ? FT4_SLOT_TIME : FT8_SLOT_TIME; - //协议每个符号的时长,FT8_SYMBOL_PERIOD=0.160f,FT4_SYMBOL_PERIOD=0.048f - float symbol_period = (cfg->protocol == PROTO_FT4) ? FT4_SYMBOL_PERIOD : FT8_SYMBOL_PERIOD; - - //************************************************** - // Compute DSP parameters that depend on the sample rate - // 根据采样率计算DSP参数 - // block_size:每一个FSK符号占用的样本数,FT8:12000*0.16=1920个 - // subblock_size:分析移动的大小(样本数),每符号样本数/时间过采样率。FT8:1920/2=960 - // nfft:fft size。fft大小=每个FSK符号占用的样本数*频率过采样率=1920*2 - // fft_norm:FFT归一化因子。2/fft size。 - me->block_size = (int) (cfg->sample_rate * - symbol_period); //12000*0.16 对应于一个FSK符号的样本=1920 - me->subblock_size = me->block_size / cfg->time_osr;//移动的样本数。一个FSK符号的样本数/过采样率 - //nfft是傅里叶变换前,时域的实数序列的数量。目前是一个FSK符号的样本数*频率过采样率 - me->nfft = me->block_size * cfg->freq_osr;//nfft=一个FSK符号的样本数*频率过采样率 - me->fft_norm = 2.0f / me->nfft;//< FFT归一化因子。FFT normalization factor - // const int len_window = 1.8f * me->block_size; // hand-picked and optimized - //************************************************** - - // 申请窗空间,大小是fft块大小*me->windows[0]的大小 - // 采集周期如果是实际信号的非整数时,端点是不连续的。 - // 这些不连续片段在FFT中显示为高频成分。这些高频成分不存在于原信号中。 - // 这些频率可能远高于奈奎斯特频率,在0~ 采样率的一半的频率区间内产生混叠。 - // 使用FFT获得的频率,不是原信号的实际频率,而是一个改变过的频率。 - // 类似于某个频率的能量泄漏至其他频率。 这种现象叫做频谱泄漏。 - // 频率泄漏使好的频谱线扩散到更宽的信号范围中。这些不连续片段在FFT中显示为高频成分。 - // 通过加窗来尽可能减少在非整数个周期上进行FFT产生的误差。 - // 加窗可减少这些不连续部分的幅值。 - // 加窗包括将时间记录乘以有限长度的窗,窗的幅值逐渐变小,在边沿处为0。 - // 加窗的结果是尽可能呈现出一个连续的波形,减少剧烈的变化。 这种方法也叫应用一个加窗。 - // 窗函数分很多种,常见的的如:Hamming窗、Hanning窗、Blackman-Harris窗、Kaiser-Bessel窗、Flat top窗。 - // Hanning窗适用于95%的情况。 - me->window = (float *) malloc( - me->nfft * sizeof(me->window[0]));// 申请窗空间,大小是fft块大小*sizeof(me->windows[0]) - //此处是窗函数的设置,使用常用的hanning窗 - for (int i = 0; i < me->nfft; ++i) { - // window[i] = 1; - me->window[i] = hann_i(i, me->nfft);// 使用Hanning窗 - // me->window[i] = blackman_i(i, me->nfft);// Blackman-Harris窗 - // me->window[i] = hamming_i(i, me->nfft);// Hamming窗 - // me->window[i] = (i < len_window) ? hann_i(i, len_window) : 0; - } - - - // 申请当前STFT(短时傅氏变换)分析框架(nfft样本)的空间。 - //last_frame:申请傅里叶变换分析框架用的(nfft样本)。 - // 空间大小=时域数据量*数据类型占用的空间=一个FSK符号占用的采样数据量*频率过采样率=12000*0.16*2*SizeOf(float) - me->last_frame = (float *) malloc(me->nfft * sizeof(me->last_frame[0])); - - // size_t 类型定义在cstddef头文件中,该文件是C标准库的头文件stddef.h的C++版。 - // 它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。 - size_t fft_work_size; - // 第一步,获取可以用的FFT工作区域的大小到fft_work_size - //nfft=一个FSK符号的样本数*频率过采样率=0.16*12000*2=3840 - kiss_fftr_alloc(me->nfft, 0, 0, &fft_work_size); - //fft_work_size - - - // 申请FFT工作区域的内存,38676个 - me->fft_work = malloc(fft_work_size); - //第二步,返回fft的设置信息 - me->fft_cfg = kiss_fftr_alloc(me->nfft, 0, me->fft_work, &fft_work_size); - - // 最大块数,FT8的周期时长/每个符号时长,FT8:15/0.16 =93 - const int max_blocks = (int) (slot_time / symbol_period); - - // num_bins:如果以6.25 Hz为单位的FFT箱数量。6.25:每秒6.25个FSK符号,0.16*6.25=1。 - // num_bins = 12000 * 0.16 / 2 = 960。2是啥?是生成的频域数据量是采集数据量的一半 - const int num_bins = (int) (cfg->sample_rate * symbol_period / 2); - - //初始化瀑布图。 - waterfall_init(&me->wf, max_blocks, num_bins, cfg->time_osr, cfg->freq_osr); - me->wf.protocol = cfg->protocol; - me->symbol_period = symbol_period; - - me->max_mag = -120.0f; - - - LOG(LOG_INFO, "Block size = %d\n", me->block_size); - LOG(LOG_INFO, "Subblock size = %d\n", me->subblock_size); - LOG(LOG_INFO, "N_FFT = %d\n", me->nfft); - LOG(LOG_DEBUG, "FFT work area = %zu\n", fft_work_size); - // 瀑布图中最多能申请max_blocks个块数 - LOG(LOG_DEBUG, "Waterfall allocated %d symbols\n", me->wf.max_blocks); -} - -void monitor_free(monitor_t *me) { - - waterfall_free(&me->wf); - free(me->fft_work); - free(me->last_frame); - free(me->window); - LOG(LOG_DEBUG, "Monitor is free ."); -} - - -// Compute FFT magnitudes (log wf) for a frame in the signal and update waterfall data -// 计算信号中一帧的FFT幅度(log wf),并更新瀑布数据 -void monitor_process(monitor_t *me, const float *frame) { - // Check if we can still store more waterfall data - //防止溢出 - //mag阵列中存储的块(符号)编号 - if (me->wf.num_blocks >= me->wf.max_blocks) - return; - - //num_bins 的值是 12000 * 0.16 / 2 = 960 - //wf.block_strid= (time_osr * freq_osr * num_bins)=2*2*960 - //offset是在mag数组中的偏移量。wf.num_blocks是当前符号的块编号,以num_bins(数据片段)*时间过采样*频率过采样为单位。 - //mag的数组大小实际上是时间过采样*频率过采样*符号的最大量(93)*每符号真实采样数据(过采样的数据,960). - int offset = me->wf.num_blocks * me->wf.block_stride; - int frame_pos = 0; - - // Loop over block subdivisions - //循环块细分,wf.time_osr=2 时间过采样率 - for (int time_sub = 0; time_sub < me->wf.time_osr; ++time_sub) { - kiss_fft_scalar timedata[me->nfft]; - kiss_fft_cpx freqdata[me->nfft / 2 + 1]; - - // Shift the new data into analysis frame - //将新数据转移到分析框架中。 - // subblock_size:分析移动的大小(样本数)blocksize/2 每秒块数/时间过采样率=FT8:12000*0.16/2=1920/2=960个 - //last_frame的空间已经申请好了。空间大小=时域数据量*数据类型占用的空间=一个FSK符号占用的采样数据量*频率过采样率=12000*0.16*2*SizeOf(float)=3840 - //nfft=一个FSK符号的样本数*频率过采样率=1920*2=3840 - //subblock_size。移动的样本数。一个FSK符号的样本数/过采样率,1920/2=960 - //第一个循环,把过采样的后半段数据向前移960个数据, - //第二个循环,把新的声音数据导入到last_frame的后半部分,新的声音数据960个。外面的时间过采样率循环2遍,正好960*2=1920,一个符号 - //这样就可以对一个符号周期的时域数据做傅里叶变换了 - for (int pos = 0; pos < me->nfft - me->subblock_size; ++pos) { - me->last_frame[pos] = me->last_frame[pos + me->subblock_size]; - } - for (int pos = me->nfft - me->subblock_size; pos < me->nfft; ++pos) { - me->last_frame[pos] = frame[frame_pos]; - ++frame_pos; - } - - - // Compute windowed analysis frame - //用窗函数做一次转换,汉宁窗。 - for (int pos = 0; pos < me->nfft; ++pos) { - //把last_frame中的数据赋值到timedata中来,timedata是时域数据,要做一次归一化、窗函数处理 - timedata[pos] = me->fft_norm * me->window[pos] * me->last_frame[pos]; - //timedata[pos] =me->window[pos] * me->last_frame[pos]; - } - - //傅里叶变换把timedata的时域数据(长度是nfft)转换到频域数据上来。频域数据是复数数组,数组长度是nfft/2+1 - //nfft=一个FSK符号的样本数*频率过采样率=12000*0.16*2=3840 - kiss_fftr(me->fft_cfg, timedata, freqdata); - - // Loop over two possible frequency bin offsets (for averaging) - //在两个可能的频率单元偏移上循环(用于平均) - //两个循环的意义是:在一个符号采样数据的范围内(12000*0.16)对freqdata的能量做计算 - for (int freq_sub = 0; freq_sub < me->wf.freq_osr; ++freq_sub) { - for (int bin = 0; bin < me->wf.num_bins; ++bin) { //num_bins 的值是 12000 * 0.16 / 2 = 960 - - //循环次数=2*960=1920 - //信号量位置src_bin, - int src_bin = (bin * me->wf.freq_osr) + freq_sub; - - ////此位置可能是计算信噪比的位置 - //求各频率点上的信号强度是傅里叶之后的平方?少了开方,mag2应当是信号量的平方 - float mag2 = (freqdata[src_bin].i * freqdata[src_bin].i) + - (freqdata[src_bin].r * freqdata[src_bin].r); - float db = 10.0f * log10f(1E-12f + mag2); - - //把信号量保存下来 - //offset=me->wf.num_blocks * me->wf.block_stride; - //wf.block_strid= (time_osr * freq_osr * num_bins)=2*2*960 - //偏移量就是当前块编号*每个符号ftt数据量 - - me->wf.mag2[offset] = mag2; - - //每循环一次,偏移量移一位。共移动time_osr*freq_osr*num_bins=2*2*960=3840 - - // Scale decibels to unsigned 8-bit range and clamp the value - //将分贝缩放到无符号8位范围,并钳制该值 - // Range 0-240 covers -120..0 dB in 0.5 dB steps - int scaled = (int) (2 * db + 240); - - //0~255之间 - me->wf.mag[offset] = (scaled < 0) ? 0 : ((scaled > 255) ? 255 : scaled); - ++offset; - - if (db > me->max_mag) - me->max_mag = db; - } - } - } - ++me->wf.num_blocks;//mag阵列中存储的块(符号)编号,块大小:2*2*960 -} - -void monitor_reset(monitor_t *me) { - LOG(LOG_DEBUG, "Monitor is resetting..."); - me->wf.num_blocks = 0; - me->max_mag = -120.0f; -} diff --git a/ft8CN/app/src/main/cpp/monitor_opr.h b/ft8CN/app/src/main/cpp/monitor_opr.h deleted file mode 100644 index dd7cc61..0000000 --- a/ft8CN/app/src/main/cpp/monitor_opr.h +++ /dev/null @@ -1,47 +0,0 @@ - -#include -#include -#include -#include -#include -#include "ft8/decode.h" -#include "fft/kiss_fftr.h" -#include "common/debug.h" - -#define LOG_LEVEL LOG_INFO - - - -/// Configuration options for FT4/FT8 monitor -typedef struct { - float f_min; ///< 最低频率界限,Lower frequency bound for analysis - float f_max; ///< 最高频率界限,Upper frequency bound for analysis - int sample_rate; ///< 采样率,Sample rate in Hertz - int time_osr; ///< 时间过采样率,Number of time subdivisions - int freq_osr; ///< 频率过采样率,Number of frequency subdivisions - ftx_protocol_t protocol; ///< Protocol: FT4 or FT8 -} monitor_config_t; - -/// FT4/FT8 monitor object that manages DSP processing of incoming audio data -/// and prepares a waterfall object -typedef struct { - float symbol_period; ///< FT4/FT8符号周期(秒)。FT4/FT8 symbol period in seconds - int block_size; ///< 每个符号(FSK)的样本数。Number of samples per symbol (block) - int subblock_size; ///< 分析移动的大小(样本数)。Analysis shift size (number of samples) - int nfft; ///< FFT size - float fft_norm; ///< FFT归一化因子。FFT normalization factor - float *window; ///< STFT分析的窗口函数(nfft样本)。Window function for STFT analysis (nfft samples) - float *last_frame; ///< 当前STFT分析框架(nfft样本)。Current STFT analysis frame (nfft samples) - waterfall_t wf; ///< 瀑布对象。Waterfall object - float max_mag; ///< 最大检测量(调试统计)。Maximum detected magnitude (debug stats) - - // KISS FFT housekeeping variables - void *fft_work; ///< FFT需要的工作区域。Work area required by Kiss FFT - kiss_fftr_cfg fft_cfg; ///< Kiss FFT需要的设置信息。Kiss FFT housekeeping object -} monitor_t; - - -void monitor_init(monitor_t *me, const monitor_config_t *cfg); -void monitor_free(monitor_t* me); -void monitor_process(monitor_t *me, const float *frame); -void monitor_reset(monitor_t *me); diff --git a/ft8CN/app/src/main/cpp/spectrum_data.c b/ft8CN/app/src/main/cpp/spectrum_data.c deleted file mode 100644 index a608ff0..0000000 --- a/ft8CN/app/src/main/cpp/spectrum_data.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include "spectrum_data.h" - -static float hann_i(int i, int N) { - float x = sinf((float) M_PI * i / N); - return x * x; -} - -void do_fftr(float *voiceData, int dataSize, int *fftData) { -// int block_size = FT8_SYMBOL_PERIOD * 12000; //=1920 - int fftSize = FT8_SYMBOL_PERIOD * 12000; //=1920 - float *window = (float *) malloc( - fftSize * sizeof(window[0])); // 申请窗空间,大小是fft块大小*sizeof(windows[0]) - for (int i = 0; i < fftSize; ++i) //汉宁窗 - { - window[i] = hann_i(i, fftSize); - } - // 申请当前STFT分析框架(nfft样本)的空间。 - //float *last_frame = (float *) malloc(fftSize * sizeof(last_frame[0])); - - size_t fft_work_size; - - // 获取FFT工作区域的大小到fft_work_size - kiss_fftr_alloc(fftSize, 0, 0, &fft_work_size); - - // 申请FFT工作区域的内存 - void *fft_work = malloc(fft_work_size); - kiss_fftr_cfg fft_cfg = kiss_fftr_alloc(fftSize, 0, fft_work, &fft_work_size); - - // 最大块数,FT8的周期时长/每个符号时长,FT8:15/0.16 =93 - const int max_blocks = (int) (FT8_SLOT_TIME / FT8_SYMBOL_PERIOD); - const int num_bins = (int) (12000 * FT8_SYMBOL_PERIOD / 2); - int fftOffset = 0; - int offset = 0; - float maxMag = 0; - float minMag = 65535.0f; - float mags[dataSize / 2]; - for (int pos = 0; pos < dataSize / fftSize; pos++) { - kiss_fft_scalar timedata[fftSize]; - kiss_fft_cpx freqdata[fftSize / 2 + 1]; - for (int i = 0; i < fftSize; i++) {//fftSize=3840 - timedata[i] = window[i] * voiceData[offset];//window[i] * - offset++; - } - kiss_fftr(fft_cfg, timedata, freqdata); - - for (int i = 1; i < fftSize / 2 + 1; i++) { - float mag2 = sqrtf(freqdata[i].i * freqdata[i].i + freqdata[i].r * freqdata[i].r); - mags[fftOffset] = mag2; - if (maxMag < mag2) { - maxMag = mag2; - } - if (minMag > mag2) { - minMag = mag2; - } - fftOffset++; - } - - float normal = (maxMag - minMag) / 256; - for (int i = 0; i < dataSize / 2; ++i) { - fftData[i] = roundf((mags[i] - minMag) / normal); - } - } - free(fft_work); - free(window); - //free(last_frame); - //free(fft_cfg); -} - -void do_fftr_raw(float *voiceData, int dataSize, int *fftData) { - //int block_size = FT8_SYMBOL_PERIOD * 12000; //=1920 - int fftSize = FT8_SYMBOL_PERIOD * 12000; //=1920 - float *window = (float *) malloc( - fftSize * sizeof(window[0])); // 申请窗空间,大小是fft块大小*sizeof(windows[0]) - for (int i = 0; i < fftSize; ++i) //汉宁窗 - { - window[i] = hann_i(i, fftSize); - } - // 申请当前STFT分析框架(nfft样本)的空间。 - //float *last_frame = (float *) malloc(fftSize * sizeof(last_frame[0])); - - size_t fft_work_size; - - // 获取FFT工作区域的大小到fft_work_size - kiss_fftr_alloc(fftSize, 0, 0, &fft_work_size); - - // 申请FFT工作区域的内存 - void *fft_work = malloc(fft_work_size); - kiss_fftr_cfg fft_cfg = kiss_fftr_alloc(fftSize, 0, fft_work, &fft_work_size); - - // 最大块数,FT8的周期时长/每个符号时长,FT8:15/0.16 =93 - const int max_blocks = (int) (FT8_SLOT_TIME / FT8_SYMBOL_PERIOD); - const int num_bins = (int) (12000 * FT8_SYMBOL_PERIOD / 2); - int fftOffset = 0; - int offset = 0; - - //float mags[dataSize / 2]; - for (int pos = 0; pos < dataSize / fftSize; pos++) { - kiss_fft_scalar timedata[fftSize]; - kiss_fft_cpx freqdata[fftSize / 2 + 1]; - for (int i = 0; i < fftSize; i++) {//fftSize=3840 - timedata[i] = window[i] * voiceData[offset];//window[i] * - offset++; - } - kiss_fftr(fft_cfg, timedata, freqdata); - - for (int i = 1; i < fftSize / 2 + 1; i++) { - float mag2 =(freqdata[i].i * freqdata[i].i + freqdata[i].r * freqdata[i].r); - mag2= 10.0f * log10f(1E-12f + mag2); - int scaled = (int) (mag2 +20)*4; - - //0~255之间 - fftData[fftOffset] = (scaled < 0) ? 0 : ((scaled > 255) ? 255 : scaled); - - fftOffset++; - } - -// float normal = (maxMag - minMag) / 256; -// for (int i = 0; i < dataSize / 2; ++i) { -// fftData[i] = roundf((mags[i] - minMag) / normal); -// } - } - free(fft_work); - free(window); -} \ No newline at end of file diff --git a/ft8CN/app/src/main/cpp/spectrum_data.h b/ft8CN/app/src/main/cpp/spectrum_data.h deleted file mode 100644 index 9714f25..0000000 --- a/ft8CN/app/src/main/cpp/spectrum_data.h +++ /dev/null @@ -1,21 +0,0 @@ - - -#include -#include -#include -#include - -#include "ft8/constants.h" -#include "common/debug.h" -#include "fft/kiss_fftr.h" - -/** - * 对符号进行快速傅里叶变换,以1920块数据变换,生成960块。0~3000Hz - * normalization=1对数据归一化处理,方便显示FT8信号的频率 - * @param voiceData 声音数据 - * @param dataSize 声音数据的大小 - * @param fftData fft数据 - * @param normalization 是否是归一化处理 - */ -void do_fftr(float* voiceData, int dataSize, int* fftData); -void do_fftr_raw(float *voiceData, int dataSize, int *fftData);