summaryrefslogtreecommitdiff
path: root/util/spkmodem_decode/spkmodem-decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/spkmodem_decode/spkmodem-decode.c')
-rw-r--r--util/spkmodem_decode/spkmodem-decode.c158
1 files changed, 72 insertions, 86 deletions
diff --git a/util/spkmodem_decode/spkmodem-decode.c b/util/spkmodem_decode/spkmodem-decode.c
index 8c57ff9a..0a22c6d5 100644
--- a/util/spkmodem_decode/spkmodem-decode.c
+++ b/util/spkmodem_decode/spkmodem-decode.c
@@ -157,15 +157,10 @@
/*
* These determine how long the program will wait during
* tone auto-detection, before shifting to defaults.
- *
- * For tone auto-detection (time waiting for detection)
- * NOTE: you could multiply SAMPLE_PER_FRAME instead
- * of SAMPLE_RATE in LEARN_SAMPLES, for more granularity.
- * Here, 1 * SAMPLE_RATE represents 1 second, which seems
- * like a reasonable, conservative default wait time.
+ * It is done every LEARN_FRAMES number of frames.
*/
#define LEARN_SECONDS 1
-#define LEARN_SAMPLES ((LEARN_SECONDS) * (SAMPLE_RATE))
+#define LEARN_FRAMES ((LEARN_SECONDS) * (FRAME_RATE))
/*
* Sample amplitude threshold used to convert the waveform
@@ -209,20 +204,20 @@ struct decoder_state {
int freq_min;
int freq_max;
int freq_threshold;
- int learn_samples;
+ int learn_frames;
};
static const char *argv0;
static int host_is_big_endian(void);
static void handle_audio(struct decoder_state *st);
+static void auto_detect_tone(struct decoder_state *st);
+static int silent_signal(struct decoder_state *st);
+static void select_low_tone(struct decoder_state *st);
static void collect_separator_tone(struct decoder_state *st);
static int valid_signal(struct decoder_state *st);
static void decode_pulse(struct decoder_state *st);
-static void auto_detect_tone(struct decoder_state *st);
-static int silent_signal(struct decoder_state *st);
static signed short read_sample(struct decoder_state *st);
-static void select_low_tone(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);
@@ -317,6 +312,72 @@ handle_audio(struct decoder_state *st)
st->sample_count = 0;
for (sample = 0; sample < SAMPLES_PER_FRAME; sample++)
decode_pulse(st);
+
+ /* Detect tone per each frame */
+ auto_detect_tone(st);
+}
+
+/*
+ * Automatically detect spkmodem tone
+ */
+static void
+auto_detect_tone(struct decoder_state *st)
+{
+ if (st->learn_frames >= LEARN_FRAMES)
+ return;
+
+ st->learn_frames++;
+
+ if (silent_signal(st))
+ return;
+
+ select_low_tone(st);
+
+ if (st->learn_frames == LEARN_FRAMES) {
+ st->freq_threshold =
+ (st->freq_min + st->freq_max) / 2;
+
+ if (st->debug)
+ printf("auto threshold: %dHz\n",
+ st->freq_threshold * FRAME_RATE);
+ }
+}
+
+/*
+ * Ignore silence / near silence.
+ * Both FIR windows will be near zero when no signal exists.
+ */
+static int
+silent_signal(struct decoder_state *st)
+{
+ return (st->freq_data <= 2 &&
+ st->freq_separator <= 2);
+}
+
+/*
+ * Choose the lowest active tone.
+ * Separator frames carry tone in the separator window,
+ * data frames carry tone in the data window.
+ */
+static void
+select_low_tone(struct decoder_state *st)
+{
+ int f;
+
+ f = st->freq_data;
+
+ if (f <= 0 || (st->freq_separator > 0 &&
+ st->freq_separator < f))
+ f = st->freq_separator;
+
+ if (f <= 0)
+ return;
+
+ if (f < st->freq_min)
+ st->freq_min = f;
+
+ if (f > st->freq_max)
+ st->freq_max = f;
}
/*
@@ -439,84 +500,9 @@ decode_pulse(struct decoder_state *st)
st->ringpos = ringpos;
st->sep_pos = sep_pos;
- /*
- * Attempt to auto-detect spkmodem tone
- */
- auto_detect_tone(st);
-
st->sample_count++;
}
-/*
- * Observe signal for LEARN_SAMPLES samples (e.g. 1 second).
- * The exact amount of time is determined by LEARN_SAMPLES
- * divided by SAMPLE_RATE, logically. For example, if
- * LEARN_SAMPLES were half of the SAMPLE_RATE, this
- * corresponds to roughly 500ms before timeout.
- *
- * to guess the correct timing. If it fails,
- * fall back to known good values.
- */
-static void
-auto_detect_tone(struct decoder_state *st)
-{
- if (st->learn_samples >= LEARN_SAMPLES)
- return;
-
- st->learn_samples++;
-
- if (silent_signal(st))
- return;
-
- select_low_tone(st);
-
- if (st->learn_samples == LEARN_SAMPLES) {
- st->freq_threshold =
- (st->freq_min + st->freq_max) / 2;
-
- if (st->debug)
- printf("auto threshold: %dHz\n",
- st->freq_threshold * FRAME_RATE);
- }
-}
-
-/*
- * Ignore silence / near silence.
- * Both FIR windows will be near zero when no signal exists.
- */
-static int
-silent_signal(struct decoder_state *st)
-{
- return (st->freq_data <= 2 &&
- st->freq_separator <= 2);
-}
-
-/*
- * Choose the lowest active tone.
- * Separator frames carry tone in the separator window,
- * data frames carry tone in the data window.
- */
-static void
-select_low_tone(struct decoder_state *st)
-{
- int f;
-
- f = st->freq_data;
-
- if (f <= 0 || (st->freq_separator > 0 &&
- st->freq_separator < f))
- f = st->freq_separator;
-
- if (f <= 0)
- return;
-
- if (f < st->freq_min)
- st->freq_min = f;
-
- if (f > st->freq_max)
- st->freq_max = f;
-}
-
static signed short
read_sample(struct decoder_state *st)
{