diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..104ffb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.wav diff --git a/listen.py b/listen.py index c0d73df..9cb7431 100644 --- a/listen.py +++ b/listen.py @@ -1,5 +1,3 @@ -import Queue -import threading import time import pyaudio import numpy as np @@ -16,13 +14,6 @@ sigil = [int(x) for x in options.sigil] frames_per_buffer = chunk * 10 -in_length = 4000 -# raw audio frames -in_frames = Queue.Queue(in_length) -# the value of the fft at the frequency we care about -points = Queue.Queue(in_length) -bits = Queue.Queue(in_length / frame_length) - wait_for_sample_timeout = 0.1 wait_for_frames_timeout = 0.1 wait_for_point_timeout = 0.1 @@ -31,88 +22,82 @@ # yeeeep this is just hard coded bottom_threshold = 8000 -def process_frames(): - while True: - try: - frame = in_frames.get(False) - fft = quietnet.fft(frame) - point = quietnet.has_freq(fft, search_freq, rate, chunk) - points.put(point) - except Queue.Empty: - time.sleep(wait_for_frames_timeout) +def process_frames(frame): + fft = quietnet.fft(frame) + point = quietnet.has_freq(fft, search_freq, rate, chunk) + process_points(point) -def process_points(): - while True: - cur_points = [] - while len(cur_points) < frame_length: - try: - cur_points.append(points.get(False)) - except Queue.Empty: - time.sleep(wait_for_point_timeout) - while True: - while np.average(cur_points) > bottom_threshold: - try: - cur_points.append(points.get(False)) - cur_points = cur_points[1:] - except Queue.Empty: - time.sleep(wait_for_point_timeout) - next_point = None - while next_point == None: - try: - next_point = points.get(False) - except Queue.Empty: - time.sleep(wait_for_point_timeout) - if next_point > bottom_threshold: - bits.put(0) - bits.put(0) - cur_points = [cur_points[-1]] - break - print '' +def process_points(point): + if not hasattr(process_points, "estate"): + process_points.estate = 0 + + if not hasattr(process_points, "cur_points"): + process_points.cur_points = [] + + if not hasattr(process_points, "last_bits"): + process_points.last_bits = [] - last_bits = [] - while True: - if len(cur_points) == frame_length: - bit = int(quietnet.get_bit(cur_points, frame_length) > bottom_threshold) - cur_points = [] - bits.put(bit) - last_bits.append(bit) - # if we've only seen low bits for a while assume the next message might not be on the same bit boundary - if len(last_bits) > 3: - if sum(last_bits) == 0: - break - last_bits = last_bits[1:] - try: - cur_points.append(points.get(False)) - except Queue.Empty: - time.sleep(wait_for_point_timeout) + if process_points.estate == 0: + if len(process_points.cur_points) < frame_length: + process_points.cur_points.append(point) + return + else: + process_points.estate = 1 -def process_bits(): - while True: - cur_bits = [] - # while the last two characters are not the sigil - while len(cur_bits) < 2 or cur_bits[-len(sigil):len(cur_bits)] != sigil: - try: - cur_bits.append(bits.get(False)) - except Queue.Empty: - time.sleep(wait_for_byte_timeout) - sys.stdout.write(psk.decode(cur_bits[:-len(sigil)])) - sys.stdout.flush() + if process_points.estate >= 1 and process_points.estate <= 2: + if process_points.estate == 1: + if np.average(process_points.cur_points) > bottom_threshold: + process_points.cur_points.append(point) + process_points.cur_points = process_points.cur_points[1:] + return + else: + process_points.estate = 2 + + if process_points.estate == 2: + next_point = point + if next_point > bottom_threshold: + process_bits(0) + process_bits(0) + process_points.cur_points = [process_points.cur_points[-1]] + process_points.last_bits = [] + print('') + process_points.estate = 3 + return + + + if process_points.estate == 3: + if len(process_points.cur_points) == frame_length: + bit = int(quietnet.get_bit(process_points.cur_points, frame_length) > bottom_threshold) + process_points.cur_points = [] + process_bits(bit) + process_points.last_bits.append(bit) + # if we've only seen low bits for a while assume the next message might not be on the same bit boundary + if len(process_points.last_bits) > 3: + if sum(process_points.last_bits) == 0: + process_points.estate = 0 + return + process_points.last_bits = process_points.last_bits[1:] + process_points.cur_points.append(point) + #return -# start the queue processing threads -processes = [process_frames, process_points, process_bits] -threads = [] +def process_bits(bit): + if not hasattr(process_bits, "cur_bits"): + process_bits.cur_bits = [] + + process_bits.cur_bits.append(bit) -for process in processes: - thread = threading.Thread(target=process) - thread.daemon = True - thread.start() + # while the last two characters are not the sigil + if len(process_bits.cur_bits) >= 2 \ + and process_bits.cur_bits[-len(sigil):len(process_bits.cur_bits)] == sigil: + sys.stdout.write(psk.decode(process_bits.cur_bits[:-len(sigil)])) + sys.stdout.flush() + process_bits.cur_bits = [] def callback(in_data, frame_count, time_info, status): frames = list(quietnet.chunks(quietnet.unpack(in_data), chunk)) for frame in frames: - if not in_frames.full(): - in_frames.put(frame, False) + process_frames(frame) return (in_data, pyaudio.paContinue) def start_analysing_stream(): diff --git a/quietnet.py b/quietnet.py index efdc6f6..3bfa4c3 100644 --- a/quietnet.py +++ b/quietnet.py @@ -1,11 +1,16 @@ import numpy as np import struct import math +import sys # split something into chunks def chunks(l, n): - for i in xrange(0, len(l), n): - yield l[i:i+n] + if sys.version_info[0] < 3: + for i in xrange(0, len(l), n): + yield l[i:i+n] + else: + for i in range(0, len(l), n): + yield l[i:i+n] def unpack(buffer): return unpack_buffer(list(chunks(buffer, 2))) diff --git a/send.py b/send.py index 3f4000b..8fa9ffe 100644 --- a/send.py +++ b/send.py @@ -2,6 +2,7 @@ import quietnet import options import psk +import sys FORMAT = pyaudio.paInt16 CHANNELS = options.channels @@ -39,7 +40,7 @@ def make_buffer_from_bit_pattern(pattern, on_freq, off_freq): return quietnet.pack_buffer(output_buffer) def play_buffer(buffer): - output = ''.join(buffer) + output = b''.join(buffer) stream.write(output) if __name__ == "__main__": @@ -48,7 +49,10 @@ def play_buffer(buffer): try: # get user input and play message while True: - message = raw_input("> ") + if sys.version_info[0] < 3: + message = raw_input("> ") + else: + message = input("> ") try: pattern = psk.encode(message) buffer = make_buffer_from_bit_pattern(pattern, FREQ, FREQ_OFF)