1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
import struct
import numpy as np
import pyaudio
import threading
import utils
from utils import *
class Recv:
def __init__(self, start_freq=18000):
self.start_freq = start_freq
self.freq_range = 2000
self.sampling_rate = 44100
self.p = pyaudio.PyAudio()
self.bytes_per_transmit = 1
# TODO: use stream to send back the data
self.CHUNK = 2048 * 2
self.FORMAT = pyaudio.paInt32
self.CHANNELS = 1
self.RATE = 44100
self.pause = False
# stream object
self.p = pyaudio.PyAudio()
self.stream = self.p.open(
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
output=True,
frames_per_buffer=self.CHUNK,
)
def read_audio_stream(self):
data = self.stream.read(self.CHUNK)
data_int = struct.unpack(str(self.CHUNK) + 'i', data)
return data_int
def print_data(self, data):
print(data)
def safe_check_byte(self, bytes_seen):
safe_byte = []
if len(bytes_seen) > 0:
for col in range(len(bytes_seen[0])):
count1s = 0
count0s = 0
for row in range(len(bytes_seen)):
bit = bytes_seen[row][col]
if bit == '1':
count1s += 1
else:
count0s += 1
if count1s > count0s:
safe_byte.append('1')
else:
safe_byte.append('0')
return safe_byte
def listen(self):
prev_is_data_flag = '0'
prev_is_new_byte_flag = '0'
bytes_seen = []
recv_buffer = []
while True:
data = self.read_audio_stream()
bits = wave_to_bits(data, self.start_freq, self.freq_range, self.bytes_per_transmit)
# handle the data flags
is_data_flag = bits[-1]
is_new_byte_flag = bits[-2]
if prev_is_data_flag == '0' and is_data_flag == '1':
prev_is_data_flag = is_data_flag
# just started receiving data
bytes_seen = []
recv_buffer = []
is_data_flag = bits[-1]
if prev_is_data_flag == '0' and is_data_flag == '0':
prev_is_data_flag = is_data_flag
# just waiting for new data
continue
if prev_is_data_flag == '1' and is_data_flag == '0':
prev_is_data_flag = is_data_flag
# just finished the last byte of data, add it to buffer, then write buffer to terminal
recv_buffer.append(self.safe_check_byte(bytes_seen))
# FIXME: what to do with buffer?
# for now print buffer as string
buffer_as_string = ''.join([utils.receive_string(byte) for byte in recv_buffer])
print("received data: ", buffer_as_string)
# clear data structure & buffer
continue
# at this point, we know we are receiving data
if prev_is_new_byte_flag == is_new_byte_flag:
prev_is_new_byte_flag = is_new_byte_flag
# we are still receiving the same byte, store it in the data structure
byte = bits[:-2]
bytes_seen.append(byte)
continue
else:
prev_is_new_byte_flag = is_new_byte_flag
# we are receiving a new byte, so we need to write the old byte to the recv buffer
recv_buffer.append(self.safe_check_byte(bytes_seen))
# clear the data structure
bytes_seen = []
# append the new byte to the data structure
byte = bits[:-2]
bytes_seen.append(byte)
continue
def main():
recv = Recv()
recv.listen()
if __name__ == "__main__":
main()
|