Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
*.wav
147 changes: 66 additions & 81 deletions listen.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Queue
import threading
import time
import pyaudio
import numpy as np
Expand All @@ -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
Expand All @@ -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():
Expand Down
9 changes: 7 additions & 2 deletions quietnet.py
Original file line number Diff line number Diff line change
@@ -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)))
Expand Down
8 changes: 6 additions & 2 deletions send.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import quietnet
import options
import psk
import sys

FORMAT = pyaudio.paInt16
CHANNELS = options.channels
Expand Down Expand Up @@ -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__":
Expand All @@ -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)
Expand Down