8#include "AudioTools/CoreAudio/Analysis/GoerzelStream.h"
39 float findFrame(
const float* samples,
unsigned frame_nsamples,
40 unsigned try_first_sample,
unsigned try_max_nsamples,
41 unsigned try_step_nsamples,
float try_confidence_search_limit,
42 const char* expect_bits_string, uint64_t* bits_outp,
43 float* ampl_outp,
unsigned* frame_start_outp) {
44 int expect_n_bits = strlen(expect_bits_string);
45 if (expect_n_bits == 0 || expect_n_bits >
MAX_BITS)
return 0.0f;
46 float samples_per_bit = (float)frame_nsamples / expect_n_bits;
49 float best_c = 0.0f, best_a = 0.0f;
50 uint64_t best_bits = 0;
55 for (
int j = 0;; j++) {
56 int up = (j % 2) ? 1 : -1;
57 int t = try_first_sample + up * ((j + 1) / 2) * try_step_nsamples;
58 if (t >= (
int)try_max_nsamples)
break;
61 float ampl_out = 0.0f;
62 uint64_t bits_out = 0;
63 float c =
frameAnalyze(samples + t, samples_per_bit, expect_n_bits,
64 expect_bits_string, &bits_out, &l_out);
71 if (best_c >= try_confidence_search_limit)
break;
74 *bits_outp = best_bits;
76 *frame_start_outp = best_t;
83 float min_mag_threshold) {
84 float magscalar = 1.0f / ((float)nsamples / 2.0f);
86 int max_mag_band = -1;
88 for (
unsigned i = 1; i <
nbands; i++) {
90 if (mag < min_mag_threshold)
continue;
136 audio_tools::GoertzelConfig gcfg;
140 gcfg.block_size = nsamples;
141 return detector.begin(gcfg);
145 float magnitude(audio_tools::GoertzelDetector& detector,
146 const float* samples,
unsigned nsamples) {
148 for (
unsigned j = 0; j < nsamples; j++) detector.processSample(samples[j]);
149 return detector.getMagnitude();
152 float bandMagnitude(
const float* samples,
unsigned nsamples,
unsigned band) {
153 audio_tools::GoertzelDetector detector;
155 return magnitude(detector, samples, nsamples);
159 unsigned* bit_outp,
float* bit_signal_mag_outp,
160 float* bit_noise_mag_outp) {
166 float magscalar = 2.0f / (float)bit_nsamples;
171 if (mag_mark > mag_space) {
173 *bit_signal_mag_outp = mag_mark;
174 *bit_noise_mag_outp = mag_space;
177 *bit_signal_mag_outp = mag_space;
178 *bit_noise_mag_outp = mag_mark;
183 float frameAnalyze(
const float* samples,
float samples_per_bit,
int n_bits,
184 const char* expect_bits, uint64_t* bits_outp,
186 unsigned bit_nsamples = (float)(samples_per_bit + 0.5f);
192 for (
int bitnum = 0; bitnum < n_bits; bitnum++) {
193 if (expect_bits[bitnum] ==
'd')
continue;
194 unsigned bit_begin_sample = (float)(samples_per_bit * bitnum + 0.5f);
195 bitAnalyze(samples + bit_begin_sample, bit_nsamples, &bit_values[bitnum],
196 &bit_sig_mags[bitnum], &bit_noise_mags[bitnum]);
197 if ((
unsigned)(expect_bits[bitnum] -
'0') != bit_values[bitnum])
202 for (
int bitnum = 0; bitnum < n_bits; bitnum++) {
203 if (expect_bits[bitnum] !=
'd')
continue;
204 unsigned bit_begin_sample = (float)(samples_per_bit * bitnum + 0.5f);
205 bitAnalyze(samples + bit_begin_sample, bit_nsamples, &bit_values[bitnum],
206 &bit_sig_mags[bitnum], &bit_noise_mags[bitnum]);
209 float total_bit_sig = 0.0f, total_bit_noise = 0.0f;
210 float avg_mark_sig = 0.0f, avg_space_sig = 0.0f;
211 unsigned n_mark = 0, n_space = 0;
212 for (
int bitnum = 0; bitnum < n_bits; bitnum++) {
215 total_bit_sig += bit_sig_mags[bitnum];
216 if (bit_noise_mags[bitnum] > FLT_EPSILON)
217 total_bit_noise += bit_noise_mags[bitnum];
218 if (bit_values[bitnum] == 1) {
219 avg_mark_sig += bit_sig_mags[bitnum];
222 avg_space_sig += bit_sig_mags[bitnum];
228 float snr = total_bit_sig / total_bit_noise;
229 float avg_bit_sig = total_bit_sig / n_bits;
230 if (n_mark) avg_mark_sig /= n_mark;
231 if (n_space) avg_space_sig /= n_space;
234 float divergence = 0.0f;
235 for (
int bitnum = 0; bitnum < n_bits; bitnum++) {
236 float avg_bit_sig_other = bit_values[bitnum] ? avg_mark_sig : avg_space_sig;
238 fabsf(bit_sig_mags[bitnum] - avg_bit_sig_other) / avg_bit_sig_other;
241 divergence /= n_bits;
244 float confidence = snr * (1.0f - divergence);
245 *ampl_outp = avg_bit_sig;
249 for (
int bitnum = 0; bitnum < n_bits && bitnum < 64; bitnum++)
250 *bits_outp |= (uint64_t)bit_values[bitnum] << bitnum;
FSK bit and frame analysis (port of minimodem's fsk.c). Instead of a full FFT we use the Goertzel alg...
Definition FSKDemodulator.h:19
unsigned b_space
Definition FSKDemodulator.h:124
float f_space
Definition FSKDemodulator.h:119
unsigned nbands
Definition FSKDemodulator.h:122
float frameAnalyze(const float *samples, float samples_per_bit, int n_bits, const char *expect_bits, uint64_t *bits_outp, float *ampl_outp)
returns confidence value [0.0 to INFINITY]
Definition FSKDemodulator.h:183
void bitAnalyze(const float *samples, unsigned bit_nsamples, unsigned *bit_outp, float *bit_signal_mag_outp, float *bit_noise_mag_outp)
Definition FSKDemodulator.h:158
float bandMagnitude(const float *samples, unsigned nsamples, unsigned band)
Definition FSKDemodulator.h:152
float bandWidth()
Definition FSKDemodulator.h:110
unsigned spaceBand()
Definition FSKDemodulator.h:112
float bandFrequency(unsigned band)
center frequency of the FFT bin which corresponds to the band
Definition FSKDemodulator.h:130
unsigned fftSize()
Definition FSKDemodulator.h:108
unsigned bandCount()
Definition FSKDemodulator.h:109
bool setupDetector(audio_tools::GoertzelDetector &detector, unsigned band, unsigned nsamples)
Definition FSKDemodulator.h:134
bool begin(float sample_rate, float f_mark, float f_space, float filter_bw)
Defines the tones and the filter bandwidth: returns false if invalid.
Definition FSKDemodulator.h:22
int detectCarrier(const float *samples, unsigned nsamples, float min_mag_threshold)
Definition FSKDemodulator.h:82
unsigned markBand()
Definition FSKDemodulator.h:111
unsigned detector_nsamples
Definition FSKDemodulator.h:127
float band_width
Definition FSKDemodulator.h:120
unsigned fftsize
Definition FSKDemodulator.h:121
static constexpr int MAX_BITS
Definition FSKDemodulator.h:116
float magnitude(audio_tools::GoertzelDetector &detector, const float *samples, unsigned nsamples)
unscaled magnitude of the band over n samples
Definition FSKDemodulator.h:145
audio_tools::GoertzelDetector mark_detector
Definition FSKDemodulator.h:125
float sample_rate
Definition FSKDemodulator.h:117
float findFrame(const float *samples, unsigned frame_nsamples, unsigned try_first_sample, unsigned try_max_nsamples, unsigned try_step_nsamples, float try_confidence_search_limit, const char *expect_bits_string, uint64_t *bits_outp, float *ampl_outp, unsigned *frame_start_outp)
Definition FSKDemodulator.h:39
void setTonesByBandShift(unsigned b_mark, int b_shift)
Redefines the mark and space band.
Definition FSKDemodulator.h:100
unsigned b_mark
Definition FSKDemodulator.h:123
float f_mark
Definition FSKDemodulator.h:118
audio_tools::GoertzelDetector space_detector
Definition FSKDemodulator.h:126
TinyModem: software audio modems and packets with error correction.
Definition AX25.h:11