diff --git a/ecc.py b/ecc.py index 7fb8b3b..db54914 100644 --- a/ecc.py +++ b/ecc.py @@ -4,8 +4,6 @@ from reedsolo import rs_encode_msg, rs_correct_msg import logging log = logging.getLogger(__name__) -import common - DEFAULT_NSYM = 10 BLOCK_SIZE = 255 @@ -17,7 +15,6 @@ def end_of_stream(size): def encode(data, nsym=DEFAULT_NSYM): chunk_size = BLOCK_SIZE - nsym - 1 - enc = bytearray() for i in range(0, len(data), chunk_size): chunk = bytearray(data[i:i+chunk_size]) @@ -26,19 +23,20 @@ def encode(data, nsym=DEFAULT_NSYM): padding = b'\x00' * (chunk_size - size) chunk.extend(padding) - chunk = bytearray([size]) + chunk - enc.extend(rs_encode_msg(chunk, nsym)) + block = bytearray([size]) + chunk + yield rs_encode_msg(block, nsym) - enc.extend(rs_encode_msg(end_of_stream(chunk_size), nsym)) - return enc + yield rs_encode_msg(end_of_stream(chunk_size), nsym) -def decode(data, nsym=DEFAULT_NSYM): +def decode(blocks, nsym=DEFAULT_NSYM): last_chunk = end_of_stream(BLOCK_SIZE - nsym - 1) - for _, block in common.iterate(data, BLOCK_SIZE): + for block in blocks: + assert len(block) == BLOCK_SIZE chunk = bytearray(rs_correct_msg(block, nsym)) if chunk == last_chunk: + log.info('EOF encountered') return # end of stream size = chunk[0] diff --git a/recv.py b/recv.py index 708cd4d..6e624ee 100755 --- a/recv.py +++ b/recv.py @@ -141,6 +141,7 @@ def demodulate(symbols, filters, freqs): yield bits decoded_bits = decoded_bits + len(bits) + # TODO: make this run even after EOF duration = time.time() - start audio_time = decoded_bits / sigproc.modem_bps log.info('Demodulated %.3f kB @ %.3f seconds = %.1f%% realtime', @@ -162,28 +163,24 @@ def receive(signal, freqs): signal.sampler.freq -= err filters = train_receiver(symbols, freqs) - return demodulate(symbols, filters, freqs) + data_bits = demodulate(symbols, filters, freqs) + return itertools.chain.from_iterable(data_bits) def decode(bits_iterator): - import cStringIO import bitarray import ecc - result = cStringIO.StringIO() - while True: - bits = itertools.islice(bits_iterator, 8 * ecc.BLOCK_SIZE) - block = bitarray.bitarray(endian='little') - block.extend(bits) - if not block: - break - result.write(block) - - data = bytearray(result.getvalue()) - data = ecc.decode(data) - if data is None: - log.warning('No blocks decoded!') + def blocks(): + while True: + bits = itertools.islice(bits_iterator, 8 * ecc.BLOCK_SIZE) + block = bitarray.bitarray(endian='little') + block.extend(bits) + if not block: + break + yield bytearray(block.tobytes()) + data = ecc.decode(blocks()) return data @@ -213,9 +210,8 @@ def main(fname): if peak > SATURATION_THRESHOLD: raise ValueError('Saturation detected: {:.3f}'.format(peak)) - data_bits = receive(x / amp, frequencies) - bits = itertools.chain.from_iterable(data_bits) size = 0 + bits = receive(x / amp, frequencies) for chunk in decode(bits): sys.stdout.write(chunk) size = size + len(chunk) diff --git a/send.py b/send.py index 204a104..1fb3c25 100755 --- a/send.py +++ b/send.py @@ -60,7 +60,10 @@ def main(fname): training_size / wave.bytes_per_second) log.info('%d bits to be send', len(data)*8) - bits = list(to_bits(ecc.encode(data))) + buf = bytearray() + for block in ecc.encode(data): + buf.extend(block) + bits = list(to_bits(buf)) ecc_ratio = 1.0 - len(data)*8.0 / len(bits) log.info('%d bits modulated (%.1f%% ECC)', len(bits), ecc_ratio * 100) modulate(fd, bits)