diff options
author | David Doan <daviddoan@Davids-MacBook-Pro-193.local> | 2023-12-14 21:40:35 -0500 |
---|---|---|
committer | David Doan <daviddoan@Davids-MacBook-Pro-193.local> | 2023-12-14 21:40:35 -0500 |
commit | d7384329b2ae615ef7d637e31f214dbe648ae418 (patch) | |
tree | 7f0fb02210a2da8b820372f5ea3a78041f390433 /utils.py | |
parent | 0fef1fc043bddbcaf467d1f35027bde60326e227 (diff) | |
parent | b66e659ba40b84dbf75e09d5463e2aef1a39b718 (diff) |
pull
Diffstat (limited to 'utils.py')
-rw-r--r-- | utils.py | 138 |
1 files changed, 47 insertions, 91 deletions
@@ -3,10 +3,41 @@ # 1875 1924 +24, -25, range/2, 1, flipping new info 2 sending or not import numpy as np import pyaudio -import struct +import threading from scipy.fftpack import fft +def wave_to_bits(wave, starting_freq, freq_range, bytes_per_transmit, chunk=4096, rate=44100): + spectrum = fft(wave) + spectrum = np.abs(spectrum) + spectrum = spectrum / (np.linalg.norm(spectrum) + 1e-16) + + # FIXME: update to self values, given if ur a sender or receiver + starting_freq = starting_freq + end_freq = starting_freq + freq_range + freq_to_index_ratio = (chunk - 1) / rate + + # only accept the scaled spectrum from our starting range to 20000 Hz + starting_range_index = int(starting_freq * freq_to_index_ratio) + ending_range_index = int(end_freq * freq_to_index_ratio) + restricted_spectrum = spectrum[starting_range_index:ending_range_index + 1] + + # get the n indices of the max peaks of amplitude greater than .125, within our confined spectrum + indices = np.argwhere(restricted_spectrum > .125) + + freqs = [int((indices[i] + starting_range_index) / freq_to_index_ratio) for i in range(len(indices))] + + # convert the frequencies to bits + data = frequencies_to_bits(freqs, calculate_send_frequencies(starting_freq, freq_range, bytes_per_transmit)) + + # TODO: remove + byte = data[:8] + if data[-1] == '1': + receive_string(byte) + + return data + + def calculate_send_frequencies(start_freq, freq_range, bytes_per_transmit): bits_to_send = 8 * bytes_per_transmit + 2 # 8 bits per byte, 2 bits for flags freq_interval = freq_range / (bits_to_send + 1) # +1 to not include endpoints of range @@ -16,66 +47,46 @@ def calculate_send_frequencies(start_freq, freq_range, bytes_per_transmit): f = int(start_freq + (i + 1) * freq_interval) freq_list.append(f) - # print(freq_list) - return freq_list -def frequencies_to_bytes(frequencies, expected_freqs): +def frequencies_to_bits(frequencies, expected_freqs): # get the interval between frequencies, so we can clamp the range around them freq_interval = expected_freqs[1] - expected_freqs[0] plus_minus = freq_interval // 2 - byte_list = ['0'] * len(expected_freqs) + bit_list = ['0'] * len(expected_freqs) for freq in frequencies: for i in range(len(expected_freqs)): # clamp the range around the frequency to the frequency if expected_freqs[i] - plus_minus <= freq < expected_freqs[i] + plus_minus: - byte_list[i] = '1' + bit_list[i] = '1' - return byte_list + return bit_list -def play_data(data, start_freq, freq_step, bytes_per_transmit, p): + +def play_data(data, start_freq, freq_step, bytes_per_transmit, stream): freq_list = calculate_send_frequencies(start_freq, freq_step, bytes_per_transmit) + send_duration = 1.0 + + flip_flag = 0 # TODO: make this global between plays for byte in data: - # print(byte) + byte = byte + str(flip_flag) + '1' + print(byte) samples = None for i, bit in enumerate(byte): if bit == '1': - # print(freq_list[i]) - s = .125 * np.sin(2 * np.pi * np.arange(44100 * 10.0) * freq_list[i] / 44100) + print(freq_list[i]) + s = .125 * np.sin(2 * np.pi * np.arange(44100 * send_duration) * freq_list[i] / 44100) if samples is None: samples = s else: samples = np.add(samples, s) if samples is not None: - # print(samples) - stream = p.open(format=pyaudio.paFloat32, channels=1, rate=44100, output=True) stream.write(samples.astype(np.float32).tobytes()) - stream.stop_stream() - stream.close() - # listening_stream = p.open( - # format=pyaudio.paInt32, - # channels=1, - # rate=44100, - # input=True, - # output=True, - # frames_per_buffer=2048 * 2, - # ) - # if receive_data(listening_stream, start_freq, freq_step, bytes_per_transmit): - # print("Success") - -""" -:param data: A string of characters. -:return: A list of binary strings. -""" -def string_to_binary(data): - data_list = [] - for char in data: - binary_representation = format(ord(char), 'b').zfill(8) - data_list.append(binary_representation) - return data_list + flip_flag = (flip_flag + 1) % 2 + def receive_string(binary): binary_string = ''.join(binary) @@ -84,58 +95,3 @@ def receive_string(binary): return chr(int(binary_string, 2)) except ValueError: print("Error: Invalid binary data") - -CHUNK = 2048 * 2 -RATE = 44100 - -def read_audio_stream(stream): - data = stream.read(CHUNK) - data_int = struct.unpack(str(CHUNK) + 'i', data) - return data_int - -def get_fundamental_frequency(audio_waveform, start_freq, freq_step, bytes_per_transmit): - spectrum = fft(audio_waveform) - - # scale and normalize the spectrum, some are imaginary - scaled_spectrum = np.abs(spectrum) - scaled_spectrum = scaled_spectrum / (np.linalg.norm(scaled_spectrum) + 1e-16) - - # FIXME: update to self values, given if ur a sender or receiver - starting_freq = 19800 - end_freq = 20000 - freq_to_index_ratio = CHUNK / RATE - # only accept the scaled spectrum from our starting range to 20000 Hz - starting_range_index = int(starting_freq * freq_to_index_ratio) - ending_range_index = int(end_freq * freq_to_index_ratio) - # print(starting_freq, end_freq, starting_range_index, ending_range_index) - restricted_spectrum = scaled_spectrum[starting_range_index:ending_range_index + 1] - - # normalize the restricted spectrum - indices = np.argwhere(restricted_spectrum > .125) - # print(indices) - - freqs = [int((indices[i] + starting_range_index) / freq_to_index_ratio) for i in range(len(indices))] - # print(freqs) - - p = frequencies_to_bytes(freqs, calculate_send_frequencies(start_freq, freq_step, bytes_per_transmit)) - data = p[:8] - # print(data) - data = receive_string(data) - return data - - -def receive_data(stream, start_freq, freq_step, bytes_per_transmit): - # freq_list = calculate_send_frequencies(start_freq, freq_step, bytes_per_transmit) - - data = [] - while not data: - waveform = read_audio_stream(stream) - freqs = get_fundamental_frequency(waveform, start_freq, freq_step, bytes_per_transmit) - data.append(freqs) - - - # if we see the same data twice in a row, we stop receiving - # if data[-1] == data[-2]: - # break - # print(data) - return data[0], True |