mirror of
https://github.com/romanz/amodem.git
synced 2026-02-06 08:38:06 +08:00
114 lines
3.7 KiB
Python
Executable File
114 lines
3.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
import sys
|
|
if sys.version_info.major == 2:
|
|
_stdin = sys.stdin
|
|
_stdout = sys.stdout
|
|
else:
|
|
_stdin = sys.stdin.buffer
|
|
_stdout = sys.stdout.buffer
|
|
|
|
import logging
|
|
format = '%(asctime)s %(levelname)-10s %(message)-100s %(filename)s:%(lineno)d'
|
|
logging.basicConfig(level=logging.DEBUG, format=format)
|
|
|
|
from amodem import recv
|
|
from amodem import send
|
|
from amodem import wave
|
|
|
|
import argparse
|
|
from functools import partial
|
|
|
|
null = open('/dev/null', 'wb')
|
|
|
|
def FileType(mode, process=None):
|
|
def opener(fname):
|
|
assert 'r' in mode or 'w' in mode
|
|
if process is None and fname is None:
|
|
fname = '-'
|
|
|
|
if fname is None:
|
|
if 'r' in mode: return process(stdout=wave.sp.PIPE, stderr=null).stdout
|
|
if 'w' in mode: return process(stdin=wave.sp.PIPE, stderr=null).stdin
|
|
|
|
if fname == '-':
|
|
if 'r' in mode: return _stdin
|
|
if 'w' in mode: return _stdout
|
|
|
|
return open(fname, mode)
|
|
|
|
return opener
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser()
|
|
subparsers = p.add_subparsers()
|
|
|
|
# Modulator
|
|
sender = subparsers.add_parser('send', help='modulate binary data into audio signal.')
|
|
sender.add_argument('-i', '--input', help='input file (use "-" for stdin).')
|
|
sender.add_argument('-o', '--output', help='output file (use "-" for stdout).'
|
|
' if not specified, `aplay` tool will be used.')
|
|
|
|
sender.add_argument('--silence-start', type=float, default=1.0,
|
|
help='seconds of silence before transmission starts')
|
|
sender.add_argument('--silence-stop', type=float, default=1.0,
|
|
help='seconds of silence after transmission stops')
|
|
|
|
sender.set_defaults(main=send.main,
|
|
input_type=FileType('rb'),
|
|
output_type=FileType('wb', wave.play)
|
|
)
|
|
|
|
# Demodulator
|
|
receiver = subparsers.add_parser('recv', help='demodulate audio signal into binary data.')
|
|
receiver.add_argument('-i', '--input', help='input file (use "-" for stdin).'
|
|
' if not specified, `arecord` tool will be used.')
|
|
receiver.add_argument('-o', '--output', help='output file (use "-" for stdout).')
|
|
receiver.add_argument('--skip', type=int, default=128,
|
|
help='skip initial N samples, due to spurious spikes')
|
|
receiver.add_argument('--plot', dest='plt', action='store_true', default=False,
|
|
help='plot results using pylab module')
|
|
receiver.set_defaults(main=recv.main,
|
|
input_type=FileType('rb', wave.record),
|
|
output_type=FileType('wb')
|
|
)
|
|
|
|
# Audio recording tool
|
|
fmt = 'a raw audio file (16 bits at {:.1f} kHz)'.format(wave.Fs / 1e3)
|
|
recorder = subparsers.add_parser('record', help='record ' + fmt)
|
|
recorder.add_argument(
|
|
'filename', default='-',
|
|
help='path to the audio file to record (otherwise, use stdout)')
|
|
recorder.set_defaults(main=partial(run, process=wave.record))
|
|
|
|
# Audio playing tool
|
|
player = subparsers.add_parser('play', help='play ' + fmt)
|
|
player.add_argument(
|
|
'filename', default='-',
|
|
help='path to the audio file to play (otherwise, use stdin)')
|
|
player.set_defaults(main=partial(run, process=wave.play))
|
|
|
|
# Parsing and execution
|
|
args = p.parse_args()
|
|
if hasattr(args, 'input_type'):
|
|
args.input = args.input_type(args.input)
|
|
if hasattr(args, 'output_type'):
|
|
args.output = args.output_type(args.output)
|
|
if getattr(args, 'plt', 'None'):
|
|
import pylab
|
|
args.plt = pylab
|
|
args.main(args)
|
|
|
|
def run(args, process):
|
|
p = process(fname=args.filename)
|
|
exitcode = 0
|
|
try:
|
|
exitcode = p.wait()
|
|
except KeyboardInterrupt:
|
|
p.kill()
|
|
exitcode = p.wait()
|
|
sys.exit(exitcode)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|