From 3eab1033b30b14b39c619ef3ccaccc1299611b30 Mon Sep 17 00:00:00 2001 From: Developer Date: Thu, 25 Jun 2026 23:59:45 +0000 Subject: [PATCH] Add LKMA-209 synthetic ground-truth recordings Co-Authored-By: Paperclip --- .../lkma-193a/ground-truth/v21/inbound.wav | Bin 0 -> 480044 bytes .../lkma-193a/ground-truth/v21/outbound.wav | Bin 0 -> 480044 bytes .../lkma-193a/ground-truth/v21/report.json | 8 + .../lkma-193a/ground-truth/v22bis/inbound.wav | Bin 0 -> 480044 bytes .../ground-truth/v22bis/outbound.wav | Bin 0 -> 480044 bytes .../lkma-193a/ground-truth/v22bis/report.json | 8 + artifacts/lkma-193a/groundtruth-v21.wav | Bin 0 -> 480044 bytes tools/generate-lkma-193a-groundtruth.c | 257 ++++++++++++++++++ 8 files changed, 273 insertions(+) create mode 100644 artifacts/lkma-193a/ground-truth/v21/inbound.wav create mode 100644 artifacts/lkma-193a/ground-truth/v21/outbound.wav create mode 100644 artifacts/lkma-193a/ground-truth/v21/report.json create mode 100644 artifacts/lkma-193a/ground-truth/v22bis/inbound.wav create mode 100644 artifacts/lkma-193a/ground-truth/v22bis/outbound.wav create mode 100644 artifacts/lkma-193a/ground-truth/v22bis/report.json create mode 100644 artifacts/lkma-193a/groundtruth-v21.wav create mode 100644 tools/generate-lkma-193a-groundtruth.c diff --git a/artifacts/lkma-193a/ground-truth/v21/inbound.wav b/artifacts/lkma-193a/ground-truth/v21/inbound.wav new file mode 100644 index 0000000000000000000000000000000000000000..bd9d02cfd15ab17caa8f547b0b57fea8a89b6951 GIT binary patch literal 480044 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 literal 0 HcmV?d00001 diff --git a/artifacts/lkma-193a/ground-truth/v21/report.json b/artifacts/lkma-193a/ground-truth/v21/report.json new file mode 100644 index 0000000..0154c34 --- /dev/null +++ b/artifacts/lkma-193a/ground-truth/v21/report.json @@ -0,0 +1,8 @@ +{ + "source": "synthetic-spandsp", + "note": "Generated by spandsp FSK TX - not a real hardware capture. Replace with lab recording when USB FXO rig is available.", + "sampleRate": 8000, + "channels": 1, + "bitDepth": 16, + "durationSeconds": 30 +} diff --git a/artifacts/lkma-193a/ground-truth/v22bis/inbound.wav b/artifacts/lkma-193a/ground-truth/v22bis/inbound.wav new file mode 100644 index 0000000000000000000000000000000000000000..c8b950c1dc0d66edb1f9204eabe2f1f00dd5baef GIT binary patch literal 480044 zcmeIuF%Cok07TKD(YgV}o!@% literal 0 HcmV?d00001 diff --git a/artifacts/lkma-193a/ground-truth/v22bis/outbound.wav b/artifacts/lkma-193a/ground-truth/v22bis/outbound.wav new file mode 100644 index 0000000000000000000000000000000000000000..c8b950c1dc0d66edb1f9204eabe2f1f00dd5baef GIT binary patch literal 480044 zcmeIuF%Cok07TKD(YgV}o!@% literal 0 HcmV?d00001 diff --git a/artifacts/lkma-193a/ground-truth/v22bis/report.json b/artifacts/lkma-193a/ground-truth/v22bis/report.json new file mode 100644 index 0000000..dd67a29 --- /dev/null +++ b/artifacts/lkma-193a/ground-truth/v22bis/report.json @@ -0,0 +1,8 @@ +{ + "source": "synthetic-spandsp", + "note": "V.22bis placeholder silence. Generated by the synthetic spandsp artifact generator; replace with lab recording when USB FXO rig is available.", + "sampleRate": 8000, + "channels": 1, + "bitDepth": 16, + "durationSeconds": 30 +} diff --git a/artifacts/lkma-193a/groundtruth-v21.wav b/artifacts/lkma-193a/groundtruth-v21.wav new file mode 100644 index 0000000000000000000000000000000000000000..bd9d02cfd15ab17caa8f547b0b57fea8a89b6951 GIT binary patch literal 480044 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 +#include +#include +#include +#include +#include + +#include + +#define SAMPLE_RATE 8000 +#define CHANNELS 1 +#define BITS_PER_SAMPLE 16 +#define DURATION_SECONDS 30 +#define TOTAL_SAMPLES (SAMPLE_RATE * DURATION_SECONDS) +#define BLOCK_SAMPLES 160 +#define V21_MARK_BITS 150 + +typedef struct { + int bit_index; +} v21_bits_t; + +static int make_dirs(const char *path); +static int write_wav_header(FILE *file, uint32_t samples); +static int write_silence_wav(const char *path); +static int write_v21_wav(const char *path); +static int copy_file(const char *from, const char *to); +static int write_report(const char *path, const char *note); +static int get_v21_bit(void *user_data); + +int main(void) { + if (make_dirs("artifacts/lkma-193a/ground-truth/v21") != 0 || + make_dirs("artifacts/lkma-193a/ground-truth/v22bis") != 0) { + return 1; + } + + if (write_v21_wav("artifacts/lkma-193a/groundtruth-v21.wav") != 0 || + copy_file("artifacts/lkma-193a/groundtruth-v21.wav", + "artifacts/lkma-193a/ground-truth/v21/inbound.wav") != 0 || + write_silence_wav("artifacts/lkma-193a/ground-truth/v21/outbound.wav") != 0 || + write_report( + "artifacts/lkma-193a/ground-truth/v21/report.json", + "Generated by spandsp FSK TX - not a real hardware capture. Replace with lab recording when USB FXO rig is available." + ) != 0 || + write_silence_wav("artifacts/lkma-193a/ground-truth/v22bis/inbound.wav") != 0 || + write_silence_wav("artifacts/lkma-193a/ground-truth/v22bis/outbound.wav") != 0 || + write_report( + "artifacts/lkma-193a/ground-truth/v22bis/report.json", + "V.22bis placeholder silence. Generated by the synthetic spandsp artifact generator; replace with lab recording when USB FXO rig is available." + ) != 0) { + return 1; + } + + return 0; +} + +static int make_dirs(const char *path) { + char partial[512]; + size_t length = strlen(path); + + if (length >= sizeof(partial)) { + fprintf(stderr, "path too long: %s\n", path); + return -1; + } + + for (size_t index = 0; index <= length; index++) { + partial[index] = path[index]; + if (path[index] != '/' && path[index] != '\0') { + continue; + } + + partial[index] = '\0'; + if (partial[0] != '\0' && mkdir(partial, 0775) != 0 && errno != EEXIST) { + fprintf(stderr, "mkdir %s: %s\n", partial, strerror(errno)); + return -1; + } + partial[index] = path[index]; + } + return 0; +} + +static int write_u16_le(FILE *file, uint16_t value) { + uint8_t bytes[2] = { + (uint8_t) (value & 0xff), + (uint8_t) ((value >> 8) & 0xff) + }; + return fwrite(bytes, 1, sizeof(bytes), file) == sizeof(bytes) ? 0 : -1; +} + +static int write_u32_le(FILE *file, uint32_t value) { + uint8_t bytes[4] = { + (uint8_t) (value & 0xff), + (uint8_t) ((value >> 8) & 0xff), + (uint8_t) ((value >> 16) & 0xff), + (uint8_t) ((value >> 24) & 0xff) + }; + return fwrite(bytes, 1, sizeof(bytes), file) == sizeof(bytes) ? 0 : -1; +} + +static int write_i16_le(FILE *file, int16_t value) { + return write_u16_le(file, (uint16_t) value); +} + +static int write_wav_header(FILE *file, uint32_t samples) { + const uint16_t block_align = CHANNELS * (BITS_PER_SAMPLE / 8); + const uint32_t byte_rate = SAMPLE_RATE * block_align; + const uint32_t data_bytes = samples * block_align; + + return fwrite("RIFF", 1, 4, file) == 4 && + write_u32_le(file, 36 + data_bytes) == 0 && + fwrite("WAVEfmt ", 1, 8, file) == 8 && + write_u32_le(file, 16) == 0 && + write_u16_le(file, 1) == 0 && + write_u16_le(file, CHANNELS) == 0 && + write_u32_le(file, SAMPLE_RATE) == 0 && + write_u32_le(file, byte_rate) == 0 && + write_u16_le(file, block_align) == 0 && + write_u16_le(file, BITS_PER_SAMPLE) == 0 && + fwrite("data", 1, 4, file) == 4 && + write_u32_le(file, data_bytes) == 0 ? 0 : -1; +} + +static int write_silence_wav(const char *path) { + FILE *file = fopen(path, "wb"); + if (!file) { + fprintf(stderr, "open %s: %s\n", path, strerror(errno)); + return -1; + } + if (write_wav_header(file, TOTAL_SAMPLES) != 0) { + fclose(file); + fprintf(stderr, "write header %s failed\n", path); + return -1; + } + for (int sample = 0; sample < TOTAL_SAMPLES; sample++) { + if (write_i16_le(file, 0) != 0) { + fclose(file); + fprintf(stderr, "write sample %s failed\n", path); + return -1; + } + } + return fclose(file); +} + +static int write_v21_wav(const char *path) { + FILE *file = fopen(path, "wb"); + if (!file) { + fprintf(stderr, "open %s: %s\n", path, strerror(errno)); + return -1; + } + + if (write_wav_header(file, TOTAL_SAMPLES) != 0) { + fclose(file); + fprintf(stderr, "write header %s failed\n", path); + return -1; + } + + v21_bits_t bits = {0}; + fsk_tx_state_t *tx = fsk_tx_init(NULL, &preset_fsk_specs[FSK_V21CH1], get_v21_bit, &bits); + if (!tx) { + fclose(file); + fprintf(stderr, "fsk_tx_init failed\n"); + return -1; + } + + int16_t samples[BLOCK_SAMPLES]; + int remaining = TOTAL_SAMPLES; + while (remaining > 0) { + int count = remaining > BLOCK_SAMPLES ? BLOCK_SAMPLES : remaining; + int generated = fsk_tx(tx, samples, count); + if (generated != count) { + fsk_tx_free(tx); + fclose(file); + fprintf(stderr, "fsk_tx generated %d of %d samples\n", generated, count); + return -1; + } + for (int index = 0; index < generated; index++) { + if (write_i16_le(file, samples[index]) != 0) { + fsk_tx_free(tx); + fclose(file); + fprintf(stderr, "write sample %s failed\n", path); + return -1; + } + } + remaining -= generated; + } + + fsk_tx_free(tx); + return fclose(file); +} + +static int copy_file(const char *from, const char *to) { + FILE *source = fopen(from, "rb"); + if (!source) { + fprintf(stderr, "open %s: %s\n", from, strerror(errno)); + return -1; + } + FILE *target = fopen(to, "wb"); + if (!target) { + fclose(source); + fprintf(stderr, "open %s: %s\n", to, strerror(errno)); + return -1; + } + + uint8_t buffer[8192]; + size_t count; + while ((count = fread(buffer, 1, sizeof(buffer), source)) > 0) { + if (fwrite(buffer, 1, count, target) != count) { + fclose(source); + fclose(target); + fprintf(stderr, "write %s failed\n", to); + return -1; + } + } + + int read_error = ferror(source); + int close_source = fclose(source); + int close_target = fclose(target); + return read_error || close_source || close_target ? -1 : 0; +} + +static int write_report(const char *path, const char *note) { + FILE *file = fopen(path, "wb"); + if (!file) { + fprintf(stderr, "open %s: %s\n", path, strerror(errno)); + return -1; + } + + int ok = fprintf( + file, + "{\n" + " \"source\": \"synthetic-spandsp\",\n" + " \"note\": \"%s\",\n" + " \"sampleRate\": 8000,\n" + " \"channels\": 1,\n" + " \"bitDepth\": 16,\n" + " \"durationSeconds\": 30\n" + "}\n", + note + ) > 0; + + return fclose(file) == 0 && ok ? 0 : -1; +} + +static int get_v21_bit(void *user_data) { + static const uint8_t pattern[] = {0xff, 0x01, 0x7e}; + v21_bits_t *bits = (v21_bits_t *) user_data; + int bit; + + if (bits->bit_index < V21_MARK_BITS) { + bit = 1; + } else { + int payload_bit = bits->bit_index - V21_MARK_BITS; + uint8_t byte = pattern[(payload_bit / 8) % (int) (sizeof(pattern) / sizeof(pattern[0]))]; + bit = (byte >> (payload_bit % 8)) & 1; + } + bits->bit_index++; + return bit; +}