Compare commits

...

11 Commits

Author SHA1 Message Date
Roman Zeyde
ee5c543737 Bump version: 1.15.1 → 1.15.2 2021-06-19 19:38:26 +03:00
Roman Zeyde
1311c58005 Ignore 'consider-using-with' pylint warning 2021-06-19 14:31:38 +03:00
Roman Zeyde
9c6ef2884e Drop izip compatibility helper 2021-06-19 14:12:26 +03:00
Roman Zeyde
21fe42e68d Increase leading and trailing silence defaults
Leading silence should help ignore initial A/D artifacts.
Trailing silence fixes buffering issues (e.g. #49).
2021-06-19 14:07:01 +03:00
Roman Zeyde
9352088389 Bump version: 1.15.0 → 1.15.1 2020-07-03 14:56:12 +03:00
Roman Zeyde
db47cda390 Remove travis, coveralls, landscape & waffle badges 2020-07-03 14:55:12 +03:00
Roman Zeyde
4cd3def507 Fix lint errors and adapt to latest Python 2020-07-03 14:50:59 +03:00
Roman Zeyde
9192a8ff67 Switch to GitHub actions 2020-07-03 14:23:12 +03:00
Roman Zeyde
3b88a23dfb Document PortAudio DLL usage on Windows 2020-07-03 13:16:10 +03:00
Roman Zeyde
10c06f7646 Ignore .pytest_cache/ 2019-03-08 15:11:47 +02:00
Roman Zeyde
df9cbfdf13 Allow more silence before transmission 2019-03-08 15:10:02 +02:00
18 changed files with 74 additions and 69 deletions

View File

@@ -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
View 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
View File

@@ -26,3 +26,4 @@ htmlcov
/dist
/deb_dist
*.html
.pytest_cache/

View File

@@ -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

View File

@@ -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

View File

@@ -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
-----------

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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. """

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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 = []

View File

@@ -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()

View File

@@ -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)

View File

@@ -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():

View File

@@ -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',