{"id":13537657,"url":"https://github.com/romanz/amodem","last_synced_at":"2025-05-14T09:06:55.525Z","repository":{"id":19265688,"uuid":"22501844","full_name":"romanz/amodem","owner":"romanz","description":"Audio MODEM Communication Library in Python","archived":false,"fork":false,"pushed_at":"2024-12-24T09:03:21.000Z","size":2303,"stargazers_count":988,"open_issues_count":24,"forks_count":124,"subscribers_count":48,"default_branch":"master","last_synced_at":"2025-04-11T22:19:50.093Z","etag":null,"topics":["airgap","audio","modem","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/romanz.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-01T08:41:48.000Z","updated_at":"2025-04-11T05:56:00.000Z","dependencies_parsed_at":"2023-02-11T14:16:02.158Z","dependency_job_id":"8adea1a2-2f60-4460-a491-0ab5035ed5fb","html_url":"https://github.com/romanz/amodem","commit_stats":{"total_commits":766,"total_committers":8,"mean_commits":95.75,"dds":"0.052219321148825104","last_synced_commit":"ed491925b2ae926a631724fd45f4a3697e33c034"},"previous_names":[],"tags_count":77,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanz%2Famodem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanz%2Famodem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanz%2Famodem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanz%2Famodem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romanz","download_url":"https://codeload.github.com/romanz/amodem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254110374,"owners_count":22016391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["airgap","audio","modem","python"],"created_at":"2024-08-01T09:01:01.726Z","updated_at":"2025-05-14T09:06:55.415Z","avatar_url":"https://github.com/romanz.png","language":"Python","readme":"Audio Modem Communication Library\n=================================\n\n.. image:: https://img.shields.io/pypi/pyversions/amodem.svg\n    :target: https://pypi.python.org/pypi/amodem/\n    :alt: Python Versions\n.. image:: https://img.shields.io/pypi/l/amodem.svg\n    :target: https://pypi.python.org/pypi/amodem/\n    :alt: License\n.. image:: https://img.shields.io/pypi/v/amodem.svg\n    :target: https://pypi.python.org/pypi/amodem/\n    :alt: Package Version\n.. image:: https://img.shields.io/pypi/status/amodem.svg\n    :target: https://pypi.python.org/pypi/amodem/\n    :alt: Development Status\n\n\nDescription\n-----------\n\nThis program can transmit a file between 2 computers, using a simple headset,\nallowing true air-gapped communication (via a speaker and a microphone),\nor an audio cable (for higher transmission speed).\n\nThe sender modulates the input data into an audio signal,\nwhich is played to the sound card.\n\nThe receiver records the audio, and demodulates it back to the original data.\n\nThe process requires a single manual calibration step: the transmitter has to\nfind the optimal output volume for its sound card, which will not saturate the\nreceiving microphone and provide good enough Signal-to-Noise ratio\nfor the demodulation to succeed.\n\nHackerNews discussion: https://news.ycombinator.com/item?id=17333257\n\nTechnical Details\n-----------------\n\nThe modem is using OFDM over an audio cable with the following parameters:\n\n- Sampling rate: 8/16/32 kHz\n- Baud rate: 1 kHz\n- Symbol modulation: BPSK, 4-PSK, 16-QAM, 64-QAM, 256-QAM\n- Carriers: 2-11 kHz (up to ten carriers)\n\nThis way, modem may achieve 80kbps bitrate = 10 kB/s (for best SNR).\n\nA simple CRC-32 checksum is used for data integrity verification\non each 250 byte data frame.\n\n\nInstallation\n------------\n\nMake sure that all the required packages are installed (on Debian)::\n\n    $ sudo apt-get install python-numpy python-pip portaudio19-dev git\n\nGet the latest released version from PyPI::\n\n    $ pip install --user amodem\n\nOr, try the latest (unstable) development version from GitHub::\n\n    $ git clone https://github.com/romanz/amodem.git\n    $ cd amodem\n    $ pip install --user -e .\n\nFor graphs and visualization (optional), install `matplotlib` Python package.\n\nFor validation, run::\n\n    $ export BITRATE=48  # explicitly select high MODEM bit rate (assuming good SNR).\n    $ amodem -h\n    usage: amodem [-h] {send,recv} ...\n\n    Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz\n\n    positional arguments:\n      {send,recv}\n        send         modulate binary data into audio signal.\n        recv         demodulate audio signal into binary data.\n\n    optional arguments:\n      -h, --help     show this help message and exit\n\nOn, Windows you may download the `portaudio` library from `MinGW \u003chttps://packages.msys2.org/base/mingw-w64-portaudio\u003e`_.\nThen, you should specify the DLL using the following command-line flag::\n\n    -l AUDIO_LIBRARY, --audio-library AUDIO_LIBRARY\n                        File name of PortAudio shared library.\n\n\nCalibration\n-----------\n\nConnect the audio cable between the sender and the receiver, and run the\nfollowing scripts:\n\nOn the sender's side::\n\n    ~/sender $ export BITRATE=48  # explicitly select high MODEM bit rate (assuming good SNR).\n    ~/sender $ amodem send --calibrate\n\nOn the receiver's side::\n\n    ~/receiver $ export BITRATE=48  # explicitly select high MODEM bit rate (assuming good SNR).\n    ~/receiver $ amodem recv --calibrate\n\nIf BITRATE is not set, the MODEM will use 1 kbps settings (single frequency with BPSK modulation).\n\nChange the sender computer's output audio level, until\nall frequencies are received well::\n\n  3000 Hz: good signal\n  4000 Hz: good signal\n  5000 Hz: good signal\n  6000 Hz: good signal\n  7000 Hz: good signal\n  8000 Hz: good signal\n  9000 Hz: good signal\n 10000 Hz: good signal\n\n\nIf the signal is \"too weak\", increase the sender's output audio level.\n\nIf the signal is \"too strong\", decrease the sender's output audio level.\n\nIf the signal is \"too noisy\", it may be that the noise level is too high\nor that the analog signal is being distorted.\nPlease run the following command during the calibration session,\nand send me the resulting ``audio.raw`` file for debugging::\n\n    ~/receiver $ arecord --format=S16_LE --channels=1 --rate=32000 audio.raw\n\nYou can see a screencast of the `calibration process \u003chttps://asciinema.org/a/25065?autoplay=1\u003e`_.\n\nUsage\n-----\n\nPrepare the sender (generate a random binary data file to be sent)::\n\n    ~/sender $ dd if=/dev/urandom of=data.tx bs=60KB count=1 status=none\n    ~/sender $ sha256sum data.tx\n    008df57d4f3ed6e7a25d25afd57d04fc73140e8df604685bd34fcab58f5ddc01  data.tx\n\nStart the receiver (will wait for the sender to start)::\n\n  ~/receiver $ amodem recv -vv -o data.rx\n\nStart the sender (will modulate the data and start the transmission)::\n\n  ~/sender $ amodem send -vv -i data.tx\n\nA similar log should be emitted by the sender::\n\n    2015-02-06 18:12:46,222 DEBUG      Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz\n    2015-02-06 18:12:46,222 INFO       PortAudio V19-devel (built Feb 25 2014 21:09:53) loaded\n    2015-02-06 18:12:48,297 INFO       Sending 2.150 seconds of training audio\n    2015-02-06 18:12:48,297 INFO       Starting modulation\n    2015-02-06 18:12:49,303 DEBUG      Sent      6.000 kB\n    2015-02-06 18:12:50,296 DEBUG      Sent     12.000 kB\n    2015-02-06 18:12:51,312 DEBUG      Sent     18.000 kB\n    2015-02-06 18:12:52,290 DEBUG      Sent     24.000 kB\n    2015-02-06 18:12:53,299 DEBUG      Sent     30.000 kB\n    2015-02-06 18:12:54,299 DEBUG      Sent     36.000 kB\n    2015-02-06 18:12:55,306 DEBUG      Sent     42.000 kB\n    2015-02-06 18:12:56,296 DEBUG      Sent     48.000 kB\n    2015-02-06 18:12:57,311 DEBUG      Sent     54.000 kB\n    2015-02-06 18:12:58,293 DEBUG      Sent     60.000 kB\n    2015-02-06 18:12:58,514 INFO       Sent 60.000 kB @ 10.201 seconds\n    2015-02-06 18:12:59,506 DEBUG      Closing input and output\n\nA similar log should be emitted by the receiver::\n\n    2015-02-06 18:12:44,848 DEBUG      Audio OFDM MODEM: 48.0 kb/s (64-QAM x 8 carriers) Fs=32.0 kHz\n    2015-02-06 18:12:44,849 INFO       PortAudio V19-devel (built Feb 25 2014 21:09:53) loaded\n    2015-02-06 18:12:44,929 DEBUG      AsyncReader thread started\n    2015-02-06 18:12:44,930 DEBUG      Skipping 0.100 seconds\n    2015-02-06 18:12:45,141 INFO       Waiting for carrier tone: 3.0 kHz\n    2015-02-06 18:12:47,846 INFO       Carrier detected at ~2265.0 ms @ 3.0 kHz\n    2015-02-06 18:12:47,846 DEBUG      Buffered 1000 ms of audio\n    2015-02-06 18:12:48,025 DEBUG      Carrier starts at 2264.000 ms\n    2015-02-06 18:12:48,029 DEBUG      Carrier symbols amplitude : 0.573\n    2015-02-06 18:12:48,030 DEBUG      Current phase on carrier: 0.061\n    2015-02-06 18:12:48,030 DEBUG      Frequency error: -0.009 ppm\n    2015-02-06 18:12:48,030 DEBUG      Frequency correction: 0.009 ppm\n    2015-02-06 18:12:48,030 DEBUG      Gain correction: 1.746\n    2015-02-06 18:12:48,198 DEBUG      Prefix OK\n    2015-02-06 18:12:48,866 DEBUG        3.0 kHz: SNR = 34.82 dB\n    2015-02-06 18:12:48,866 DEBUG        4.0 kHz: SNR = 36.39 dB\n    2015-02-06 18:12:48,867 DEBUG        5.0 kHz: SNR = 37.88 dB\n    2015-02-06 18:12:48,867 DEBUG        6.0 kHz: SNR = 38.58 dB\n    2015-02-06 18:12:48,867 DEBUG        7.0 kHz: SNR = 38.86 dB\n    2015-02-06 18:12:48,867 DEBUG        8.0 kHz: SNR = 38.63 dB\n    2015-02-06 18:12:48,867 DEBUG        9.0 kHz: SNR = 38.07 dB\n    2015-02-06 18:12:48,868 DEBUG       10.0 kHz: SNR = 37.22 dB\n    2015-02-06 18:12:48,869 INFO       Starting demodulation\n    2015-02-06 18:12:49,689 DEBUG      Got       6.000 kB, SNR: 41.19 dB, drift: -0.01 ppm\n    2015-02-06 18:12:50,659 DEBUG      Got      12.000 kB, SNR: 41.05 dB, drift: -0.00 ppm\n    2015-02-06 18:12:51,639 DEBUG      Got      18.000 kB, SNR: 40.96 dB, drift: -0.00 ppm\n    2015-02-06 18:12:52,610 DEBUG      Got      24.000 kB, SNR: 41.47 dB, drift: -0.01 ppm\n    2015-02-06 18:12:53,610 DEBUG      Got      30.000 kB, SNR: 41.06 dB, drift: -0.00 ppm\n    2015-02-06 18:12:54,589 DEBUG      Got      36.000 kB, SNR: 41.37 dB, drift: -0.00 ppm\n    2015-02-06 18:12:55,679 DEBUG      Got      42.000 kB, SNR: 41.13 dB, drift: -0.00 ppm\n    2015-02-06 18:12:56,650 DEBUG      Got      48.000 kB, SNR: 41.31 dB, drift: -0.00 ppm\n    2015-02-06 18:12:57,631 DEBUG      Got      54.000 kB, SNR: 41.23 dB, drift: +0.00 ppm\n    2015-02-06 18:12:58,605 DEBUG      Got      60.000 kB, SNR: 41.31 dB, drift: +0.00 ppm\n    2015-02-06 18:12:58,857 DEBUG      EOF frame detected\n    2015-02-06 18:12:58,857 DEBUG      Demodulated 61.205 kB @ 9.988 seconds (97.9% realtime)\n    2015-02-06 18:12:58,858 INFO       Received 60.000 kB @ 9.988 seconds = 6.007 kB/s\n    2015-02-06 18:12:58,876 DEBUG      Closing input and output\n    2015-02-06 18:12:58,951 DEBUG      AsyncReader thread stopped (read 896000 bytes)\n\nAfter the receiver has finished, verify the received file's hash::\n\n  ~/receiver $ sha256sum data.rx\n  008df57d4f3ed6e7a25d25afd57d04fc73140e8df604685bd34fcab58f5ddc01  data.rx\n\nYou can see a screencast of the `data transfer process \u003chttps://asciinema.org/a/25066?autoplay=1\u003e`_.\n\nI/O redirection\n---------------\nThe audio can be written/read to an intermediate PCM file (instead of the speaker/microphone) using::\n\n    $ echo 123 | amodem send -o /tmp/file.pcm\n    Sending 0.800 seconds of training audio\n    Starting modulation\n    Sent 0.004 kB @ 0.113 seconds\n\n    $ amodem recv -i /tmp/file.pcm\n    Waiting for carrier tone: 2.0 kHz\n    Carrier detected at ~150.0 ms @ 2.0 kHz\n    Carrier coherence: 100.000%\n    Carrier symbols amplitude : 1.000\n    Frequency error: 0.000 ppm\n    Starting demodulation\n    123\n    Received 0.004 kB @ 0.011 seconds = 0.376 kB/s\n\n\nVisualization\n-------------\nMake sure that ``matplotlib`` package is installed, and run (at the receiver side)::\n\n    ~/receiver $ amodem recv --plot -o data.rx\n\n","funding_links":[],"categories":["Python","\u003ca id=\"9eee96404f868f372a6cbc6769ccb7f8\"\u003e\u003c/a\u003e新添加的","\u003ca id=\"9eee96404f868f372a6cbc6769ccb7f8\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"31185b925d5152c7469b963809ceb22d\"\u003e\u003c/a\u003e新添加的"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromanz%2Famodem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromanz%2Famodem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromanz%2Famodem/lists"}