forked from romanz/amodem
-
Notifications
You must be signed in to change notification settings - Fork 1
/
send.py
executable file
·121 lines (90 loc) · 3.02 KB
/
send.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python
import numpy as np
import sys
import logging
import itertools
import time
log = logging.getLogger(__name__)
import train
import wave
import common
import config
import sigproc
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]
sym = Symbol()
class Writer(object):
def __init__(self):
self.last = time.time()
self.offset = 0
def write(self, fd, sym, n=1):
data = common.dumps(sym, n)
fd.write(data)
self.offset += len(data)
if time.time() > self.last + 1:
log.debug('%10.3f seconds of data audio',
self.offset / wave.bytes_per_second)
self.last += 1
writer = Writer()
def start(fd, c):
writer.write(fd, c*1, n=400)
writer.write(fd, c*0, n=50)
def training(fd, c):
for b in train.equalizer:
writer.write(fd, c * b)
def modulate(fd, bits):
symbols_iter = modem.qam.encode(bits)
symbols_iter = itertools.chain(symbols_iter, itertools.repeat(0))
carriers = np.array(sym.carrier) / len(sym.carrier)
while True:
symbols = itertools.islice(symbols_iter, len(sym.carrier))
symbols = np.array(list(symbols))
writer.write(fd, np.dot(symbols, carriers))
if all(symbols == 0): # EOF marker
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))
fd = sys.stdout
# padding audio with silence
writer.write(fd, np.zeros(int(config.Fs * args.silence_start)))
start(fd, sym.carrier[config.carrier_index])
for c in sym.carrier:
training(fd, c)
training_size = writer.offset
log.info('%.3f seconds of training audio',
training_size / wave.bytes_per_second)
reader = Reader(sys.stdin, 64 << 10)
data = itertools.chain.from_iterable(reader)
encoded = itertools.chain.from_iterable(ecc.encode(data))
modulate(fd, bits=common.to_bits(encoded))
data_size = writer.offset - training_size
log.info('%.3f seconds of data audio, for %.3f kB of data',
data_size / wave.bytes_per_second, reader.total / 1e3)
# padding audio with silence
writer.write(fd, np.zeros(int(config.Fs * args.silence_stop)))
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)-12s %(message)s')
import argparse
p = argparse.ArgumentParser()
p.add_argument('--silence-start', type=float, default=1.0)
p.add_argument('--silence-stop', type=float, default=1.0)
args = p.parse_args()
main(args)