mirror of
https://github.com/romanz/amodem.git
synced 2026-02-06 16:48:06 +08:00
206 lines
11 KiB
Plaintext
206 lines
11 KiB
Plaintext
# Audio Modem Communication Library
|
|
|
|
[](https://travis-ci.org/romanz/amodem)
|
|
[](https://coveralls.io/r/romanz/amodem?branch=master)
|
|
[](https://landscape.io/github/romanz/amodem/master)
|
|
[](https://pypi.python.org/pypi/amodem/)
|
|
[](https://pypi.python.org/pypi/amodem/)
|
|
|
|
# Description
|
|
|
|
This program can be used to transmit a specified file between 2 computers, using
|
|
a simple audio cable (for better SNR and higher speeds) or a simple headset,
|
|
allowing true air-gapped communication (via a speaker and a microphone).
|
|
|
|
The sender modulates an input binary data file into an 32kHz audio,
|
|
which is played to the sound card.
|
|
|
|
The receiver side records the transmitted audio,
|
|
which is demodulated concurrently into an output binary data file.
|
|
|
|
The process requires a single manual calibration step: the transmitter has to
|
|
find maximal output volume for its sound card, which will not saturate the
|
|
receiving microphone.
|
|
|
|
The modem is using OFDM over an audio cable with the following parameters:
|
|
|
|
- Sampling rate: 32 kHz
|
|
- Baud rate: 1 kHz
|
|
- Symbol modulation: BPSK, 4-PSK, 16-QAM ,64-QAM
|
|
- Carriers: 2-11 kHz
|
|
|
|
This way, modem may achieve 60kbps bitrate = 7.5 kB/s.
|
|
|
|
A simple CRC-32 checksum is used for data integrity verification
|
|
on each 250 byte data frame.
|
|
|
|
|
|
# Installation
|
|
|
|
Make sure that `numpy` and `PortAudio v19` packages are installed (on Debian):
|
|
|
|
$ sudo apt-get install python-numpy portaudio19-dev
|
|
|
|
Clone and install latest version:
|
|
|
|
$ git clone https://github.com/romanz/amodem.git
|
|
$ pip install --user -e amodem
|
|
|
|
For graphs and visualization (optional), install `matplotlib` Python package.
|
|
|
|
For validation, run:
|
|
|
|
$ export BITRATE=48 # explicitly select high MODEM bit rate (assuming good SNR).
|
|
$ amodem-cli -h
|
|
usage: amodem-cli [-h] {send,recv} ...
|
|
|
|
Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz
|
|
|
|
positional arguments:
|
|
{send,recv}
|
|
send modulate binary data into audio signal.
|
|
recv demodulate audio signal into binary data.
|
|
|
|
optional arguments:
|
|
-h, --help show this help message and exit
|
|
|
|
|
|
# Calibration
|
|
|
|
Connect the audio cable between the sender and the receiver, and run the
|
|
following scripts:
|
|
|
|
- On the sender's side:
|
|
```
|
|
~/sender $ export BITRATE=48 # explicitly select high MODEM bit rate (assuming good SNR).
|
|
~/sender $ amodem-cli send --calibrate
|
|
```
|
|
|
|
- On the receiver's side:
|
|
```
|
|
~/receiver $ export BITRATE=48 # explicitly select high MODEM bit rate (assuming good SNR).
|
|
~/receiver $ amodem-cli recv --calibrate
|
|
```
|
|
|
|
If BITRATE is not set, the MODEM will use 1 kbps settings (single frequency with BPSK modulation).
|
|
|
|
Change the sender computer's output audio level, until
|
|
all frequencies are received well:
|
|
```
|
|
3000 Hz: good signal
|
|
4000 Hz: good signal
|
|
5000 Hz: good signal
|
|
6000 Hz: good signal
|
|
7000 Hz: good signal
|
|
8000 Hz: good signal
|
|
9000 Hz: good signal
|
|
10000 Hz: good signal
|
|
```
|
|
|
|
If the signal is "too weak", increase the sender's output audio level.
|
|
|
|
If the signal is "too strong", decrease the sender's output audio level.
|
|
|
|
If the signal is "too noisy", the SNR is probably too low: decrease the
|
|
background noise or increase the signal (without causing saturation).
|
|
|
|
You can see a video of the calibration process [here](http://www.youtube.com/watch?v=jRUj2Ifk-Po).
|
|
|
|
# Usage
|
|
|
|
- Prepare the sender (generate a random binary data file to be sent):
|
|
|
|
```
|
|
~/sender $ dd if=/dev/urandom of=data.tx bs=10KB count=1 status=none
|
|
~/sender $ sha256sum data.tx
|
|
008df57d4f3ed6e7a25d25afd57d04fc73140e8df604685bd34fcab58f5ddc01 data.tx
|
|
```
|
|
|
|
- Start the receiver (will wait for the sender to start):
|
|
```
|
|
~/receiver $ amodem-cli recv -vv -i data.rx
|
|
```
|
|
|
|
- Start the sender (will modulate the data and start the transmission):
|
|
```
|
|
~/sender $ amodem-cli send -vv -o data.tx
|
|
```
|
|
|
|
- A similar log should be emitted by the sender:
|
|
```
|
|
2015-01-16 11:49:25,181 DEBUG Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz amodem-cli:174
|
|
2015-01-16 11:49:27,028 INFO Sending 2.150 seconds of training audio send.py:63
|
|
2015-01-16 11:49:27,029 INFO Starting modulation send.py:68
|
|
2015-01-16 11:49:28,016 DEBUG Sent 6.000 kB send.py:50
|
|
2015-01-16 11:49:28,776 INFO Sent 10.000 kB @ 1.701 seconds send.py:73
|
|
|
|
```
|
|
|
|
- A similar log should be emitted by the receiver:
|
|
```
|
|
2015-01-16 11:49:24,369 DEBUG Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz amodem-cli:174
|
|
2015-01-16 11:49:24,382 DEBUG Skipping 0.100 seconds recv.py:214
|
|
2015-01-16 11:49:24,535 INFO Waiting for carrier tone: 3.0 kHz recv.py:221
|
|
2015-01-16 11:49:26,741 INFO Carrier detected at ~1761.0 ms @ 3.0 kHz: coherence=99.944%, amplitude=0.499 detect.py:64
|
|
2015-01-16 11:49:26,741 DEBUG Buffered 1000 ms of audio detect.py:66
|
|
2015-01-16 11:49:26,912 DEBUG Carrier starts at 1761.000 ms detect.py:76
|
|
2015-01-16 11:49:26,917 DEBUG Carrier symbols amplitude : 0.499 detect.py:101
|
|
2015-01-16 11:49:26,917 DEBUG Current phase on carrier: -0.466 detect.py:112
|
|
2015-01-16 11:49:26,917 DEBUG Frequency error: -0.01 ppm detect.py:113
|
|
2015-01-16 11:49:26,917 DEBUG Frequency correction: 0.005 ppm recv.py:225
|
|
2015-01-16 11:49:26,917 DEBUG Gain correction: 2.004 recv.py:228
|
|
2015-01-16 11:49:27,099 DEBUG Prefix OK recv.py:48
|
|
2015-01-16 11:49:27,925 DEBUG 3.0 kHz: SNR = 40.58 dB recv.py:92
|
|
2015-01-16 11:49:27,925 DEBUG 4.0 kHz: SNR = 41.98 dB recv.py:92
|
|
2015-01-16 11:49:27,925 DEBUG 5.0 kHz: SNR = 42.81 dB recv.py:92
|
|
2015-01-16 11:49:27,925 DEBUG 6.0 kHz: SNR = 43.71 dB recv.py:92
|
|
2015-01-16 11:49:27,926 DEBUG 7.0 kHz: SNR = 43.43 dB recv.py:92
|
|
2015-01-16 11:49:27,926 DEBUG 8.0 kHz: SNR = 42.96 dB recv.py:92
|
|
2015-01-16 11:49:27,926 DEBUG 9.0 kHz: SNR = 42.66 dB recv.py:92
|
|
2015-01-16 11:49:27,926 DEBUG 10.0 kHz: SNR = 42.22 dB recv.py:92
|
|
2015-01-16 11:49:27,928 INFO Starting demodulation recv.py:119
|
|
2015-01-16 11:49:28,008 DEBUG Got 0.600 kB, realtime: 80.73%, drift: -0.00 ppm recv.py:140
|
|
2015-01-16 11:49:28,081 DEBUG Got 1.200 kB, realtime: 76.60%, drift: -0.00 ppm recv.py:140
|
|
2015-01-16 11:49:28,153 DEBUG Got 1.800 kB, realtime: 75.17%, drift: -0.00 ppm recv.py:140
|
|
2015-01-16 11:49:28,224 DEBUG Got 2.400 kB, realtime: 74.02%, drift: -0.00 ppm recv.py:140
|
|
2015-01-16 11:49:28,306 DEBUG Got 3.000 kB, realtime: 75.72%, drift: -0.00 ppm recv.py:140
|
|
2015-01-16 11:49:28,382 DEBUG Got 3.600 kB, realtime: 75.71%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,458 DEBUG Got 4.200 kB, realtime: 75.72%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,528 DEBUG Got 4.800 kB, realtime: 75.10%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,609 DEBUG Got 5.400 kB, realtime: 75.76%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,686 DEBUG Got 6.000 kB, realtime: 75.80%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,757 DEBUG Got 6.600 kB, realtime: 75.36%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,828 DEBUG Got 7.200 kB, realtime: 75.03%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,909 DEBUG Got 7.800 kB, realtime: 75.50%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:28,980 DEBUG Got 8.400 kB, realtime: 75.15%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:29,051 DEBUG Got 9.000 kB, realtime: 74.88%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:29,261 DEBUG Got 9.600 kB, realtime: 83.31%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:29,342 DEBUG Got 10.200 kB, realtime: 83.23%, drift: -0.01 ppm recv.py:140
|
|
2015-01-16 11:49:29,343 DEBUG EOF frame detected framing.py:57
|
|
2015-01-16 11:49:29,343 DEBUG Demodulated 10.205 kB @ 1.415 seconds (83.2% realtime) recv.py:165
|
|
2015-01-16 11:49:29,343 INFO Received 10.000 kB @ 1.415 seconds = 7.066 kB/s recv.py:169
|
|
```
|
|
|
|
- After the receiver has finished, verify the received file's hash:
|
|
```
|
|
~/receiver $ sha256sum data.rx
|
|
008df57d4f3ed6e7a25d25afd57d04fc73140e8df604685bd34fcab58f5ddc01 data.rx
|
|
```
|
|
|
|
You can see a video of the data transfer process [here](http://www.youtube.com/watch?v=GZQUtHB8so4).
|
|
|
|
# Visualization
|
|
Make sure that `matplotlib` package is installed, and run (at the receiver side):
|
|
|
|
```
|
|
~/receiver $ amodem-cli recv --plot -o data.rx
|
|
```
|
|
|
|
|
|
# Donations
|
|
|
|
Want to donate? Feel free.
|
|
Send to [1C1snTrkHAHM5XnnfuAtiTBaA11HBxjJyv](https://blockchain.info/address/1C1snTrkHAHM5XnnfuAtiTBaA11HBxjJyv).
|
|
|
|
Thanks :)
|