Minor cleanup in encoding, more documentation

pull/12/merge
Karlis Goba 2021-08-16 12:49:32 +03:00
rodzic f7ca67be9f
commit 456eefede4
3 zmienionych plików z 25 dodań i 52 usunięć

Wyświetl plik

@ -3,20 +3,9 @@
#include <stdint.h>
// Generate FT8 tone sequence from payload data
// [IN] payload - 9 byte array consisting of 72 bit payload
// [OUT] itone - array of NN (79) bytes to store the generated tones (encoded as 0..7)
/// Generate FT8 tone sequence from payload data
/// @param[in] payload - 10 byte array consisting of 77 bit payload
/// @param[out] itone - array of NN (79) bytes to store the generated tones (encoded as 0..7)
void genft8(const uint8_t *payload, uint8_t *itone);
// Encode an 87-bit message and return a 174-bit codeword.
// The generator matrix has dimensions (87,87).
// The code is a (174,87) regular ldpc code with column weight 3.
// The code was generated using the PEG algorithm.
// After creating the codeword, the columns are re-ordered according to
// "colorder" to make the codeword compatible with the parity-check matrix
// Arguments:
// * message - array of 87 bits stored as 11 bytes (MSB first)
// * codeword - array of 174 bits stored as 22 bytes (MSB first)
void encode174(const uint8_t *message, uint8_t *codeword);
#endif // _INCLUDE_ENCODE_H_

Wyświetl plik

@ -212,7 +212,7 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
Tnm += tov[n][m_idx];
}
}
toc[m][n_idx] = fast_tanh(-Tnm / 2); // == (exp(-Tnm)-1) / (exp(-Tnm)+1)
toc[m][n_idx] = fast_tanh(-Tnm / 2);
}
}
@ -228,10 +228,10 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
{
if ((kFT8_LDPC_Nm[m][n_idx] - 1) != n)
{
Tmn *= toc[m][n_idx]; // tanh(q(n', m) / 2)
Tmn *= toc[m][n_idx];
}
}
tov[n][m_idx] = 2 * fast_atanh(-Tmn); // == log( (1-Tmn) / (1+Tmn) )
tov[n][m_idx] = -2 * fast_atanh(Tmn);
}
}
}

Wyświetl plik

@ -12,9 +12,16 @@
#define LOG_LEVEL LOG_INFO
/// Computes a GFSK smoothing pulse.
/// The pulse is theoretically infinitely long, however, here it's truncated at 3 times the symbol length.
/// This means the pulse array has to have space for 3*n_spsym elements.
/// @param[in] n_spsym Number of samples per symbol
/// @param[in] b Shape parameter (values defined for FT8/FT4)
/// @param[out] pulse Output array of pulse samples
///
void gfsk_pulse(int n_spsym, float b, float *pulse)
{
const float c = M_PI * sqrtf(2 / logf(2));
float c = M_PI * sqrtf(2 / logf(2));
for (int i = 0; i < 3 * n_spsym; ++i)
{
@ -23,11 +30,19 @@ void gfsk_pulse(int n_spsym, float b, float *pulse)
}
}
// Same as synth_fsk, but uses GFSK phase shaping
/// Synthesize waveform data using GFSK phase shaping.
/// The output waveform will contain n_sym+2 symbols (extra symbol at the beginning/end).
/// @param[in] symbols Array of symbols (tones) (0-7 for FT8)
/// @param[in] n_sym Number of symbols in the symbols array
/// @param[in] f0 Audio frequency in Hertz for the symbol 0 (base frequency)
/// @param[in] n_spsym Number of samples per symbol (only integer number of samples supported)
/// @param[in] signal_rate Sample rate of synthesized signal, Hertz
/// @param[out] signal Output array of signal waveform samples (should have space for n_spsym*(n_sym+2) samples)
///
void synth_gfsk(const uint8_t *symbols, int n_sym, float f0, int n_spsym, int signal_rate, float *signal)
{
LOG(LOG_DEBUG, "n_spsym = %d\n", n_spsym);
int n_wave = n_sym * n_spsym;
int n_wave = n_sym * n_spsym; // Number of output samples
float hmod = 1.0f;
// Compute the smoothed frequency waveform.
@ -78,34 +93,6 @@ void synth_gfsk(const uint8_t *symbols, int n_sym, float f0, int n_spsym, int si
}
}
// Convert a sequence of symbols (tones) into a sinewave of continuous phase (FSK).
// Symbol 0 gets encoded as a sine of frequency f0, the others are spaced in increasing
// fashion.
void synth_fsk(const uint8_t *symbols, int num_symbols, float f0, float spacing,
float symbol_rate, float signal_rate, float *signal)
{
float phase = 0;
float dt = 1 / signal_rate;
float dt_sym = 1 / symbol_rate;
float t = 0;
int j = 0;
int i = 0;
while (j < num_symbols)
{
float f = f0 + symbols[j] * spacing;
phase = fmodf(phase + 2 * M_PI * f / signal_rate, 2 * M_PI);
signal[i] = sinf(phase);
t += dt;
if (t >= dt_sym)
{
// Move to the next symbol
t -= dt_sym;
++j;
}
++i;
}
}
void usage()
{
printf("Generate a 15-second WAV file encoding a given message.\n");
@ -135,7 +122,6 @@ int main(int argc, char **argv)
// First, pack the text data into binary message
uint8_t packed[FT8_K_BYTES];
//int rc = packmsg(message, packed);
int rc = pack77(message, packed);
if (rc < 0)
{
@ -152,8 +138,7 @@ int main(int argc, char **argv)
printf("\n");
// Second, encode the binary message as a sequence of FSK tones
uint8_t tones[FT8_NN]; // FT8_NN = 79, lack of better name at the moment
//genft8(packed, 0, tones);
uint8_t tones[FT8_NN]; // Array of 79 tones (symbols)
genft8(packed, tones);
printf("FSK tones: ");
@ -174,7 +159,6 @@ int main(int argc, char **argv)
signal[i] = 0;
}
// synth_fsk(tones, FT8_NN, frequency, symbol_rate, symbol_rate, sample_rate, signal + num_silence);
synth_gfsk(tones, FT8_NN, frequency, sample_rate / symbol_rate, sample_rate, signal + num_silence);
save_wav(signal, num_silence + num_samples + num_silence, sample_rate, wav_path);