From 9ac03315958c20b1f6c0bac0988033d007c3d977 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Thu, 12 Mar 2026 05:03:42 +0000 Subject: util/spkmodem-recv: buffer calls to fread() we currently read small amounts of data with fread, repeatedly, which is quite taxing on the CPU, on very old systems. 48khz audio. 48000 calls to fread() per second? yeah. let's optimise this. performance now should be roughly O(1) in practise. this and the other recent changes means no modulo or division, reduced branching, memory memory roads, and lots of buffering. the buffering here is quite conservative, so the human won't notice any difference. we're cutting the number of times we call fread by a factor of several thousand, but you'll still see text scrolling down pretty quick, with minimal lag. the old GNU code i forked was terrible at this. Signed-off-by: Leah Rowe --- util/spkmodem_recv/spkmodem-recv.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/util/spkmodem_recv/spkmodem-recv.c b/util/spkmodem_recv/spkmodem-recv.c index 7bfdaff3..52466215 100644 --- a/util/spkmodem_recv/spkmodem-recv.c +++ b/util/spkmodem_recv/spkmodem-recv.c @@ -36,10 +36,16 @@ #define THRESHOLD 500 +#define READ_BUF 4096 + struct decoder_state { signed short frame[MAX_SAMPLES]; unsigned char pulse[MAX_SAMPLES]; + signed short inbuf[READ_BUF]; + size_t inpos; + size_t inlen; + int ringpos; int sep_pos; @@ -58,6 +64,7 @@ static const char *argv0; static void handle_audio(struct decoder_state *st); static int valid_signal(struct decoder_state *st); static void decode_pulse(struct decoder_state *st); +static signed short read_sample(struct decoder_state *st); static int set_ascii_bit(struct decoder_state *st); static void print_char(struct decoder_state *st); static void print_stats(struct decoder_state *st); @@ -151,7 +158,6 @@ valid_signal(struct decoder_state *st) static void decode_pulse(struct decoder_state *st) { - size_t n; unsigned char old_ring, old_sep; unsigned char new_pulse; @@ -162,12 +168,7 @@ decode_pulse(struct decoder_state *st) st->freq_data += old_sep; st->freq_separator -= old_sep; - n = fread(&st->frame[st->ringpos], sizeof(st->frame[0]), 1, stdin); - if (n != 1) { - if (feof(stdin)) - exit(EXIT_SUCCESS); - err(errno, "stdin read"); - } + st->frame[st->ringpos] = read_sample(st); new_pulse = abs(st->frame[st->ringpos]) > THRESHOLD; st->pulse[st->ringpos] = new_pulse; @@ -184,6 +185,29 @@ decode_pulse(struct decoder_state *st) st->sample_count++; } +static signed short +read_sample(struct decoder_state *st) +{ + size_t n; + + if (st->inpos >= st->inlen) { + + n = fread(st->inbuf, sizeof(st->inbuf[0]), + READ_BUF, stdin); + + if (n == 0) { + if (feof(stdin)) + exit(EXIT_SUCCESS); + err(errno, "stdin read"); + } + + st->inpos = 0; + st->inlen = n; + } + + return st->inbuf[st->inpos++]; +} + static int set_ascii_bit(struct decoder_state *st) { -- cgit v1.2.1