| .. | ||
| selcald | ||
| .gitignore | ||
| add-user-to-audio-group.sh | ||
| audio-capture.sh | ||
| audio-pipe.sh | ||
| filters.py | ||
| live.py | ||
| raw-to-wav.sh | ||
| README.md | ||
| requirements.txt | ||
| samples.py | ||
| selcal-detect.py | ||
| selcal-fft.py | ||
| tonegen.py | ||
| tones.csv | ||
| tones.py | ||
| utilities.py | ||
Planned algorithm
From selcald: One possible solution to this problem is to step back from trying to determine the frequencies of the individual tones and to instead verify that:
- There are two tones present
- The difference in frequency between the two tones matches a pair of known tones in the alphabet
The author of selcald seems awfully hung up on trying to ensure correct detection of the silent period
between two tones. I don't think this is worth actively trying to detect, as it is more important
to find two dominant tones for a period of ~1 sec, followed by another 1 sec with two dominant tones.
The silence period is irrelevant - according to the spec of 0.2 +/- 0.1 sec at the transmitter it
could be impossibly short to reliably distinguish between successive A*-A* tones at the receiver.
Terrible pseudocode
collect samples from audio source <wavfile, arecord>
low pass & decimate if necessary
<simultaneously>
run wide fft over a large sample window
detect peak bin (with some hysteresis)
if peak bin within tone band:
assume difference is due to doppler shift
gradually adjust expected freq(s) for tone(s) to match
record RMS energy into buffer
<simultaneously>
run correlation over small sample window
For each tone in the alphabet:
Cross correlate the audio with the adjusted tone
Record normalized tone energy into tone buffer
For tone record in tone buffer:
sort tones by amplitude
if:
- the two highest amplitude tones are within 3 dB of each other
- the two highest amplitude tones are at least 3 dB greater than the next nearest tone
- the sum of the two highest tones account for at least 60% of the modulation energy (-2.22 dB)
(as determined relative to stable RMS energy calc'd by wide fft)
(nominally 90% / -0.458 dB)
then:
record dominant two tones in tone buffer
if any two tones are dominant tones for the majority of previous 1 sec:
record dominant two tones in code buffer
reset tone detection counter (prohibit detecting codes for another 0.5 sec)
upon code record in code buffer:
if dominant code previously occured within 1.25 sec
emit SELCAL detection
reset code detection counter (prohibit detecting codes for another 0.5 sec)