Minor tweaks for performance

pull/12/merge
Karlis Goba 2021-08-18 11:07:12 +03:00
rodzic 78c3e25a08
commit ee9567ab1d
3 zmienionych plików z 46 dodań i 66 usunięć

Wyświetl plik

@ -17,9 +17,9 @@
#define LOG_LEVEL LOG_INFO
const int kMin_score = 12; // Minimum sync score threshold for candidates
const int kMin_score = 10; // Minimum sync score threshold for candidates
const int kMax_candidates = 120;
const int kLDPC_iterations = 25;
const int kLDPC_iterations = 20;
const int kMax_decoded_messages = 50;
@ -35,7 +35,7 @@ void usage()
float hann_i(int i, int N)
{
float x = sinf((float)M_PI * i / (N - 1));
float x = sinf((float)M_PI * i / N);
return x * x;
}
@ -44,7 +44,7 @@ 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 - 1));
float x1 = cosf(2 * (float)M_PI * i / N);
return a0 - a1 * x1;
}
@ -55,8 +55,7 @@ float blackman_i(int i, int N)
const float a1 = 1.0f / 2;
const float a2 = alpha / 2;
float x1 = cosf(2 * (float)M_PI * i / (N - 1));
//float x2 = cosf(4 * (float)M_PI * i / (N - 1));
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;
@ -73,15 +72,16 @@ void extract_power(const float signal[], waterfall_t *power, int block_size)
const int subblock_size = block_size / power->time_osr;
const int nfft = block_size * power->freq_osr;
const float fft_norm = 2.0f / nfft;
const int len_window = 1.8f * block_size; // hand-picked and optimized
float window[nfft];
for (int i = 0; i < nfft; ++i)
{
// window[i] = 1;
window[i] = hann_i(i, nfft);
// window[i] = (i < block_size) ? hamming_i(i, block_size) : 0;
// window[i] = hann_i(i, nfft);
// window[i] = blackman_i(i, nfft);
// window[i] = hamming_i(i, nfft);
window[i] = (i < len_window) ? hann_i(i, len_window) : 0;
}
size_t fft_work_size;
@ -96,7 +96,7 @@ void extract_power(const float signal[], waterfall_t *power, int block_size)
kiss_fftr_cfg fft_cfg = kiss_fftr_alloc(nfft, 0, fft_work, &fft_work_size);
int offset = 0;
float max_mag = -100.0f;
float max_mag = -120.0f;
for (int idx_block = 0; idx_block < power->num_blocks; ++idx_block)
{
// Loop over two possible time offsets (0 and block_size/2)
@ -118,7 +118,7 @@ void extract_power(const float signal[], waterfall_t *power, int block_size)
for (int idx_bin = 0; idx_bin < nfft / 2 + 1; ++idx_bin)
{
float mag2 = (freqdata[idx_bin].i * freqdata[idx_bin].i) + (freqdata[idx_bin].r * freqdata[idx_bin].r);
mag_db[idx_bin] = 10.0f * log10f(1E-10f + mag2 * fft_norm * fft_norm);
mag_db[idx_bin] = 10.0f * log10f(1E-12f + mag2 * fft_norm * fft_norm);
}
// Loop over two possible frequency bin offsets (for averaging)
@ -128,7 +128,8 @@ void extract_power(const float signal[], waterfall_t *power, int block_size)
{
float db = mag_db[pos * power->freq_osr + freq_sub];
// Scale decibels to unsigned 8-bit range and clamp the value
int scaled = (int)(2 * (db + 120));
// Range 0-240 covers -120..0 dB in 0.5 dB steps
int scaled = (int)(2 * db + 240);
power->mag[offset] = (scaled < 0) ? 0 : ((scaled > 255) ? 255 : scaled);
++offset;
@ -144,39 +145,6 @@ void extract_power(const float signal[], waterfall_t *power, int block_size)
free(fft_work);
}
void normalize_signal(float *signal, int num_samples)
{
float max_amp = 1E-5f;
for (int i = 0; i < num_samples; ++i)
{
float amp = fabsf(signal[i]);
if (amp > max_amp)
{
max_amp = amp;
}
}
for (int i = 0; i < num_samples; ++i)
{
signal[i] /= max_amp;
}
}
void print_tones(const uint8_t *code_map, const float *log174)
{
for (int k = 0; k < FT8_LDPC_N; k += 3)
{
uint8_t max = 0;
if (log174[k + 0] > 0)
max |= 4;
if (log174[k + 1] > 0)
max |= 2;
if (log174[k + 2] > 0)
max |= 1;
LOG(LOG_DEBUG, "%d", code_map[max]);
}
LOG(LOG_DEBUG, "\n");
}
int main(int argc, char **argv)
{
// Expect one command-line argument
@ -197,7 +165,6 @@ int main(int argc, char **argv)
{
return -1;
}
normalize_signal(signal, num_samples);
// Compute DSP parameters that depend on the sample rate
const int num_bins = (int)(sample_rate / (2 * kFSK_dev)); // number bins of FSK tone width that the spectrum can be divided into
@ -222,8 +189,6 @@ int main(int argc, char **argv)
candidate_t candidate_list[kMax_candidates];
int num_candidates = find_sync(&power, kMax_candidates, candidate_list, kMin_score);
// TODO: sort the candidates by strongest sync first?
// Hash table for decoded messages (to check for duplicates)
int num_decoded = 0;
message_t decoded[kMax_decoded_messages];
@ -265,17 +230,17 @@ int main(int argc, char **argv)
}
LOG(LOG_DEBUG, "Checking hash table for %4.1fs / %4.1fHz [%d]...\n", time_sec, freq_hz, cand->score);
int hash_idx = message.hash % kMax_decoded_messages;
int idx_hash = message.hash % kMax_decoded_messages;
bool found_empty_slot = false;
bool found_duplicate = false;
do
{
if (decoded_hashtable[hash_idx] == NULL)
if (decoded_hashtable[idx_hash] == NULL)
{
LOG(LOG_DEBUG, "Found an empty slot\n");
found_empty_slot = true;
}
else if ((decoded_hashtable[hash_idx]->hash == message.hash) && (0 == strcmp(decoded_hashtable[hash_idx]->text, message.text)))
else if ((decoded_hashtable[idx_hash]->hash == message.hash) && (0 == strcmp(decoded_hashtable[idx_hash]->text, message.text)))
{
LOG(LOG_DEBUG, "Found a duplicate [%s]\n", message.text);
found_duplicate = true;
@ -284,20 +249,20 @@ int main(int argc, char **argv)
{
LOG(LOG_DEBUG, "Hash table clash!\n");
// Move on to check the next entry in hash table
hash_idx = (hash_idx + 1) % kMax_decoded_messages;
idx_hash = (idx_hash + 1) % kMax_decoded_messages;
}
} while (!found_empty_slot && !found_duplicate);
if (found_empty_slot)
{
// Fill the empty hashtable slot
memcpy(&decoded[hash_idx], &message, sizeof(message));
decoded_hashtable[hash_idx] = &decoded[hash_idx];
memcpy(&decoded[idx_hash], &message, sizeof(message));
decoded_hashtable[idx_hash] = &decoded[idx_hash];
++num_decoded;
// Fake WSJT-X-like output for now
int snr = 0; // TODO: compute SNR
printf("000000 %3d %4.1f %4d ~ %s\n", cand->score, time_sec, (int)(freq_hz + 0.5f), message.text);
printf("000000 %3d %+4.2f %4.0f ~ %s\n", cand->score, time_sec, freq_hz, message.text);
}
}
LOG(LOG_INFO, "Decoded %d messages\n", num_decoded);

Wyświetl plik

@ -38,14 +38,14 @@ int find_sync(const waterfall_t *power, int num_candidates, candidate_t heap[],
{
for (int freq_sub = 0; freq_sub < power->freq_osr; ++freq_sub)
{
for (int time_offset = -12; time_offset < power->num_blocks - FT8_NN + 12; ++time_offset)
for (int time_offset = -12; time_offset < 24; ++time_offset)
{
for (int freq_offset = 0; freq_offset + 8 < power->num_bins; ++freq_offset)
for (int freq_offset = 0; freq_offset + 7 < power->num_bins; ++freq_offset)
{
int score = 0;
int num_average = 0;
// Compute average score over sync symbols (m+k = 0-7, 36-43, 72-79)
int num_symbols = 0;
for (int m = 0; m <= 72; m += 36)
{
for (int k = 0; k < 7; ++k)
@ -65,7 +65,7 @@ int find_sync(const waterfall_t *power, int num_candidates, candidate_t heap[],
// score += 8 * p8[kFT8_Costas_pattern[k]] -
// p8[0] - p8[1] - p8[2] - p8[3] -
// p8[4] - p8[5] - p8[6] - p8[7];
// ++num_symbols;
// ++num_average;
// Check only the neighbors of the expected symbol frequency- and time-wise
int sm = kFT8_Costas_pattern[k]; // Index of the expected bin
@ -73,29 +73,31 @@ int find_sync(const waterfall_t *power, int num_candidates, candidate_t heap[],
{
// look at one frequency bin lower
score += p8[sm] - p8[sm - 1];
++num_symbols;
++num_average;
}
if (sm < 7)
{
// look at one frequency bin higher
score += p8[sm] - p8[sm + 1];
++num_symbols;
++num_average;
}
if (k > 0)
if ((k > 0) && (block > 0))
{
// look one symbol back in time
score += p8[sm] - p8[sm - sym_stride];
++num_symbols;
++num_average;
}
if (k < 6)
if ((k < 6) && ((block + 1) < power->num_blocks))
{
// look one symbol forward in time
score += p8[sm] - p8[sm + sym_stride];
++num_symbols;
++num_average;
}
}
}
score /= num_symbols;
if (num_average > 0)
score /= num_average;
if (score < min_score)
continue;
@ -127,6 +129,17 @@ int find_sync(const waterfall_t *power, int num_candidates, candidate_t heap[],
}
}
// 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;
}
@ -173,7 +186,7 @@ void extract_likelihood(const waterfall_t *power, const candidate_t *cand, float
float variance = (sum2 - (sum * sum * inv_n)) * inv_n;
// Normalize log174 distribution and scale it with experimentally found coefficient
float norm_factor = sqrtf(32.0f / variance);
float norm_factor = sqrtf(24.0f / variance);
for (int i = 0; i < FT8_LDPC_N; ++i)
{
log174[i] *= norm_factor;

Wyświetl plik

@ -152,6 +152,8 @@ int main(int argc, char **argv)
if (is_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-ORed with [a] pseudorandom sequence before computing the CRC and FEC parity bits'
for (int i = 0; i < 10; ++i)
{
packed[i] ^= kFT4_XOR_sequence[i];