我正在通过“听不清”的频率构建数据传输系统,但到目前为止最好的结果是6%的位丢失,以2bps的速度传输450B。我对数据传输了解不多,这是我在Python中的第一个项目。
以异步通信的形式发送,理论上可以实现无损传输,因此我不知道为什么它会以低速(例如2bps)丢失数据位。这是接收部分的代码,我已经用外部设备测试了一个传输,它可以准确无误地工作:/
import pyaudio
import numpy as np
import pylab
#import matplotlib.pyplot as plt
from scipy.io import wavfile
from timeit import default_timer as timer
import sys
import seaborn as sns
import time
class Fourier():
def __init__(self):
print("Fourier class constructed\n")
#Random variables
received_data = ""
#i=0
#f,ax = plt.subplots(2)
#Default value, gets changed according to set_reading_speed()
speed = 1
count = 0
#Preparing the Plotting Environment with random starting values
#x = np.arange(10000)
#y = np.random.randn(10000)
#Raw audio data plot
#li, = ax[0].plot(x, y)
#ax[0].set_xlim(0,4000)
#ax[0].set_ylim(-20000,20000)
#ax[0].set_title("Raw Audio Signal")
#FFT plot
#li2, = ax[1].plot(x, y)
#ax[1].set_xlim(0,20000)
#ax[1].set_ylim(-50,100)
#ax[1].set_title("Fast Fourier Transform")
#Show the plot, but without blocking updates
#plt.pause(0.01)
#plt.tight_layout()
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 2048
RECORD_SECONDS = 0.1
WAVE_OUTPUT_FILENAME = "file.wav"
audio = pyaudio.PyAudio()
#Start Recording
stream = audio.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True)#,
#frames_per_buffer=CHUNK)
stream.start_stream() #Opens the connection and start streaming the data
result_herz = 0 #Making the variable visible to other class methods
pass_flag = False #Makes sure we read the first available bit after waiting for the start bit to end
timeout_flag = False #False until no more bits are received in a timespan of 5 seconds
data_flag = False #Marks the start of reading data from the channel
start_flag = False #True while the start bit is detected
listening_start = time.time() #Making both variables visible
timeout_start = time.time()
self.data_flag=False
def check_timeout(self):
timeout_end = time.time()
if (timeout_end - self.timeout_start) > 5.0:
self.timeout_flag = True
print("Listener has timed out")
print("Received {} bits".format(self.count))
def listen(self):
#For determining when to read another bit
self.listening_start = time.time()
#To determine if timeout_flag should be raised
self.timeout_start = time.time()
while not self.timeout_flag:
#to measure time spent running a cycle
#start_time = time.clock()
self.calc() #Picks up data from the microphone and calculates the frequency
self.check_timeout() #Checks if 5 seconds have passed since the last bit received
#end_time = round(time.clock() - start_time, 5)
#print(end_time)
def plot(self, audio_data, dfft):
#Plotting data, for it to function the lines of code right under the constructor should be uncommented
self.li.set_xdata(np.arange(len(audio_data)))
self.li.set_ydata(audio_data)
self.li2.set_xdata(np.arange(len(dfft))*10.)
self.li2.set_ydata(dfft)
plt.pause(0.01)
def calc(self):
input_data = self.stream.read(self.CHUNK) #Read the stream
audio_data = np.fromstring(input_data, np.int16) #Acquire and convert data to floats
dfft = 10.*np.log10(abs(np.fft.rfft(audio_data))) #FFT, 10*log10(abs) is to scale it to dB and make sure its not imaginary
fft_bin = np.fft.fftfreq(len(dfft)) #Calculating the frequencies
idx = np.argmax(np.abs(dfft)) #Finding the peak in the coefficients
fft_bin = fft_bin[idx]
self.result_herz = abs(fft_bin*self.RATE) #Final result
self.check_frequenc() #Checks frequency
#print(result_herz)
#self.plot(audio_data, dfft) #Update the graph
def check_frequenc(self):
#Asynchronous data receiving
if self.result_herz > 14900.0 and self.result_herz < 15100.0: #Checks if it is the start bit
self.data_flag = False #We don't read data from the start bit
self.start_flag = True #Signals that the start bit is active
#print("count reset")
#self.stream.stop_stream()
#self.stream.start_stream()
self.timeout_start = time.time() #Starts the timeout timer
#print("if n1")
if self.start_flag == True: #If start bit is active
#print("if n2")
if not (self.result_herz > 14900.0 and self.result_herz < 15100.0): #Checks if the start bit is still here
#print("end of start bit")
self.start_flag = False
self.data_flag = True #Allows for reading data
self.pass_flag = True #Allows for the first bit we arrive on to be instantly read, after that we read once every self.read
if self.data_flag == True:
#print("if n3")
listening_end = time.time()
if ((listening_end - self.listening_start) >= self.speed) or self.pass_flag: #Checks the timestamps
self.pass_flag = False #Turn off the pass_flag, it gets activated every 8 bits received
#print("reading")
if self.result_herz > 18700.0 and self.result_herz < 18800.0: #Check for ranges
#print("read")
self.set_data('1') #Write to self.received_data
self.timeout_start = time.time() #Reset timeout timer
self.listening_start = time.time() #Reset listening timer
if self.result_herz > 19150.0 and self.result_herz < 19250.0:
#print("read")
self.set_data('0')
self.timeout_start = time.time()
self.listening_start = time.time()
#if not self.data_flag:
#if self.result_herz > 14900.0 and self.result_herz < 15100.0:
#self.start_flag=True
#elif self.start_flag:
#self.data_flag=true
def reset_count(self): #Resets the flags and sleeps for half the interval of transmission, to land somewhere near the middle of the signal
#print("count reset")
self.start_flag = False
self.data_flag = False
time.sleep(self.speed/2.0) #Sleep ends up being called every new Byte of data, so we align ourselves on the first bit
def set_data(self, value):
if value == '1':
self.received_data = self.received_data + '1'
if value == '0':
self.received_data = self.received_data + '0'
self.count = self.count + 1
if self.count % 8 == 0: #Checks if it is time to sleeps to get in sync
self.reset_count()
def set_reading_speed(self, s):
self.speed = s #Received speed
print("Listening speed is: {}".format(self.speed))
def __del__(self): #Destructor
self.stream.stop_stream()
self.stream.close()
self.audio.terminate()
def get_data(self):
return self.received_data #Data passing
有时,我会收到RuntimeWarning:在log10中除以零, 来自第102行| dfft = 10. * np.log10(abs(np.fft.rfft(audio_data)))