mirror of
https://github.com/romanz/amodem.git
synced 2026-05-03 08:27:26 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee5c543737 | ||
|
|
1311c58005 | ||
|
|
9c6ef2884e | ||
|
|
21fe42e68d | ||
|
|
9352088389 | ||
|
|
db47cda390 | ||
|
|
4cd3def507 | ||
|
|
9192a8ff67 | ||
|
|
3b88a23dfb | ||
|
|
10c06f7646 | ||
|
|
df9cbfdf13 |
@@ -1,7 +1,7 @@
|
||||
[bumpversion]
|
||||
commit = True
|
||||
tag = True
|
||||
current_version = 1.15.0
|
||||
current_version = 1.15.2
|
||||
|
||||
[bumpversion:file:setup.py]
|
||||
|
||||
|
||||
37
.github/workflows/build.yml
vendored
Normal file
37
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.5, 3.6, 3.7, 3.8]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pytest mock pycodestyle coverage pylint six
|
||||
pip install -e .
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
pycodestyle amodem/ scripts/
|
||||
pylint --extension-pkg-whitelist=numpy --reports=no amodem --rcfile .pylintrc
|
||||
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
coverage run --source amodem/ --omit="*/__main__.py" -m py.test -v
|
||||
coverage report
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,3 +26,4 @@ htmlcov
|
||||
/dist
|
||||
/deb_dist
|
||||
*.html
|
||||
.pytest_cache/
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[MESSAGES CONTROL]
|
||||
disable=invalid-name, missing-docstring, too-many-instance-attributes, too-few-public-methods, logging-format-interpolation
|
||||
disable=invalid-name, missing-docstring, too-many-instance-attributes, too-few-public-methods, logging-format-interpolation, consider-using-with
|
||||
|
||||
20
.travis.yml
20
.travis.yml
@@ -1,20 +0,0 @@
|
||||
sudo: false
|
||||
language: python
|
||||
python:
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "3.7-dev"
|
||||
|
||||
install:
|
||||
- pip install .
|
||||
- pip install pytest>=2.7.3 --upgrade
|
||||
- pip install coveralls pycodestyle mock
|
||||
|
||||
script:
|
||||
- pycodestyle amodem/ scripts/
|
||||
- echo "Hello World!" | amodem send -vv -l- -o- | amodem recv -vv -l- -i-
|
||||
- coverage run --source=amodem --omit="*/__main__.py" -m py.test -vvs
|
||||
|
||||
after_success:
|
||||
- coverage report
|
||||
- coveralls
|
||||
19
README.rst
19
README.rst
@@ -1,16 +1,6 @@
|
||||
Audio Modem Communication Library
|
||||
=================================
|
||||
|
||||
.. image:: https://travis-ci.org/romanz/amodem.svg?branch=master
|
||||
:target: https://travis-ci.org/romanz/amodem
|
||||
:alt: Build Status
|
||||
.. image:: https://coveralls.io/repos/romanz/amodem/badge.svg?branch=master
|
||||
:target: https://coveralls.io/r/romanz/amodem?branch=master
|
||||
:alt: Code Coverage
|
||||
.. image:: https://landscape.io/github/romanz/amodem/master/landscape.svg?style=flat
|
||||
:target: https://landscape.io/github/romanz/amodem/master
|
||||
:alt: Code Health
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/amodem.svg
|
||||
:target: https://pypi.python.org/pypi/amodem/
|
||||
:alt: Python Versions
|
||||
@@ -24,9 +14,6 @@ Audio Modem Communication Library
|
||||
:target: https://pypi.python.org/pypi/amodem/
|
||||
:alt: Development Status
|
||||
|
||||
.. image:: https://badge.waffle.io/romanz/amodem.svg?label=ready&title=ready
|
||||
:target: https://waffle.io/romanz/amodem
|
||||
:alt: 'Ready'
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -98,6 +85,12 @@ For validation, run::
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
On, Windows you may download the `portaudio` library from `MinGW <https://packages.msys2.org/base/mingw-w64-portaudio>`_.
|
||||
Then, you should specify the DLL using the following command-line flag::
|
||||
|
||||
-l AUDIO_LIBRARY, --audio-library AUDIO_LIBRARY
|
||||
File name of PortAudio shared library.
|
||||
|
||||
|
||||
Calibration
|
||||
-----------
|
||||
|
||||
@@ -124,10 +124,13 @@ def create_parser(description, interface_factory):
|
||||
sender.add_argument(
|
||||
'-g', '--gain', type=float, default=1.0,
|
||||
help='Modulator gain (defaults to 1)')
|
||||
sender.add_argument(
|
||||
'--silence', type=float, default=0.0,
|
||||
help='Extra silence before sending the data (in seconds)')
|
||||
sender.set_defaults(
|
||||
main=lambda config, args: main.send(
|
||||
config, src=wrap(Compressor, args.src, args.zlib), dst=args.dst,
|
||||
gain=args.gain
|
||||
gain=args.gain, extra_silence=args.silence
|
||||
),
|
||||
calib=lambda config, args: calib.send(
|
||||
config=config, dst=args.dst,
|
||||
@@ -233,11 +236,11 @@ def _main():
|
||||
|
||||
args.pylab = None
|
||||
if getattr(args, 'plot', False):
|
||||
import pylab # pylint: disable=import-error
|
||||
import pylab # pylint: disable=import-error,import-outside-toplevel
|
||||
args.pylab = pylab
|
||||
|
||||
if args.audio_library == 'ALSA':
|
||||
from . import alsa
|
||||
from . import alsa # pylint: disable=import-outside-toplevel
|
||||
interface = alsa.Interface(config)
|
||||
elif args.audio_library == '-':
|
||||
interface = _Dummy() # manually disable PortAudio
|
||||
|
||||
@@ -29,7 +29,7 @@ class AsyncReader:
|
||||
queue.put(buf)
|
||||
total += len(buf)
|
||||
log.debug('AsyncReader thread stopped (read %d bytes)', total)
|
||||
except BaseException:
|
||||
except BaseException: # pylint: disable=broad-except
|
||||
log.exception('AsyncReader thread failed')
|
||||
queue.put(None)
|
||||
|
||||
|
||||
@@ -107,8 +107,7 @@ def volume_calibration(result_iterator, volume_ctl):
|
||||
def iter_window(iterable, size):
|
||||
# pylint: disable=stop-iteration-return
|
||||
block = []
|
||||
while True:
|
||||
item = next(iterable)
|
||||
for item in iterable:
|
||||
block.append(item)
|
||||
block = block[-size:]
|
||||
if len(block) == size:
|
||||
|
||||
@@ -73,14 +73,6 @@ def take(iterable, n):
|
||||
return np.array(list(itertools.islice(iterable, n)))
|
||||
|
||||
|
||||
def izip(iterables):
|
||||
""" "Python 3" zip re-implementation for Python 2. """
|
||||
# pylint: disable=stop-iteration-return
|
||||
iterables = [iter(iterable) for iterable in iterables]
|
||||
while True:
|
||||
yield tuple([next(iterable) for iterable in iterables])
|
||||
|
||||
|
||||
class Dummy:
|
||||
""" Dummy placeholder object for testing and mocking. """
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ class Configuration:
|
||||
latency = 0.1
|
||||
|
||||
# sender config
|
||||
silence_start = 0.25
|
||||
silence_stop = 0.25
|
||||
silence_start = 0.5
|
||||
silence_stop = 0.5
|
||||
|
||||
# receiver config
|
||||
skip_start = 0.1
|
||||
|
||||
@@ -29,8 +29,7 @@ class Checksum:
|
||||
if received != expected:
|
||||
log.warning('Invalid checksum: %08x != %08x', received, expected)
|
||||
raise ValueError('Invalid checksum')
|
||||
else:
|
||||
log.debug('Good checksum: %08x', received)
|
||||
log.debug('Good checksum: %08x', received)
|
||||
return payload
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ from . import framing, common, stream, detect, sampling
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def send(config, src, dst, gain=1.0):
|
||||
def send(config, src, dst, gain=1.0, extra_silence=0.0):
|
||||
sender = _send.Sender(dst, config=config, gain=gain)
|
||||
Fs = config.Fs
|
||||
|
||||
# pre-padding audio with silence (priming the audio sending queue)
|
||||
sender.write(np.zeros(int(Fs * config.silence_start)))
|
||||
sender.write(np.zeros(int(Fs * (config.silence_start + extra_silence))))
|
||||
|
||||
sender.start()
|
||||
|
||||
@@ -63,7 +63,7 @@ def recv(config, src, dst, dump_audio=None, pylab=None):
|
||||
freq=freq)
|
||||
receiver.run(sampler, gain=1.0/amplitude, output=dst)
|
||||
return True
|
||||
except BaseException:
|
||||
except BaseException: # pylint: disable=broad-except
|
||||
log.exception('Decoding failed')
|
||||
return False
|
||||
finally:
|
||||
|
||||
@@ -111,7 +111,7 @@ class Receiver:
|
||||
bits = self.modem.decode(S, freq_handler) # list of bit tuples
|
||||
streams.append(bits) # bit stream per frequency
|
||||
|
||||
return common.izip(streams), symbol_list
|
||||
return zip(*streams), symbol_list
|
||||
|
||||
def _demodulate(self, sampler, symbols):
|
||||
symbol_list = []
|
||||
|
||||
@@ -48,12 +48,6 @@ def test_dumps_loads():
|
||||
assert all(x == y)
|
||||
|
||||
|
||||
def test_izip():
|
||||
x = range(10)
|
||||
y = range(-10, 0)
|
||||
assert list(common.izip([x, y])) == list(zip(x, y))
|
||||
|
||||
|
||||
def test_configs():
|
||||
default = config.Configuration()
|
||||
fastest = config.fastest()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from amodem import stream
|
||||
import subprocess as sp
|
||||
import sys
|
||||
|
||||
script = br"""
|
||||
import sys
|
||||
@@ -14,7 +15,7 @@ while True:
|
||||
|
||||
|
||||
def test_read():
|
||||
p = sp.Popen(args=['python', '-'], stdin=sp.PIPE, stdout=sp.PIPE)
|
||||
p = sp.Popen(args=[sys.executable, '-'], stdin=sp.PIPE, stdout=sp.PIPE)
|
||||
p.stdin.write(script)
|
||||
p.stdin.close()
|
||||
f = stream.Reader(p.stdout)
|
||||
|
||||
@@ -49,13 +49,18 @@ def run(size, chan=None, df=0, success=True, cfg=None):
|
||||
assert rx_data == tx_data
|
||||
|
||||
|
||||
@pytest.fixture(params=[0, 1, 3, 10, 42, 123])
|
||||
@pytest.fixture(params=[0, 1, 3, 10, 16, 17, 42, 123])
|
||||
def small_size(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_small(small_size):
|
||||
run(small_size, chan=lambda x: x)
|
||||
@pytest.fixture(params=list(config.bitrates.values()))
|
||||
def all_configs(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_small(small_size, all_configs):
|
||||
run(small_size, chan=lambda x: x, cfg=all_configs)
|
||||
|
||||
|
||||
def test_flip():
|
||||
|
||||
5
setup.py
5
setup.py
@@ -15,7 +15,7 @@ class PyTest(TestCommand):
|
||||
|
||||
setup(
|
||||
name='amodem',
|
||||
version='1.15.0',
|
||||
version='1.15.2',
|
||||
description='Audio Modem Communication Library',
|
||||
author='Roman Zeyde',
|
||||
author_email='dev@romanzey.de',
|
||||
@@ -32,9 +32,10 @@ setup(
|
||||
'Intended Audience :: Information Technology',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: POSIX',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
'Topic :: System :: Networking',
|
||||
'Topic :: Communications',
|
||||
|
||||
Reference in New Issue
Block a user