diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-13 02:06:29 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-13 02:21:20 +0000 |
| commit | 2d77f9649d8e0c1f873e766549869cee0e0c7063 (patch) | |
| tree | 3d5893524830addc42011bc7c7b2b90ed67a5d01 /util/spkmodem_decode | |
| parent | 656c39e45ccb41592776fb49d06c036a7c0f8a6c (diff) | |
spkmodem-decode: edge detection *and* amplitude
for pulses, we currently use amplitude detection.
edge detection is better, because weak / low gain
signals will be more reliable. if audio is coming
in on/from a system that does automatic gain
adjustment, this once again is more robust too.
microphones and speakers (which people often use
with spkmodem if nothing else available) often
clamp amplitude, to an extent that this software
may not detect those pulses reliably that way.
so we detect slope edges instead. this causes
very little performance penalty (use of abs(),
that's about it)
however, edge detection is inherently vulnerable
to noise, so we will also detect amplitude. this
acts as an effective noise filter, while still
improving pulse detection.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/spkmodem_decode')
| -rw-r--r-- | util/spkmodem_decode/spkmodem-decode.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/util/spkmodem_decode/spkmodem-decode.c b/util/spkmodem_decode/spkmodem-decode.c index 0f28bc6f..40581dd7 100644 --- a/util/spkmodem_decode/spkmodem-decode.c +++ b/util/spkmodem_decode/spkmodem-decode.c @@ -206,6 +206,9 @@ struct decoder_state { int freq_max; int freq_threshold; int learn_frames; + + /* previous sample used for edge detection */ + signed short prev_sample; }; static const char *argv0; @@ -445,9 +448,11 @@ decode_pulse(struct decoder_state *st) { unsigned char old_ring, old_sep; unsigned char new_pulse; + signed short sample; int ringpos; int sep_pos; - signed short sample; + int diff_edge; + int diff_amp; ringpos = st->ringpos; sep_pos = st->sep_pos; @@ -483,18 +488,33 @@ decode_pulse(struct decoder_state *st) sample = read_sample(st); /* - * Convert the waveform sample into a pulse (0 or 1). + * Avoid startup edge. Since + * it's zero at startup, this + * may wrongly produce a pulse + */ + if (st->sample_count == 0) + st->prev_sample = sample; + + /* + * Detect edges instead of amplitude. + * This is more tolerant of weak microphones + * and speaker distortion.. * - * The unsigned comparison creates a small dead zone near zero, - * suppressing small amplitude noise from microphones or - * cheap ADCs. Real PC speaker tones are far outside this - * range, so they still produce clean pulses. + * However, we check both slope edges and + * amplitude, to mitagate noise. */ - if ((unsigned)(sample + THRESHOLD) - > (unsigned)(2 * THRESHOLD)) + diff_amp = sample; + diff_edge = sample - st->prev_sample; + if (diff_edge < 0) + diff_edge = -diff_edge; + if (diff_amp < 0) + diff_amp = -diff_amp; + if (diff_edge > THRESHOLD && + diff_amp > THRESHOLD) new_pulse = 1; else new_pulse = 0; + st->prev_sample = sample; st->pulse[ringpos] = new_pulse; st->freq_separator += new_pulse; |
