From a748fdb5a1deab8371e26f42f84887a99d0cd92c Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Wed, 6 Aug 2014 18:22:15 +0300 Subject: [PATCH 01/11] port stream and send --- amodem/send.py | 9 +++++---- amodem/stream.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/amodem/send.py b/amodem/send.py index 6322224..3c9f255 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -18,8 +18,9 @@ modem = sigproc.MODEM(config) class Symbol(object): - t = np.arange(0, config.Nsym) * config.Ts - carrier = [np.exp(2j * np.pi * F * t) for F in modem.freqs] + def __init__(self): + t = np.arange(0, config.Nsym) * config.Ts + self.carrier = [np.exp(2j * np.pi * F * t) for F in modem.freqs] sym = Symbol() @@ -31,7 +32,7 @@ class Writer(object): def write(self, fd, sym, n=1): data = common.dumps(sym, n) - fd.write(data) + fd.write(str(data)) self.offset += len(data) if time.time() > self.last + 1: log.debug('%10.3f seconds of data audio', @@ -69,7 +70,7 @@ class Reader(object): self.size = size self.total = 0 - def next(self): + def __next__(self): block = self.fd.read(self.size) if block: self.total += len(block) diff --git a/amodem/stream.py b/amodem/stream.py index fc59b93..8b0c835 100644 --- a/amodem/stream.py +++ b/amodem/stream.py @@ -19,7 +19,7 @@ class Reader(object): def __iter__(self): return self - def next(self): + def __next__(self): block = bytearray() finish_time = time.time() + self.TIMEOUT while time.time() <= finish_time: From 61bea70bc971afec7649bf55b8bc1a479fa9b0de Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 13:13:21 +0300 Subject: [PATCH 02/11] Reader: fix iteration logic. --- amodem/send.py | 21 ++------------------- amodem/stream.py | 11 ++++++++++- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/amodem/send.py b/amodem/send.py index 3c9f255..b1b58d0 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -13,6 +13,7 @@ import wave import common import config import sigproc +import stream modem = sigproc.MODEM(config) @@ -64,24 +65,6 @@ def modulate(fd, bits): break -class Reader(object): - def __init__(self, fd, size): - self.fd = fd - self.size = size - self.total = 0 - - def __next__(self): - block = self.fd.read(self.size) - if block: - self.total += len(block) - return block - else: - raise StopIteration() - - def __iter__(self): - return self - - def main(args): import ecc log.info('Running MODEM @ {:.1f} kbps'.format(modem.modem_bps / 1e3)) @@ -96,7 +79,7 @@ def main(args): log.info('%.3f seconds of training audio', training_size / wave.bytes_per_second) - reader = Reader(args.input, 64 << 10) + reader = stream.Reader(args.input, 64 << 10) data = itertools.chain.from_iterable(reader) encoded = itertools.chain.from_iterable(ecc.encode(data)) modulate(args.output, bits=common.to_bits(encoded)) diff --git a/amodem/stream.py b/amodem/stream.py index 8b0c835..02a3bf6 100644 --- a/amodem/stream.py +++ b/amodem/stream.py @@ -12,21 +12,30 @@ class Reader(object): WAIT = 0.1 TIMEOUT = 2.0 - def __init__(self, fd): + def __init__(self, fd, bufsize=None, eof=False): self.fd = fd self.check = None + self.total = 0 + self.bufsize = bufsize if (bufsize is not None) else self.BUFSIZE + self.eof = eof def __iter__(self): return self def __next__(self): + return self.next() + + def next(self): block = bytearray() finish_time = time.time() + self.TIMEOUT while time.time() <= finish_time: left = self.BUFSIZE - len(block) data = self.fd.read(left) if data: + self.total += len(data) block.extend(data) + elif self.eof: # handle EOF condition by stopping iteration + raise StopIteration() if len(block) == self.BUFSIZE: values = common.loads(str(block)) From 89b37ae2851820f7a804c8bd8316f89e3ea28426 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 13:19:46 +0300 Subject: [PATCH 03/11] send: stream.Reader should use eof=True --- amodem/send.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amodem/send.py b/amodem/send.py index b1b58d0..58127ab 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -79,7 +79,7 @@ def main(args): log.info('%.3f seconds of training audio', training_size / wave.bytes_per_second) - reader = stream.Reader(args.input, 64 << 10) + reader = stream.Reader(args.input, 64 << 10, eof=True) data = itertools.chain.from_iterable(reader) encoded = itertools.chain.from_iterable(ecc.encode(data)) modulate(args.output, bits=common.to_bits(encoded)) From 99de92c7e82b56c817b37f1ae76e3f31e3638a92 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 14:14:08 +0300 Subject: [PATCH 04/11] fix stream bugs --- amodem/common.py | 2 +- amodem/ecc.py | 3 ++- amodem/recv.py | 7 ++++++- amodem/send.py | 8 +++++--- amodem/stream.py | 22 ++++++++++++---------- tests/test_stream.py | 2 +- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/amodem/common.py b/amodem/common.py index da9344c..97b58a6 100644 --- a/amodem/common.py +++ b/amodem/common.py @@ -41,7 +41,7 @@ def load(fileobj): def loads(data): - x = np.fromstring(data, dtype='int16') + x = np.fromstring(str(data), dtype='int16') x = x / scaling return x diff --git a/amodem/ecc.py b/amodem/ecc.py index 1da4f32..b80b1aa 100644 --- a/amodem/ecc.py +++ b/amodem/ecc.py @@ -17,7 +17,8 @@ def end_of_stream(size): def encode(data, nsym=DEFAULT_NSYM): chunk_size = BLOCK_SIZE - nsym - 1 - for _, chunk in common.iterate(data, chunk_size, bytearray, truncate=False): + for _, chunk in common.iterate(data=data, size=chunk_size, + func=bytearray, truncate=False): size = len(chunk) if size < chunk_size: padding = [0] * (chunk_size - size) diff --git a/amodem/recv.py b/amodem/recv.py index 08866fa..d1d95ad 100755 --- a/amodem/recv.py +++ b/amodem/recv.py @@ -238,11 +238,16 @@ def decode(bits_iterator): return ecc.decode(blocks()) +def iread(fd): + reader = stream.Reader(fd, data_type=common.loads) + return itertools.chain.from_iterable(reader) + + def main(args): log.info('Running MODEM @ {:.1f} kbps'.format(modem.modem_bps / 1e3)) - signal = stream.iread(args.input) + signal = iread(args.input) skipped = common.take(signal, args.skip) log.debug('Skipping first %.3f seconds', len(skipped) / float(modem.baud)) diff --git a/amodem/send.py b/amodem/send.py index 58127ab..cae52d2 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -79,7 +79,7 @@ def main(args): log.info('%.3f seconds of training audio', training_size / wave.bytes_per_second) - reader = stream.Reader(args.input, 64 << 10, eof=True) + reader = stream.Reader(args.input, bufsize=(64 << 10), eof=True) data = itertools.chain.from_iterable(reader) encoded = itertools.chain.from_iterable(ecc.encode(data)) modulate(args.output, bits=common.to_bits(encoded)) @@ -99,7 +99,9 @@ if __name__ == '__main__': p = argparse.ArgumentParser() p.add_argument('--silence-start', type=float, default=1.0) p.add_argument('--silence-stop', type=float, default=1.0) - p.add_argument('-i', '--input', type=argparse.FileType('r'), default=sys.stdin) - p.add_argument('-o', '--output', type=argparse.FileType('w'), default=sys.stdout) + p.add_argument('-i', '--input', type=argparse.FileType('r'), + default=sys.stdin) + p.add_argument('-o', '--output', type=argparse.FileType('w'), + default=sys.stdout) args = p.parse_args() main(args) diff --git a/amodem/stream.py b/amodem/stream.py index 02a3bf6..78ff5eb 100644 --- a/amodem/stream.py +++ b/amodem/stream.py @@ -1,7 +1,5 @@ import time -import itertools -import common import wave @@ -12,12 +10,13 @@ class Reader(object): WAIT = 0.1 TIMEOUT = 2.0 - def __init__(self, fd, bufsize=None, eof=False): + def __init__(self, fd, data_type=None, bufsize=None, eof=False): self.fd = fd self.check = None self.total = 0 self.bufsize = bufsize if (bufsize is not None) else self.BUFSIZE self.eof = eof + self.data_type = data_type if (data_type is not None) else lambda x: x def __iter__(self): return self @@ -27,6 +26,15 @@ class Reader(object): def next(self): block = bytearray() + if self.eof: + data = self.fd.read(self.BUFSIZE) + if data: + self.total += len(data) + block.extend(data) + return block + else: + raise StopIteration() + finish_time = time.time() + self.TIMEOUT while time.time() <= finish_time: left = self.BUFSIZE - len(block) @@ -34,11 +42,9 @@ class Reader(object): if data: self.total += len(data) block.extend(data) - elif self.eof: # handle EOF condition by stopping iteration - raise StopIteration() if len(block) == self.BUFSIZE: - values = common.loads(str(block)) + values = self.data_type(block) if self.check: self.check(values) return values @@ -46,7 +52,3 @@ class Reader(object): time.sleep(self.WAIT) raise IOError('timeout') - - -def iread(fd): - return itertools.chain.from_iterable(Reader(fd)) diff --git a/tests/test_stream.py b/tests/test_stream.py index 5dbbcf4..e5b80bd 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -25,7 +25,7 @@ def test_read(): j = 0 for i, buf in result: assert i == j - assert len(buf) == f.SAMPLES + assert len(buf) == f.bufsize j += 1 try: From cb08b23aa342ff26f70c6f3d530e47d42eee5729 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:00:31 +0300 Subject: [PATCH 05/11] fix imports --- amodem/calib.py | 9 +++++---- amodem/common.py | 6 ++++++ amodem/ecc.py | 2 +- amodem/loop.py | 7 ++++--- amodem/recv.py | 22 +++++++++++----------- amodem/send.py | 14 +++++++------- amodem/sigproc.py | 4 ++-- amodem/stream.py | 1 - amodem/wave.py | 2 +- tests/test_full.py | 6 +++++- 10 files changed, 42 insertions(+), 31 deletions(-) diff --git a/amodem/calib.py b/amodem/calib.py index 53446b7..25e0643 100755 --- a/amodem/calib.py +++ b/amodem/calib.py @@ -1,9 +1,10 @@ #!/usr/bin/env python import numpy as np -import common -import config -import sigproc -import wave + +from . import common +from . import config +from . import sigproc +from . import wave Tsample = 1 t = np.arange(int(Tsample * config.Fs)) * config.Ts diff --git a/amodem/common.py b/amodem/common.py index 97b58a6..62791e2 100644 --- a/amodem/common.py +++ b/amodem/common.py @@ -108,3 +108,9 @@ def icapture(iterable, result): def take(iterable, n): return np.array(list(itertools.islice(iterable, n))) + + +try: + izip = itertools.izip +except AttributeError: + izip = zip # Python 3 diff --git a/amodem/ecc.py b/amodem/ecc.py index b80b1aa..f69445c 100644 --- a/amodem/ecc.py +++ b/amodem/ecc.py @@ -1,7 +1,7 @@ ''' Reed-Solomon CODEC. ''' from reedsolo import rs_encode_msg, rs_correct_msg -import common +from . import common import logging log = logging.getLogger(__name__) diff --git a/amodem/loop.py b/amodem/loop.py index a1a409e..beef6cb 100644 --- a/amodem/loop.py +++ b/amodem/loop.py @@ -1,8 +1,9 @@ import numpy as np import itertools -import sampling -import sigproc +from . import sampling +from . import sigproc +from . import common class Filter(object): @@ -33,4 +34,4 @@ class FreqLoop(object): self.gens.append(gen) def __iter__(self): - return itertools.izip(*self.gens) + return common.izip(*self.gens) diff --git a/amodem/recv.py b/amodem/recv.py index d1d95ad..d6596df 100755 --- a/amodem/recv.py +++ b/amodem/recv.py @@ -8,21 +8,24 @@ import time import sys import os +import bitarray + log = logging.getLogger(__name__) -import stream -import sigproc -import loop -import train -import common -import config +from . import stream +from . import sigproc +from . import loop +from . import train +from . import common +from . import config +from . import ecc modem = sigproc.MODEM(config) if os.environ.get('PYLAB') == '1': - import pylab - import show + from . import pylab + from . import show WIDTH = np.floor(np.sqrt(len(modem.freqs))) HEIGHT = np.ceil(len(modem.freqs) / float(WIDTH)) else: @@ -223,9 +226,6 @@ def receive(signal, freqs, gain=1.0): def decode(bits_iterator): - import bitarray - import ecc - def blocks(): while True: bits = itertools.islice(bits_iterator, 8 * ecc.BLOCK_SIZE) diff --git a/amodem/send.py b/amodem/send.py index cae52d2..8f60210 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -7,13 +7,14 @@ import time log = logging.getLogger(__name__) -import train -import wave +from . import train +from . import wave -import common -import config -import sigproc -import stream +from . import common +from . import config +from . import sigproc +from . import stream +from . import ecc modem = sigproc.MODEM(config) @@ -66,7 +67,6 @@ def modulate(fd, bits): def main(args): - import ecc log.info('Running MODEM @ {:.1f} kbps'.format(modem.modem_bps / 1e3)) # padding audio with silence diff --git a/amodem/sigproc.py b/amodem/sigproc.py index 270c1fb..91b8f33 100644 --- a/amodem/sigproc.py +++ b/amodem/sigproc.py @@ -1,8 +1,8 @@ import numpy as np from numpy import linalg -import common -from config import Ts, Nsym +from . import common +from .config import Ts, Nsym class Filter(object): diff --git a/amodem/stream.py b/amodem/stream.py index 78ff5eb..20123d5 100644 --- a/amodem/stream.py +++ b/amodem/stream.py @@ -1,6 +1,5 @@ import time -import wave class Reader(object): diff --git a/amodem/wave.py b/amodem/wave.py index 57e47ab..7ab4a98 100755 --- a/amodem/wave.py +++ b/amodem/wave.py @@ -6,7 +6,7 @@ import logging log = logging.getLogger(__name__) -import config +from . import config Fs = int(config.Fs) # sampling rate bits_per_sample = 16 diff --git a/tests/test_full.py b/tests/test_full.py index 564e8af..6fcd276 100644 --- a/tests/test_full.py +++ b/tests/test_full.py @@ -1,5 +1,9 @@ import os -from cStringIO import StringIO +try: + from cStringIO import StringIO as BytesIO +except ImportError: + from io import BytesIO # Python 3 + import numpy as np from amodem import send From 16bc186631eb8fc1b1f4be37729fef454f1a3eb3 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:02:09 +0300 Subject: [PATCH 06/11] fix string/bytes issues --- amodem/common.py | 2 +- amodem/recv.py | 6 ++++-- amodem/send.py | 6 +++--- tests/test_full.py | 10 ++++++---- tests/test_stream.py | 4 ++-- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/amodem/common.py b/amodem/common.py index 62791e2..d260016 100644 --- a/amodem/common.py +++ b/amodem/common.py @@ -41,7 +41,7 @@ def load(fileobj): def loads(data): - x = np.fromstring(str(data), dtype='int16') + x = np.frombuffer(data, dtype='int16') x = x / scaling return x diff --git a/amodem/recv.py b/amodem/recv.py index d6596df..2a7d116 100755 --- a/amodem/recv.py +++ b/amodem/recv.py @@ -287,8 +287,10 @@ if __name__ == '__main__': p = argparse.ArgumentParser() p.add_argument('--skip', type=int, default=100, help='skip initial N samples, due to spurious spikes') - p.add_argument('-i', '--input', type=argparse.FileType('r'), default=sys.stdin) - p.add_argument('-o', '--output', type=argparse.FileType('w'), default=sys.stdout) + p.add_argument('-i', '--input', type=argparse.FileType('rb'), + default=sys.stdin) + p.add_argument('-o', '--output', type=argparse.FileType('wb'), + default=sys.stdout) args = p.parse_args() try: main(args) diff --git a/amodem/send.py b/amodem/send.py index 8f60210..fe9e7bf 100755 --- a/amodem/send.py +++ b/amodem/send.py @@ -34,7 +34,7 @@ class Writer(object): def write(self, fd, sym, n=1): data = common.dumps(sym, n) - fd.write(str(data)) + fd.write(data) self.offset += len(data) if time.time() > self.last + 1: log.debug('%10.3f seconds of data audio', @@ -99,9 +99,9 @@ if __name__ == '__main__': p = argparse.ArgumentParser() p.add_argument('--silence-start', type=float, default=1.0) p.add_argument('--silence-stop', type=float, default=1.0) - p.add_argument('-i', '--input', type=argparse.FileType('r'), + p.add_argument('-i', '--input', type=argparse.FileType('rb'), default=sys.stdin) - p.add_argument('-o', '--output', type=argparse.FileType('w'), + p.add_argument('-o', '--output', type=argparse.FileType('wb'), default=sys.stdout) args = p.parse_args() main(args) diff --git a/tests/test_full.py b/tests/test_full.py index 6fcd276..aa6c14d 100644 --- a/tests/test_full.py +++ b/tests/test_full.py @@ -18,18 +18,20 @@ class Args(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) + def run(size, chan): tx_data = os.urandom(size) - tx_audio = StringIO() - send.main(Args(silence_start=1, silence_stop=1, input=StringIO(tx_data), output=tx_audio)) + tx_audio = BytesIO() + send.main(Args(silence_start=1, silence_stop=1, + input=BytesIO(tx_data), output=tx_audio)) data = tx_audio.getvalue() data = common.loads(data) data = chan(data) data = common.dumps(data * 1j) - rx_audio = StringIO(data) + rx_audio = BytesIO(data) - rx_data = StringIO() + rx_data = BytesIO() recv.main(Args(skip=100, input=rx_audio, output=rx_data)) rx_data = rx_data.getvalue() diff --git a/tests/test_stream.py b/tests/test_stream.py index e5b80bd..d4e3a07 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -1,14 +1,14 @@ from amodem import stream import subprocess as sp -script = r""" +script = br""" import sys import time import os while True: time.sleep(0.1) - sys.stdout.write(b'\x00' * 6400) + sys.stdout.write('\x00' * 6400) sys.stderr.write('.') """ From 53363ee1717aa28ff7a56f78eb245d20bda6e801 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:03:09 +0300 Subject: [PATCH 07/11] fix iterator issues --- amodem/common.py | 2 +- amodem/recv.py | 2 +- amodem/sampling.py | 4 +++- amodem/wave.py | 2 +- tests/test_common.py | 10 +++++----- tests/test_stream.py | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/amodem/common.py b/amodem/common.py index d260016..cf9e078 100644 --- a/amodem/common.py +++ b/amodem/common.py @@ -83,7 +83,7 @@ class Splitter(object): while True: if all(self.read): try: - self.last = self.iterable.next() + self.last = next(self.iterable) except StopIteration: return diff --git a/amodem/recv.py b/amodem/recv.py index 2a7d116..d47fcba 100755 --- a/amodem/recv.py +++ b/amodem/recv.py @@ -193,7 +193,7 @@ def demodulate(symbols, filters, freqs, sampler): stats['rx_start'] = time.time() log.info('Demodulation started') - for i, block in enumerate(itertools.izip(*streams)): # block per frequency + for i, block in enumerate(common.izip(*streams)): # block per frequency for bits in block: stats['rx_bits'] = stats['rx_bits'] + len(bits) yield bits diff --git a/amodem/sampling.py b/amodem/sampling.py index 56a68d3..e55221d 100755 --- a/amodem/sampling.py +++ b/amodem/sampling.py @@ -49,6 +49,8 @@ class Sampler(object): def next(self): return self._sample() * self.gain + __next__ = next + def _sample(self): offset = self.offset # offset = k + (j / self.resolution) @@ -58,7 +60,7 @@ class Sampler(object): end = k + self.width while self.index < end: self.buff[:-1] = self.buff[1:] - self.buff[-1] = self.src.next() # throws StopIteration + self.buff[-1] = next(self.src) # throws StopIteration self.index += 1 self.offset += self.freq diff --git a/amodem/wave.py b/amodem/wave.py index 7ab4a98..269c66f 100755 --- a/amodem/wave.py +++ b/amodem/wave.py @@ -27,7 +27,7 @@ def record(fname, **kwargs): def launch(*args, **kwargs): - args = map(str, args) + args = list(map(str, args)) log.debug('$ %s', ' '.join(args)) p = sp.Popen(args=args, **kwargs) p.stop = lambda: os.kill(p.pid, signal.SIGKILL) diff --git a/tests/test_common.py b/tests/test_common.py index c5e32aa..7858fec 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -25,13 +25,13 @@ def test_iterate(): def test_split(): L = [(i*2, i*2+1) for i in range(10)] iters = common.split(L, n=2) - assert zip(*iters) == L + assert list(zip(*iters)) == L for i in [0, 1]: iters = common.split(L, n=2) - iters[i].next() + next(iters[i]) try: - iters[i].next() + next(iters[i]) assert False except IndexError as e: assert e.args == (i,) @@ -43,8 +43,8 @@ def test_icapture(): z = [] for i in common.icapture(x, result=y): z.append(i) - assert x == y - assert x == z + assert list(x) == y + assert list(x) == z def test_dumps_loads(): diff --git a/tests/test_stream.py b/tests/test_stream.py index d4e3a07..e220e26 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -19,7 +19,7 @@ def test_read(): p.stdin.close() f = stream.Reader(p.stdout) - result = zip(range(10), f) + result = list(zip(range(10), f)) p.kill() j = 0 From 2030b0942f219917d4792f6eab99dc5a7b5c8ea0 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:04:16 +0300 Subject: [PATCH 08/11] fix whitespace and styling --- amodem/calib.py | 11 +++++++---- tests/test_full.py | 6 ++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/amodem/calib.py b/amodem/calib.py index 25e0643..06197f7 100755 --- a/amodem/calib.py +++ b/amodem/calib.py @@ -23,6 +23,7 @@ def send(): except KeyboardInterrupt: p.kill() + def recv(): p = wave.record('-', stdout=wave.sp.PIPE) try: @@ -37,13 +38,15 @@ def recv(): continue x = x - np.mean(x) - c = np.abs(np.dot(x, sig)) / (np.sqrt(0.5 * len(x)) * sigproc.norm(x)) + normalization_factor = np.sqrt(0.5 * len(x)) * sigproc.norm(x) + coherence = np.abs(np.dot(x, sig)) / normalization_factor z = np.dot(x, sig.conj()) / (0.5 * len(x)) - amp = np.abs(z) + amplitude = np.abs(z) phase = np.angle(z) peak = np.max(np.abs(x)) - print('coherence={:.3f} amp={:.3f} phase={:.1f} peak={:.3f}'.format( - c, amp, phase * 180 / np.pi, peak)) + + fmt = 'coherence={:.3f} amplitude={:.3f} phase={:+.1f} peak={:.3f}' + print(fmt.format(coherence, amplitude, phase * 180 / np.pi, peak)) except KeyboardInterrupt: p.kill() diff --git a/tests/test_full.py b/tests/test_full.py index aa6c14d..3c1a533 100644 --- a/tests/test_full.py +++ b/tests/test_full.py @@ -14,6 +14,7 @@ import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-12s %(message)s') + class Args(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) @@ -37,19 +38,24 @@ def run(size, chan): assert rx_data == tx_data + def test_small(): run(1024, lambda x: x) + def test_large(): run(54321, lambda x: x) + def test_attenuation(): run(5120, lambda x: x * 0.1) + def test_low_noise(): r = np.random.RandomState(seed=0) run(5120, lambda x: x + r.normal(size=len(x), scale=0.0001)) + def test_medium_noise(): r = np.random.RandomState(seed=0) run(5120, lambda x: x + r.normal(size=len(x), scale=0.001)) From 0b91ef76c59e23e30f4d9c9b95419be84dfd75cd Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:04:27 +0300 Subject: [PATCH 09/11] fix stream implementation --- amodem/stream.py | 36 ++++++++++++++++++++---------------- tests/test_stream.py | 4 ++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/amodem/stream.py b/amodem/stream.py index 20123d5..25844ff 100644 --- a/amodem/stream.py +++ b/amodem/stream.py @@ -1,21 +1,25 @@ import time +import logging +log = logging.getLogger(__name__) + + +class Timeout(Exception): + pass class Reader(object): - SAMPLES = 4096 - BUFSIZE = int(SAMPLES * wave.bytes_per_sample) - WAIT = 0.1 - TIMEOUT = 2.0 - - def __init__(self, fd, data_type=None, bufsize=None, eof=False): + def __init__(self, fd, data_type=None, bufsize=4096, + eof=False, timeout=2.0, wait=0.2): self.fd = fd - self.check = None - self.total = 0 - self.bufsize = bufsize if (bufsize is not None) else self.BUFSIZE - self.eof = eof self.data_type = data_type if (data_type is not None) else lambda x: x + self.bufsize = bufsize + self.eof = eof + self.timeout = timeout + self.wait = wait + self.total = 0 + self.check = None def __iter__(self): return self @@ -26,7 +30,7 @@ class Reader(object): def next(self): block = bytearray() if self.eof: - data = self.fd.read(self.BUFSIZE) + data = self.fd.read(self.bufsize) if data: self.total += len(data) block.extend(data) @@ -34,20 +38,20 @@ class Reader(object): else: raise StopIteration() - finish_time = time.time() + self.TIMEOUT + finish_time = time.time() + self.timeout while time.time() <= finish_time: - left = self.BUFSIZE - len(block) + left = self.bufsize - len(block) data = self.fd.read(left) if data: self.total += len(data) block.extend(data) - if len(block) == self.BUFSIZE: + if len(block) == self.bufsize: values = self.data_type(block) if self.check: self.check(values) return values - time.sleep(self.WAIT) + time.sleep(self.wait) - raise IOError('timeout') + raise Timeout(self.timeout) diff --git a/tests/test_stream.py b/tests/test_stream.py index e220e26..8805bd1 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -31,5 +31,5 @@ def test_read(): try: for buf in f: pass - except IOError as e: - assert str(e) == 'timeout' + except stream.Timeout as e: + assert e.args == (f.timeout,) From e4ba6cf232c70378d2cbed7605a38c4d3e008aea Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:04:39 +0300 Subject: [PATCH 10/11] move scripts directory --- {amodem/scripts => scripts}/auto-calib.sh | 4 ++-- {amodem/scripts => scripts}/profile.sh | 0 {amodem/scripts => scripts}/test.sh | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) rename {amodem/scripts => scripts}/auto-calib.sh (56%) rename {amodem/scripts => scripts}/profile.sh (100%) rename {amodem/scripts => scripts}/test.sh (78%) diff --git a/amodem/scripts/auto-calib.sh b/scripts/auto-calib.sh similarity index 56% rename from amodem/scripts/auto-calib.sh rename to scripts/auto-calib.sh index af47cc2..d97687d 100755 --- a/amodem/scripts/auto-calib.sh +++ b/scripts/auto-calib.sh @@ -1,7 +1,7 @@ #!/bin/bash killall -q aplay arecord -./calib.py send & +python -m amodem.calib send & SENDER_PID=$! -./calib.py recv +python -m amodem.calib recv kill -INT $SENDER_PID diff --git a/amodem/scripts/profile.sh b/scripts/profile.sh similarity index 100% rename from amodem/scripts/profile.sh rename to scripts/profile.sh diff --git a/amodem/scripts/test.sh b/scripts/test.sh similarity index 78% rename from amodem/scripts/test.sh rename to scripts/test.sh index f97bb2b..0e9b640 100755 --- a/amodem/scripts/test.sh +++ b/scripts/test.sh @@ -32,20 +32,20 @@ run_src dd if=/dev/urandom of=$TEST_DIR/data.send bs=125kB count=1 status=none SRC_HASH=`run_src sha256sum $TEST_DIR/data.send` # modulate data into audio file -run_src "./send.py <$TEST_DIR/data.send >$TEST_DIR/audio.send" +run_src "python -m amodem.send -i $TEST_DIR/data.send -o $TEST_DIR/audio.send" # stop old recording and start a new one run_src killall -q aplay || true run_dst killall -q arecord || true -run_dst "./wave.py record $TEST_DIR/audio.recv" & +run_dst "python -m amodem.wave record $TEST_DIR/audio.recv" & sleep 1 # let audio.recv be filled # play the modulated data -run_src ./wave.py play $TEST_DIR/audio.send & +run_src "python -m amodem.wave play $TEST_DIR/audio.send" & # start the receiever -run_dst "./recv.py <$TEST_DIR/audio.recv >$TEST_DIR/data.recv" +run_dst "python -m amodem.recv -i $TEST_DIR/audio.recv -o $TEST_DIR/data.recv" # stop recording after playing is over run_src killall -q aplay || true From 01670827359fb97968d98c6cca30cc481f4f361c Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 7 Aug 2014 17:05:27 +0300 Subject: [PATCH 11/11] add Python 3 to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0934039..d83083a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: python python: - "2.7" + - "3.3" install: - pip install .