#!/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()