From b768132d19514da4270b82544f5eea236f966823 Mon Sep 17 00:00:00 2001 From: antonxy Date: Fri, 18 Apr 2014 15:30:36 +0200 Subject: [PATCH] fsk instead of psk --- analyse_audio.py | 96 ++++++++++++------------------- program_logic.py | 2 +- tests/bfsk_test.py | 94 ++++++++++++++++++++++++++++++ tests/bpsk_test.py | 140 --------------------------------------------- 4 files changed, 132 insertions(+), 200 deletions(-) create mode 100644 tests/bfsk_test.py delete mode 100644 tests/bpsk_test.py diff --git a/analyse_audio.py b/analyse_audio.py index fd60e5b..e4a8301 100644 --- a/analyse_audio.py +++ b/analyse_audio.py @@ -21,74 +21,52 @@ def find_signal(data, freq, sr): th = np.amax(mul)/2 return np.argmax(np.greater(mul, th)) -if False: - def decode_signal(data, chunk_length, frequency, signal_start, sample_rate, num_bits): - """ - decodes the n byte BPSK-signal in the audio data - """ - max_arg = int(frequency * chunk_length * 2 * np.pi) - one_chunk = np.sin(np.linspace(0, max_arg, chunk_length * sample_rate)) - - chunk_samples = int(sample_rate * chunk_length) - decoded_data = [] - - for delta_n in range(signal_start, signal_start + chunk_samples * (num_bits + 1), chunk_samples): - if delta_n + chunk_samples > data.size: - break - - current_chunk = data[delta_n:delta_n + chunk_samples] - prod = np.multiply(current_chunk, one_chunk) - s = np.sum(prod) - decoded_data.append(1 if s > 0 else 0) - - return decoded_data[1:] -else: - - def decode_signal(data, chunk_length, frequency, signal_start, sample_rate, num_bits): - """ - decodes the n byte BPSK-signal in the audio data - """ - chunk_samples = int(sample_rate * chunk_length) - decoded_data = [] - last_chunk = None - last_bit = 0 - # Read n bytes + start bit - for delta_n in range(signal_start, signal_start + chunk_samples * (num_bits + 1), chunk_samples): - if delta_n + chunk_samples > data.size: - break - - current_chunk = data[delta_n:delta_n + chunk_samples] - if last_chunk is not None: - prod = np.multiply(current_chunk, last_chunk) - s = np.sum(prod) - - #Switch bit if s < 0; s < 0 means phase change - if s < 0: - if last_bit < 1: - last_bit = 1 - else: - last_bit = 0 - decoded_data.append(last_bit) - - last_chunk = current_chunk - return decoded_data - - -def find_and_decode_signal(data, sample_rate, chunk_length, frequency, chirp_f0, chirp_f1, chirp_duration): + +def decode_signal(data, chunk_length, f0, f1, signal_start, sample_rate, num_bits): + """ + decodes the n byte BPSK-signal in the audio data + """ + chunk_samples = int(sample_rate * chunk_length) + decoded_data = np.array([]) + + max_arg_0 = int(f0 * chunk_length * 2 * np.pi) + max_arg_1 = int(f1 * chunk_length * 2 * np.pi) + + zero_chunk = np.exp(1j * np.linspace(0, max_arg_0, chunk_samples)) + one_chunk = np.exp(1j * np.linspace(0, max_arg_1, chunk_samples)) + + # Read n bytes + start bit + for delta_n in range(signal_start, signal_start + chunk_samples * (num_bits + 1), chunk_samples): + if delta_n + chunk_samples > data.size: + break + + current_chunk = data[delta_n:delta_n + chunk_samples] + prod0 = np.multiply(current_chunk, zero_chunk) + s0 = np.sum(prod0) + + prod1 = np.multiply(current_chunk, one_chunk) + s1 = np.sum(prod1) + + decoded_data = np.append(decoded_data, np.abs(s1) > np.abs(s0)) + return decoded_data.astype(int) + + +def find_and_decode_signal(data, sample_rate, chunk_length, frequency0, frequency1, chirp_f0, chirp_f1, chirp_duration): """ returns: signal start, decoded bytes """ signal_start = find_sync_signal(data, sample_rate, generate_chirp(chirp_f0, chirp_f1, chirp_duration, sample_rate)) - decoded_data = bits_to_bytes(decode_signal(data, chunk_length, frequency, signal_start, sample_rate, 32)) + decoded_data = bits_to_bytes(decode_signal(data, chunk_length, frequency0, frequency1, signal_start, sample_rate, 32)) return signal_start, decoded_data -def generate_signal(bits, chunk_length, sample_rate, frequency): +def generate_signal(bits, chunk_length, sample_rate, f0, f1): #max_arg = int(frequency * chunk_length / sample_rate * 2 * np.pi) - max_arg = int(frequency * chunk_length * 2 * np.pi) + max_arg_0 = int(f0 * chunk_length * 2 * np.pi) + max_arg_1 = int(f1 * chunk_length * 2 * np.pi) - zero_chunk = np.sin(np.linspace(0 + np.pi, max_arg + np.pi, chunk_length * sample_rate)) - one_chunk = np.sin(np.linspace(0, max_arg, chunk_length * sample_rate)) + zero_chunk = np.sin(np.linspace(0, max_arg_0, chunk_length * sample_rate)) + one_chunk = np.sin(np.linspace(0, max_arg_1, chunk_length * sample_rate)) data = np.zeros(0) diff --git a/program_logic.py b/program_logic.py index 1af9e1a..80c9886 100644 --- a/program_logic.py +++ b/program_logic.py @@ -11,7 +11,7 @@ def analyse_file(path): return length = audio.size - sync_point, data = analyse_audio.find_and_decode_signal(audio, sr, 0.02, 4000, 3000, 6000, 0.2) + sync_point, data = analyse_audio.find_and_decode_signal(audio, sr, 0.02, 5500, 6000, 3000, 6000, 0.2) valid = analyse_audio.check_checksum(data) print('path {} analysed'.format(path)) diff --git a/tests/bfsk_test.py b/tests/bfsk_test.py new file mode 100644 index 0000000..ea4d8d6 --- /dev/null +++ b/tests/bfsk_test.py @@ -0,0 +1,94 @@ +import analyse_audio +import numpy as np +import matplotlib.pyplot as plt + + +def bfsk_single_test(chunk_length, f0, f1, noise_factor=0, shift_error=0): + bits = np.random.choice([0, 1], 32) + signal = analyse_audio.generate_signal(bits, chunk_length, 48000, f0, f1) + shift_signal = np.zeros(shift_error) + signal = np.append(shift_signal, signal) + if noise_factor != 0: + noise = np.random.random(signal.size) * noise_factor + noised_signal = np.add(signal, noise) + else: + noised_signal = signal + + decoded_bits = analyse_audio.decode_signal(noised_signal, chunk_length, f0, f1, 0, 48000, len(bits)) + if len(bits) != len(decoded_bits): + return False + return (bits == np.array(decoded_bits)).all() + + +def bfsk_noise_test(): + n = 200 + chunk_length = 0.01 + f0, f1 = 3000, 6000 + noise_level_list = [] + success_list = [] + for noise_factor in np.linspace(0, 30, 20): + success_ratio = 0 + for i in range(n): + if bfsk_single_test(chunk_length, f0, f1, noise_factor=noise_factor): + success_ratio += 1 / n + noise_level_list.append(noise_factor) + success_list.append(success_ratio) + + print('{} Successes at noise level {}'.format(success_ratio, noise_factor)) + + plt.plot(noise_level_list, success_list, 'bo-') + plt.title('Trials per value: {}, Chunk length: {}, f0: {}, f1: {}'.format(n, chunk_length, f0, f1)) + plt.ylabel('Success ratio') + plt.xlabel('Noise level') + plt.show() + + +def bfsk_chunk_length_test(): + n = 50 + noise_level = 10 + f0, f1 = 3000, 6000 + chunk_length_list = [] + success_list = [] + for chunk_length in np.logspace(-4, -1.9, 20): + success_ratio = 0 + for i in range(n): + if bfsk_single_test(chunk_length, f0, f1, noise_factor=noise_level): + success_ratio += 1 / n + chunk_length_list.append(chunk_length) + success_list.append(success_ratio) + + print('{} Successes at length {}'.format(success_ratio, chunk_length)) + + plt.plot(chunk_length_list, success_list, 'bo-') + plt.title('Trials per value: {}, Noise level: {}, f0: {}, f1: {}'.format(n, noise_level, f0, f1)) + plt.ylabel('Success ratio') + plt.xlabel('Chunk length [s]') + plt.show() + + +def bfsk_shift_error_test(): + n = 50 + noise_level = 2 + chunk_length = 0.01 + f0, f1 = 3000, 6000 + shift_error_list = [] + success_list = [] + for shift_error in np.logspace(1, 3, 20): + success_ratio = 0 + for i in range(n): + if bfsk_single_test(chunk_length, f0, f1, noise_factor=noise_level, shift_error=shift_error): + success_ratio += 1 / n + shift_error_list.append(shift_error) + success_list.append(success_ratio) + + print('{} Successes at Shift Error {}'.format(success_ratio, shift_error)) + + plt.plot(shift_error_list, success_list, 'bo-') + plt.title('Trials per value: {}, Noise level: {}, Chunk length: {}, f0: {}, f1: {}'. + format(n, noise_level, chunk_length, f0, f1)) + plt.ylabel('Success ratio') + plt.xlabel('Shift error [samples]') + plt.show() + +if __name__ == '__main__': + bfsk_shift_error_test() \ No newline at end of file diff --git a/tests/bpsk_test.py b/tests/bpsk_test.py deleted file mode 100644 index 0c7e5ef..0000000 --- a/tests/bpsk_test.py +++ /dev/null @@ -1,140 +0,0 @@ -import analyse_audio -import numpy as np -import matplotlib.pyplot as plt - - -def bpsk_single_test(chunk_length, frequency, noise_factor=0, frequency_error=0, shift_error=0): - bits = np.random.choice([0, 1], 32) - signal = analyse_audio.generate_signal(np.append([0], bits), chunk_length, 48000, frequency + frequency_error) - shift_signal = np.zeros(shift_error) - signal = np.append(shift_signal, signal) - if noise_factor != 0: - noise = np.random.random(signal.size) * noise_factor - noised_signal = np.add(signal, noise) - else: - noised_signal = signal - - decoded_bits = analyse_audio.decode_signal(noised_signal, chunk_length, frequency, 0, 48000, len(bits)) - return (bits == np.array(decoded_bits)).all() - - -def bpsk_noise_test(): - n = 200 - chunk_length = 0.01 - frequency = 1000 - noise_level_list = [] - success_list = [] - for noise_factor in np.linspace(0, 5, 20): - success_ratio = 0 - for i in range(n): - if bpsk_single_test(chunk_length, frequency, noise_factor): - success_ratio += 1 / n - noise_level_list.append(noise_factor) - success_list.append(success_ratio) - - print('{} Successes at noise level {}'.format(success_ratio, noise_factor)) - - plt.plot(noise_level_list, success_list, 'bo-') - plt.title('Trials per value: {}, Chunk length: {}, Frequency: {}'.format(n, chunk_length, frequency)) - plt.ylabel('Success ratio') - plt.xlabel('Noise level') - plt.show() - - -def bpsk_chunk_length_test(): - n = 50 - noise_level = 10 - frequency = 6000 - chunk_length_list = [] - success_list = [] - for chunk_length in np.logspace(-4, -1.9, 20): - success_ratio = 0 - for i in range(n): - if bpsk_single_test(chunk_length, frequency, noise_level): - success_ratio += 1 / n - chunk_length_list.append(chunk_length) - success_list.append(success_ratio) - - print('{} Successes at length {}'.format(success_ratio, chunk_length)) - - plt.plot(chunk_length_list, success_list, 'bo-') - plt.title('Trials per value: {}, Noise level: {}, Frequency: {}'.format(n, noise_level, frequency)) - plt.ylabel('Success ratio') - plt.xlabel('Chunk length [s]') - plt.show() - - -def bpsk_frequency_test(): - n = 50 - noise_level = 20 - chunk_length = 0.01 - freq_list = [] - success_list = [] - for freq in np.logspace(1, 4.5, 50): - success_ratio = 0 - for i in range(n): - if bpsk_single_test(chunk_length, freq, noise_level): - success_ratio += 1 / n - freq_list.append(freq) - success_list.append(success_ratio) - - print('{} Successes at Frequency {}'.format(success_ratio, freq)) - - plt.plot(freq_list, success_list, 'bo-') - plt.title('Trials per value: {}, Noise level: {}, Chunk length: {}'.format(n, noise_level, chunk_length)) - plt.ylabel('Success ratio') - plt.xlabel('Frequency [Hz]') - plt.show() - - -def bpsk_frequency_error_test(): - n = 50 - noise_level = 2 - chunk_length = 0.01 - freq = 6000 - freq_error_list = [] - success_list = [] - for freq_error in np.logspace(0, 2.5, 20): - success_ratio = 0 - for i in range(n): - if bpsk_single_test(chunk_length, freq, noise_level, freq_error): - success_ratio += 1 / n - freq_error_list.append(freq_error) - success_list.append(success_ratio) - - print('{} Successes at Frequency Error {}'.format(success_ratio, freq_error)) - - plt.plot(freq_error_list, success_list, 'bo-') - plt.title('Trials per value: {}, Noise level: {}, Chunk length: {}, Freq: {}'. - format(n, noise_level, chunk_length, freq)) - plt.ylabel('Success ratio') - plt.xlabel('Frequency error [Hz]') - plt.show() - - -def bpsk_shift_error_test(): - n = 50 - noise_level = 2 - chunk_length = 0.01 - freq = 1000 - shift_error_list = [] - success_list = [] - for shift_error in np.logspace(0, 2, 20): - success_ratio = 0 - for i in range(n): - if bpsk_single_test(chunk_length, freq, noise_level, shift_error=shift_error): - success_ratio += 1 / n - shift_error_list.append(shift_error) - success_list.append(success_ratio) - - print('{} Successes at Shift Error {}'.format(success_ratio, shift_error)) - - plt.plot(shift_error_list, success_list, 'bo-') - plt.title('Trials per value: {}, Noise level: {}, Chunk length: {}, Freq: {}'. - format(n, noise_level, chunk_length, freq)) - plt.ylabel('Success ratio') - plt.xlabel('Shift error [samples]') - plt.show() - -if __name__ == '__main__': - bpsk_noise_test() \ No newline at end of file