From 53acfab11c324dc6666e1dc58ef6fd29c1a254df Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Fri, 18 Jul 2025 15:16:36 +0200 Subject: [PATCH] added support for base37 encoded call sign --- Makefile | 2 +- decode.cc | 17 ++++++++++++++--- encode.cc | 38 ++++++++++++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index faa7ba6..1902930 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ CXX = clang++ -stdlib=libc++ -march=native all: encode decode test: encode decode - $(QEMU) ./encode audio.wav 48000 16 1 1500 5 /dev/urandom + $(QEMU) ./encode audio.wav 48000 16 1 1500 ANONYMOUS 48 /dev/urandom $(QEMU) ./decode audio.wav /dev/null encode: encode.cc common.hh diff --git a/decode.cc b/decode.cc index d299b28..c64e59a 100644 --- a/decode.cc +++ b/decode.cc @@ -80,6 +80,11 @@ struct Decoder : Common } return 0; } + static void base37_decoder(char *str, int64_t val, int len) + { + for (int i = len-1; i >= 0; --i, val /= 37) + str[i] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[val%37]; + } const cmplx *mls0_seq() { CODE::MLS seq0(mls0_poly, mls0_seed); @@ -393,11 +398,17 @@ struct Decoder : Common std::cerr << "preamble decoding error." << std::endl; break; } - if (meta_info > 255) { - std::cerr << "unsupported operation mode: " << meta_info << std::endl; + int64_t call = meta_info >> 8; + if (call == 0 || call >= 129961739795077L) { + std::cerr << "call sign unsupported." << std::endl; break; } - if (!setup(meta_info)) + char call_sign[10]; + base37_decoder(call_sign, call, 9); + call_sign[9] = 0; + std::cerr << "call sign: " << call_sign << std::endl; + int mode = meta_info & 255; + if (!setup(mode)) break; k = 0; for (int i = 0; i < symbol_pos+symbol_len+extended_len; ++i) diff --git a/encode.cc b/encode.cc index 9c7c0e5..268e08c 100644 --- a/encode.cc +++ b/encode.cc @@ -277,14 +277,14 @@ struct Encoder : public Common for (int i = guard_len / 4 + guard_len / 2; i < guard_len; ++i) weight[i] = 1; } - Encoder(DSP::WritePCM *pcm, const char *const *input_names, int input_count, int freq_off, int oper_mode) : pcm(pcm) + Encoder(DSP::WritePCM *pcm, const char *const *input_names, int input_count, int freq_off, int64_t call_sign, int oper_mode) : pcm(pcm) { if (!setup(oper_mode)) return; int offset = (freq_off * symbol_len) / rate; tone_off = offset - tone_count / 2; guard_interval_weights(); - meta_data(oper_mode); + meta_data((call_sign << 8) | oper_mode); leading_noise(); for (int input_index = 0; input_index < input_count; ++input_index) { const char *input_name = input_names[input_index]; @@ -342,10 +342,27 @@ struct Encoder : public Common } }; +int64_t base37_encoder(const char *str) +{ + int64_t acc = 0; + for (char c = *str++; c; c = *str++) { + acc *= 37; + if (c >= '0' && c <= '9') + acc += c - '0' + 1; + else if (c >= 'a' && c <= 'z') + acc += c - 'a' + 11; + else if (c >= 'A' && c <= 'Z') + acc += c - 'A' + 11; + else if (c != ' ') + return -1; + } + return acc; +} + int main(int argc, char **argv) { - if (argc < 8) { - std::cerr << "usage: " << argv[0] << " OUTPUT RATE BITS CHANNELS OFFSET MODE INPUT.." << std::endl; + if (argc < 9) { + std::cerr << "usage: " << argv[0] << " OUTPUT RATE BITS CHANNELS OFFSET CALLSIGN MODE INPUT.." << std::endl; return 1; } @@ -361,8 +378,13 @@ int main(int argc, char **argv) std::cerr << "Frequency offset must be divisible by 300." << std::endl; return 1; } - int input_count = argc - 7; - int oper_mode = std::atoi(argv[6]); + int64_t call_sign = base37_encoder(argv[6]); + if (call_sign <= 0 || call_sign >= 129961739795077L) { + std::cerr << "Unsupported call sign." << std::endl; + return 1; + } + int input_count = argc - 8; + int oper_mode = std::atoi(argv[7]); if (oper_mode < 0 || oper_mode > 255) { std::cerr << "Unsupported operation mode." << std::endl; return 1; @@ -379,10 +401,10 @@ int main(int argc, char **argv) output_file.silence(output_rate); switch (output_rate) { case 44100: - delete new Encoder(&output_file, argv+7, input_count, freq_off, oper_mode); + delete new Encoder(&output_file, argv + 8, input_count, freq_off, call_sign, oper_mode); break; case 48000: - delete new Encoder(&output_file, argv+7, input_count, freq_off, oper_mode); + delete new Encoder(&output_file, argv + 8, input_count, freq_off, call_sign, oper_mode); break; default: std::cerr << "Unsupported sample rate." << std::endl;