diff --git a/util/spkmodem_recv/.gitignore b/util/spkmodem_recv/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2f5c946cc4b2f00e25e0f2282d538d421e279e5f --- /dev/null +++ b/util/spkmodem_recv/.gitignore @@ -0,0 +1 @@ +spkmodem-recv diff --git a/util/spkmodem_recv/Makefile b/util/spkmodem_recv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..92a3bfe930144461c8de02548efa22950c491ca8 --- /dev/null +++ b/util/spkmodem_recv/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +PREFIX ?= /usr/local +INSTALL ?= install + +spkmodem-recv: + $(CC) -o $@ $@.c +install: spkmodem-recv + $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin/ + $(INSTALL) $< -t $(DESTDIR)$(PREFIX)/bin/ diff --git a/util/spkmodem_recv/annotation b/util/spkmodem_recv/annotation new file mode 100644 index 0000000000000000000000000000000000000000..eb4dd0533733af5dbe6471b9c058ccb52a7a65ca --- /dev/null +++ b/util/spkmodem_recv/annotation @@ -0,0 +1,119 @@ +/* spkmodem-recv.c - decode spkmodem signals */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Compilation: gcc -o spkmodem-recv spkmodem-recv */ +/* Usage: parec --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv */ + +// 1/48000Hz * 240 = 5ms, +#define SAMPLES_PER_TRAME 240 +// 5 transitions = 2.5 pulses/5ms = 500Hz +#define FREQ_SEP_MIN 5 +// 15 transitions = 7.5 pulses/5ms = 1500Hz +#define FREQ_SEP_MAX 15 +// 15 transitions = 7.5 pulses/5ms = 1500Hz +#define FREQ_DATA_MIN 15 +// 25 transitions = 12.5 pulses/5ms = 2500Hz +#define FREQ_DATA_THRESHOLD 25 +// 60 transitions = 30 pulses/5ms = 6000Hz +#define FREQ_DATA_MAX 60 +// Threshold amplitude to register a transition +#define THRESHOLD 500 + +#define DEBUG 0 +#define FLUSH_TIMEOUT 1 + +// Just a ring buffer of the raw samples, not meaningfully +// used otherwise +static signed short trame[2 * SAMPLES_PER_TRAME]; +// stores a 1 for each detected edge transition of the audio signal, +// 0 otherwise +static signed short pulse[2 * SAMPLES_PER_TRAME]; +// ring buffer index +static int ringpos = 0; +// pos is the polarity to look for in the next sample +// f1 counts the number of transitions in each trame +// f2 +static int pos, f1, f2; +// amplitude not meaningfully used +static int amplitude = 0; +static int lp = 0; + +static void read_sample (void) +{ + amplitude -= abs (trame[ringpos]); + f1 -= pulse[ringpos]; + // ringpos + SAMPLES_PER_TRAME will be the results of the + // previous trame interval + f1 += pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)]; + // gradually clear the count of pulses from the previous trame from f1 + f2 -= pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)]; + // Read one 16 bit sample to trame index ringpos + fread (trame + ringpos, 1, sizeof (trame[0]), stdin); + // amplitude will be the difference in magnitude of old value + // in trame and new value + amplitude += abs (trame[ringpos]); + + // if magnitude of trame[ringpos] greater than threshold, set pulse to 1 + // found positive peak, now look for negative peak + if (pos ? (trame[ringpos] < -THRESHOLD) : (trame[ringpos] > +THRESHOLD)) { + pulse[ringpos] = 1; + // Invert sign flag + pos = !pos; + f2++; + } else { + pulse[ringpos] = 0; + } + // move buffer index forward + ringpos++; + ringpos %= 2 * SAMPLES_PER_TRAME; + lp++; +} + +int main () +{ + int bitn = 7; + char c = 0; + int i; + int llp = 0; + while (!feof (stdin)) { + // lp gets reset whenever a valid bit is detected, + // reset things if a bit hasn't been read in a while + if (lp > 3 * SAMPLES_PER_TRAME) { + bitn = 7; + c = 0; + lp = 0; + llp++; + } + if (llp == FLUSH_TIMEOUT) + fflush (stdout); + if (f2 > FREQ_SEP_MIN && f2 < FREQ_SEP_MAX + && f1 > FREQ_DATA_MIN && f1 < FREQ_DATA_MAX) { + #if DEBUG + printf ("%d %d %d @%d\n", f1, f2, FREQ_DATA_THRESHOLD, ftell (stdin) - sizeof (trame)); + #endif + if (f1 < FREQ_DATA_THRESHOLD) + c |= (1 << bitn); + bitn--; + if (bitn < 0) { + #if DEBUG + printf ("<%c, %x>", c, c); + #else + printf ("%c", c); + #endif + bitn = 7; + c = 0; + } + lp = 0; + llp = 0; + for (i = 0; i < SAMPLES_PER_TRAME; i++) + read_sample (); + continue; + } + read_sample (); + } + return 0; +} diff --git a/util/spkmodem_recv/description.md b/util/spkmodem_recv/description.md new file mode 100644 index 0000000000000000000000000000000000000000..fe62f1691787debcdc3bbf70691fc8101ea00aca --- /dev/null +++ b/util/spkmodem_recv/description.md @@ -0,0 +1 @@ +Decode spkmodem signals `C` diff --git a/util/spkmodem_recv/spkmodem-recv.c b/util/spkmodem_recv/spkmodem-recv.c new file mode 100644 index 0000000000000000000000000000000000000000..cd7bd483d09b3d6be6f9204af1325a4c667bf60a --- /dev/null +++ b/util/spkmodem_recv/spkmodem-recv.c @@ -0,0 +1,100 @@ +/* spkmodem-recv.c - decode spkmodem signals */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Compilation: gcc -o spkmodem-recv spkmodem-recv */ +/* Usage: parec --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv */ + +#define SAMPLES_PER_TRAME 240 +#define FREQ_SEP_MIN 5 +#define FREQ_SEP_MAX 15 +#define FREQ_DATA_MIN 15 +#define FREQ_DATA_THRESHOLD 25 +#define FREQ_DATA_MAX 60 +#define THRESHOLD 500 + +#define DEBUG 0 +#define FLUSH_TIMEOUT 1 + +static signed short trame[2 * SAMPLES_PER_TRAME]; +static signed short pulse[2 * SAMPLES_PER_TRAME]; +static int ringpos = 0; +static int pos, f1, f2; +static int amplitude = 0; +static int lp = 0; + +static void +read_sample (void) +{ + amplitude -= abs (trame[ringpos]); + f1 -= pulse[ringpos]; + f1 += pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)]; + f2 -= pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)]; + fread (trame + ringpos, 1, sizeof (trame[0]), stdin); + amplitude += abs (trame[ringpos]); + + if (pos ? (trame[ringpos] < -THRESHOLD) + : (trame[ringpos] > +THRESHOLD)) + { + pulse[ringpos] = 1; + pos = !pos; + f2++; + } + else + pulse[ringpos] = 0; + ringpos++; + ringpos %= 2 * SAMPLES_PER_TRAME; + lp++; +} + +int +main () +{ + int bitn = 7; + char c = 0; + int i; + int llp = 0; + while (!feof (stdin)) + { + if (lp > 3 * SAMPLES_PER_TRAME) + { + bitn = 7; + c = 0; + lp = 0; + llp++; + } + if (llp == FLUSH_TIMEOUT) + fflush (stdout); + if (f2 > FREQ_SEP_MIN && f2 < FREQ_SEP_MAX + && f1 > FREQ_DATA_MIN && f1 < FREQ_DATA_MAX) + { +#if DEBUG + printf ("%d %d %d @%d\n", f1, f2, FREQ_DATA_THRESHOLD, + ftell (stdin) - sizeof (trame)); +#endif + if (f1 < FREQ_DATA_THRESHOLD) + c |= (1 << bitn); + bitn--; + if (bitn < 0) + { +#if DEBUG + printf ("<%c, %x>", c, c); +#else + printf ("%c", c); +#endif + bitn = 7; + c = 0; + } + lp = 0; + llp = 0; + for (i = 0; i < SAMPLES_PER_TRAME; i++) + read_sample (); + continue; + } + read_sample (); + } + return 0; +}