update to v0.1.4

This commit is contained in:
Georgi Gerganov
2021-01-23 14:36:11 +02:00
parent f245b6e930
commit 3f690868a4
6 changed files with 225 additions and 5 deletions

View File

@@ -1,5 +1,8 @@
cmake_minimum_required (VERSION 3.0)
project (ggwave)
project(ggwave VERSION 0.1.4)
configure_file(${CMAKE_SOURCE_DIR}/README.md.tmpl ${CMAKE_SOURCE_DIR}/README.md @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/bindings/python/setup.py.tmpl ${CMAKE_SOURCE_DIR}/bindings/python/setup.py @ONLY)
set(CMAKE_EXPORT_COMPILE_COMMANDS "on")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

View File

@@ -2,7 +2,7 @@
[![Actions Status](https://github.com/ggerganov/ggwave/workflows/CI/badge.svg)](https://github.com/ggerganov/ggwave/actions)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![ggwave v0.0.1 badge][changelog-badge]][changelog]
[![ggwave badge][changelog-badge]][changelog]
![pypi](https://img.shields.io/pypi/v/ggwave.svg)
Tiny data-over-sound library.
@@ -165,6 +165,5 @@ sudo snap connect waver:audio-record :audio-record
```
[changelog]: ./CHANGELOG.md
[changelog-badge]: https://img.shields.io/badge/changelog-ggwave%20v0.1-dummy
[changelog-badge]: https://img.shields.io/badge/changelog-ggwave%20v0.1.4-dummy
[license]: ./LICENSE
[version-badge]: https://img.shields.io/badge/version-0.0.1-blue.svg

169
README.md.tmpl Normal file
View File

@@ -0,0 +1,169 @@
# ggwave
[![Actions Status](https://github.com/ggerganov/ggwave/workflows/CI/badge.svg)](https://github.com/ggerganov/ggwave/actions)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![ggwave badge][changelog-badge]][changelog]
![pypi](https://img.shields.io/pypi/v/ggwave.svg)
Tiny data-over-sound library.
Click on the images below to hear what it sounds like:
<a href="https://youtu.be/Zcgf77T71QM"><img width="100%" src="media/waver-preview1.gif"></img></a>
<a href="https://youtu.be/S2YdGefZiy4"><img width="100%" src="media/ggwave0.gif"></img></a>
<a href="https://youtu.be/KWlcgZHJhGQ"><img width="100%" src="media/waver-0-fast.gif"></img></a>
## Details
This library allows you to communicate small amounts of data between air-gapped devices using sound. It implements a simple FSK-based transmission protocol that can be easily integrated in various projects. The bandwidth rate is between 8-16 bytes/sec depending on the protocol parameters. Error correction codes (ECC) are used to improve demodulation robustness.
This library is used only to generate and analyze the RAW waveforms that are played and captured from your audio devices (speakers, microphones, etc.). You are free to use any audio backend (e.g. PulseAudio, ALSA, etc.) as long as you provide callbacks for queuing and dequeuing audio samples.
Possible applications:
- Serverless, one-to-many broadcast
- Device pairing
- Authorization
- Internet of Things
- Audio QR codes
## Try it out
You can easily test the library using the free [waver](https://github.com/ggerganov/ggwave/tree/master/examples/waver) application which is available on the following platforms:
<a href="https://apps.apple.com/us/app/waver-data-over-sound/id1543607865?itsct=apps_box&amp;itscg=30200&ign-itsct=apps_box#?platform=iphone" style="display: inline-block; overflow: hidden; border-radius: 13px; width: 250px; height: 83px;"><img height="60px" src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/white/en-US?size=250x83&amp;releaseDate=1607558400&h=8e5fafc57929918f684abc83ff8311ef" alt="Download on the App Store"></a>
<a href='https://play.google.com/store/apps/details?id=com.ggerganov.Waver&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' src='https://i.imgur.com/BKDCbKv.png' height="60px"/></a>
<a href="https://snapcraft.io/waver">
<img alt="Get it from the Snap Store" src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg" height="60px"/>
</a>
### Browser demos
- https://waver.ggerganov.com
- https://ggwave.ggerganov.com
### [HTTP service](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-to-file/README.md#http-service)
```bash
# audible example
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello world!' --output hello.wav
# ultrasound example
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello world!&p=4' --output hello.wav
```
## Technical details
Below is a short summary of the modulation and demodulation algorithm used in `ggwave` for encoding and decoding data into sound.
### Modulation (Tx)
The current approach uses a multi-frequency [Frequency-Shift Keying (FSK)](https://en.wikipedia.org/wiki/Frequency-shift_keying) modulation scheme. The data to be transmitted is first split into 4-bit chunks. At each moment of time, 3 bytes are transmitted using 6 tones - one tone for each 4-bit chunk. The 6 tones are emitted in a 4.5kHz range divided in 96 equally-spaced frequencies:
| Freq, [Hz] | Value, [bits] | Freq, [Hz] | Value, [bits] | ... | Freq, [Hz] | Value, [bits] |
| ------------ | --------------- | ------------ | --------------- | --- | ------------ | --------------- |
| `F0 + 00*dF` | Chunk 0: `0000` | `F0 + 16*dF` | Chunk 1: `0000` | ... | `F0 + 80*dF` | Chunk 5: `0000` |
| `F0 + 01*dF` | Chunk 0: `0001` | `F0 + 17*dF` | Chunk 1: `0001` | ... | `F0 + 81*dF` | Chunk 5: `0001` |
| `F0 + 02*dF` | Chunk 0: `0010` | `F0 + 18*dF` | Chunk 1: `0010` | ... | `F0 + 82*dF` | Chunk 5: `0010` |
| ... | ... | ... | ... | ... | ... | ... |
| `F0 + 14*dF` | Chunk 0: `1110` | `F0 + 30*dF` | Chunk 1: `1110` | ... | `F0 + 94*dF` | Chunk 5: `1110` |
| `F0 + 15*dF` | Chunk 0: `1111` | `F0 + 31*dF` | Chunk 1: `1111` | ... | `F0 + 95*dF` | Chunk 5: `1111` |
For all protocols: `dF = 46.875 Hz`. For non-ultrasonic protocols: `F0 = 1875.000 Hz`. For ultrasonic protocols: `F0 = 15000.000 Hz`.
The original data is encoded using [Reed-Solomon error codes](https://github.com/ggerganov/ggwave/blob/master/src/reed-solomon). The number of ECC bytes is determined based on the length of the original data. The encoded data is the one being transmitted.
### Demodulation (Rx)
Beginning and ending of the transmission are marked with special sound markers ([#13](https://github.com/ggerganov/ggwave/discussions/13)). The receiver listens for these markers and records the in-between sound data. The recorded data is then Fourier transformed to obtain a frequency spectrum. The detected frequencies are decoded back to binary data in the same way they were encoded.
Reed-Solomon decoding is finally performed to obtain the original data.
## Examples
The [examples](https://github.com/ggerganov/ggwave/blob/master/examples/) folder contains several sample applications of the library:
| Example | Description | Backend |
| ------- | ----------- | ------- |
| [ggwave-rx](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-rx) | Very basic receive-only program | SDL |
| [ggwave-cli](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-cli) | Command line tool for sending/receiving data through sound | SDL |
| [ggwave-wasm](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-wasm) | WebAssembly module for web applications | SDL |
| [ggwave-to-file](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-to-file) | Output a generated waveform to an uncompressed WAV file | - |
| [waver](https://github.com/ggerganov/ggwave/blob/master/examples/waver) | GUI application for sending/receiving data through sound | SDL |
| [ggwave-py](https://github.com/ggerganov/ggwave/blob/master/examples/ggwave-py) | Python examples | - |
Other projects using **ggwave** or one of its prototypes:
- [wave-gui](https://github.com/ggerganov/wave-gui) - a GUI for exploring different modulation protocols
- [wave-share](https://github.com/ggerganov/wave-share) - WebRTC file sharing with sound signaling
## Building
### Dependencies for SDL-based examples
[Ubuntu]
$ sudo apt install libsdl2-dev
[Mac OS with brew]
$ brew install sdl2
[MSYS2]
$ pacman -S git cmake make mingw-w64-x86_64-dlfcn mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2
### Linux, Mac, Windows (MSYS2)
```bash
# build
git clone https://github.com/ggerganov/ggwave --recursive
cd ggwave && mkdir build && cd build
cmake ..
make
# running
./bin/ggwave-cli
```
### Emscripten
```bash
git clone https://github.com/ggerganov/ggwave --recursive
cd ggwave
mkdir build && cd build
emcmake cmake ..
make
```
### Python
```bash
pip install ggwave
```
More info: https://pypi.org/project/ggwave/
## Installing the Waver application
[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/waver)
### Linux
```bash
sudo snap install waver
sudo snap connect waver:audio-record :audio-record
```
### Mac OS
```bash
brew install ggerganov/ggerganov/waver
```
[changelog]: ./CHANGELOG.md
[changelog-badge]: https://img.shields.io/badge/changelog-ggwave%20v@PROJECT_VERSION@-dummy
[license]: ./LICENSE

View File

@@ -3,3 +3,5 @@ README.rst
ggwave.bycython.cpp
ggwave.cpython-36m-x86_64-linux-gnu.so
ggwave/
ggwave.egg-info/
dist/

View File

@@ -30,7 +30,7 @@ setup(
name = "ggwave",
description = "Tiny data-over-sound library.",
long_description = long_description,
version = "0.1.3",
version = "0.1.4",
url = "https://github.com/ggerganov/ggwave",
author = "Georgi Gerganov",
author_email = "ggerganov@gmail.com",

View File

@@ -0,0 +1,47 @@
from setuptools import setup, Extension
from codecs import open
import os
cmdclass = {}
long_description = ""
# Build directly from cython source file(s) if user wants so (probably for some experiments).
# Otherwise, pre-generated c source file(s) are used.
# User has to set environment variable GGWAVE_USE_CYTHON.
# e.g.: GGWAVE_USE_CYTHON=1 python setup.py install
USE_CYTHON = os.getenv('GGWAVE_USE_CYTHON', False)
if USE_CYTHON:
from Cython.Build import build_ext
ggwave_module_src = "ggwave.pyx"
cmdclass['build_ext'] = build_ext
else:
ggwave_module_src = "ggwave.bycython.cpp"
# Load README.rst into long description.
# User can skip using README.rst as long description: GGWAVE_OMIT_README_RST=1 python setup.py install
OMIT_README_RST = os.getenv('GGWAVE_OMIT_README_RST', False)
if not OMIT_README_RST:
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read()
setup(
# Information
name = "ggwave",
description = "Tiny data-over-sound library.",
long_description = long_description,
version = "@PROJECT_VERSION@",
url = "https://github.com/ggerganov/ggwave",
author = "Georgi Gerganov",
author_email = "ggerganov@gmail.com",
license = "MIT",
keywords = "data-over-sound fsk ecc serverless pairing qrcode ultrasound",
# Build instructions
ext_modules = [Extension("ggwave",
[ggwave_module_src, "ggwave/src/ggwave.cpp"],
include_dirs=["ggwave/include", "ggwave/include/ggwave"],
depends=["ggwave/include/ggwave/ggwave.h"],
language="c++",
extra_compile_args=["-O3", "-std=c++11"])],
cmdclass = cmdclass
)