mirror of
https://github.com/romanz/amodem.git
synced 2026-05-09 13:07:39 +08:00
refactor calibration recv script
This commit is contained in:
@@ -12,7 +12,7 @@ CALIBRATION_SYMBOLS = int(1.0 * config.Fs)
|
|||||||
ALLOWED_EXCEPTIONS = (IOError, KeyboardInterrupt)
|
ALLOWED_EXCEPTIONS = (IOError, KeyboardInterrupt)
|
||||||
|
|
||||||
|
|
||||||
def send(wave_play=wave.play):
|
def send(wave_play=wave.play, verbose=False):
|
||||||
t = np.arange(0, CALIBRATION_SYMBOLS) * config.Ts
|
t = np.arange(0, CALIBRATION_SYMBOLS) * config.Ts
|
||||||
signal = [np.sin(2 * np.pi * f * t) for f in config.frequencies]
|
signal = [np.sin(2 * np.pi * f * t) for f in config.frequencies]
|
||||||
signal = common.dumps(np.concatenate(signal))
|
signal = common.dumps(np.concatenate(signal))
|
||||||
@@ -28,41 +28,66 @@ def send(wave_play=wave.play):
|
|||||||
p.kill()
|
p.kill()
|
||||||
|
|
||||||
|
|
||||||
FRAME_LENGTH = 100 * config.Nsym
|
FRAME_LENGTH = 200 * config.Nsym
|
||||||
|
|
||||||
|
|
||||||
def recorder(process):
|
def recorder(process):
|
||||||
|
t = np.arange(0, FRAME_LENGTH) * config.Ts
|
||||||
|
scaling_factor = 0.5 * len(t)
|
||||||
|
carriers = [np.exp(2j * np.pi * f * t) for f in config.frequencies]
|
||||||
|
carriers = np.array(carriers) / scaling_factor
|
||||||
|
|
||||||
frame_size = int(wave.bytes_per_sample * FRAME_LENGTH)
|
frame_size = int(wave.bytes_per_sample * FRAME_LENGTH)
|
||||||
fd = process.stdout
|
fd = process.stdout
|
||||||
|
|
||||||
|
states = [True]
|
||||||
|
errors = ['weak', 'strong', 'noisy']
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
data = fd.read(frame_size)
|
data = fd.read(frame_size)
|
||||||
if len(data) < frame_size:
|
if len(data) < frame_size:
|
||||||
return
|
return
|
||||||
data = common.loads(data)
|
data = common.loads(data)
|
||||||
data = data - np.mean(data)
|
frame = data - np.mean(data)
|
||||||
yield data
|
|
||||||
|
coeffs = np.dot(carriers, frame)
|
||||||
|
peak = np.max(np.abs(frame))
|
||||||
|
total = np.sqrt(np.dot(frame, frame) / scaling_factor)
|
||||||
|
|
||||||
|
max_index = np.argmax(np.abs(coeffs))
|
||||||
|
freq = config.frequencies[max_index]
|
||||||
|
rms = abs(coeffs[max_index])
|
||||||
|
coherency = rms / total
|
||||||
|
flags = [rms > 0.1, peak < 1.0, coherency > 0.9999]
|
||||||
|
|
||||||
|
states.append(all(flags))
|
||||||
|
states = states[-2:]
|
||||||
|
|
||||||
|
message = 'good signal'
|
||||||
|
error = not any(states)
|
||||||
|
if error:
|
||||||
|
error_index = flags.index(False)
|
||||||
|
message = 'too {} signal'.format(errors[error_index])
|
||||||
|
|
||||||
|
yield dict(
|
||||||
|
freq=freq, rms=rms, peak=peak, coherency=coherency,
|
||||||
|
total=total, error=error, message=message
|
||||||
|
)
|
||||||
except ALLOWED_EXCEPTIONS:
|
except ALLOWED_EXCEPTIONS:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
process.kill()
|
process.kill()
|
||||||
|
|
||||||
|
fmt = '{freq:6.0f} Hz: {message:s}{extra:s}'
|
||||||
|
fields = ['peak', 'total', 'rms', 'coherency']
|
||||||
|
|
||||||
def recv(wave_record=wave.record, log=sys.stdout.write):
|
def recv(wave_record=wave.record, printer=sys.stdout.write, verbose=False):
|
||||||
t = np.arange(0, FRAME_LENGTH) * config.Ts
|
extra = ''
|
||||||
carriers = [np.exp(2j * np.pi * f * t) for f in config.frequencies]
|
if verbose:
|
||||||
carriers = np.array(carriers) / (0.5 * len(t))
|
extra = ''.join(', {0}={{{0}:.4f}}'.format(f) for f in fields)
|
||||||
|
for r in recorder(wave_record(stdout=wave.sp.PIPE)):
|
||||||
for frame in recorder(wave_record(stdout=wave.sp.PIPE)):
|
msg = fmt.format(extra=extra.format(**r), **r)
|
||||||
peak = np.max(np.abs(frame))
|
if not r['error']:
|
||||||
coeffs = np.dot(carriers, frame)
|
log.info(msg)
|
||||||
max_index = np.argmax(np.abs(coeffs))
|
else:
|
||||||
max_coeff = coeffs[max_index]
|
log.error(msg)
|
||||||
|
|
||||||
freq = config.frequencies[max_index]
|
|
||||||
rms = abs(max_coeff)
|
|
||||||
total = np.sqrt(np.dot(frame, frame) / (0.5 * len(t)))
|
|
||||||
coherency = rms / total
|
|
||||||
log(fmt.format(freq / 1e3, 100 * coherency, rms, total, peak))
|
|
||||||
|
|
||||||
fmt = '{:4.0f} kHz @ {:6.2f}% : RMS = {:.4f}, Total = {:.4f}, Peak = {:.4f}\n'
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ def run_modem(args, func):
|
|||||||
|
|
||||||
def run_send(args):
|
def run_send(args):
|
||||||
if args.calibrate:
|
if args.calibrate:
|
||||||
calib.send()
|
calib.send(verbose=args.verbose)
|
||||||
elif args.wave:
|
elif args.wave:
|
||||||
join_process(wave.play(fname=args.input))
|
join_process(wave.play(fname=args.input))
|
||||||
else:
|
else:
|
||||||
@@ -157,7 +157,7 @@ def run_send(args):
|
|||||||
|
|
||||||
def run_recv(args):
|
def run_recv(args):
|
||||||
if args.calibrate:
|
if args.calibrate:
|
||||||
calib.recv()
|
calib.recv(verbose=args.verbose)
|
||||||
elif args.wave:
|
elif args.wave:
|
||||||
join_process(wave.record(fname=args.output))
|
join_process(wave.record(fname=args.output))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -43,5 +43,5 @@ def test_errors():
|
|||||||
def _read(data):
|
def _read(data):
|
||||||
raise KeyboardInterrupt()
|
raise KeyboardInterrupt()
|
||||||
p.read = _read
|
p.read = _read
|
||||||
calib.recv(p)
|
calib.recv(p, verbose=True)
|
||||||
assert p.buf.tell() == 0
|
assert p.buf.tell() == 0
|
||||||
|
|||||||
Reference in New Issue
Block a user