From ba2c5a6e39342809a14528bf1a39e1f11d545094 Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:25:31 +0000 Subject: [PATCH 1/7] create offiplayergui.py & update offitracker.py Adds a GUI for easy usage --- offiplayergui.py | 45 +++++++++++++++ offitracker.py | 144 +++++++++++++++++++++++++---------------------- 2 files changed, 122 insertions(+), 67 deletions(-) create mode 100644 offiplayergui.py diff --git a/offiplayergui.py b/offiplayergui.py new file mode 100644 index 0000000..2c76f6a --- /dev/null +++ b/offiplayergui.py @@ -0,0 +1,45 @@ +import PySimpleGUI as sg +import glob +import offitracker as offi +import sys +import csv +import numpy as np +import sounddevice as sd +import threading + +names = glob.glob("./**/*.csv", recursive=True) +toplay = "" + +layout = [[sg.Text('Search')], + [sg.Input(size=(200, 1), enable_events=True, key='-INPUT-')], + [sg.Listbox(names, size=(200, 10), enable_events=True, key='-LIST-')], + [sg.Button('Play'), sg.Button('Stop'), sg.Text("",key="file")]] + +window = sg.Window('OffiPlayer', layout,size=(480, 320)) + +def playthread(window): + offi.stop_signal = False + offi.play_csv_file(toplay) + window.write_event_value(('-THREAD-', '** DONE **'), 'Done!') + +while True: + event, values = window.read() + if event in (sg.WIN_CLOSED, 'Exit'): + break + if values['-INPUT-'] != '': + search = values['-INPUT-'] + new_values = [x for x in names if search in x] + window['-LIST-'].update(new_values) + else: + window['-LIST-'].update(names) + if event == '-LIST-' and len(values['-LIST-']): + toplay = values['-LIST-'][0] + window['file'].update(toplay) + if event == 'Play': + window.start_thread(lambda: playthread(window), ('-THREAD-', '-THEAD ENDED-')) + if event == 'Stop': + offi.stop_signal = True +window.close() + + + diff --git a/offitracker.py b/offitracker.py index ecd240f..8d27ff7 100644 --- a/offitracker.py +++ b/offitracker.py @@ -1,67 +1,77 @@ -import sys -import csv -import numpy as np -import sounddevice as sd - -# OffiTracker, the tracker that no one asked for but I made it anyways :3 -# Usage: Make a CSV table in Excel or LibreOffice with the following format: -# Frequency1 Effect1 Frequency2 Effect2 .... Noise Duration -# You can make as many channels as you want. -# Effect = pulse width from 0 to 100 -# Frequency = tone in Hz. -# Noise = noise amplitude from 0 to 10 -# Duration = tone duration in ms -# (c) 2024 mueller_minki, Feel free to modify or share. - -def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): - num_waves = len(frequencies) - t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), endpoint=False) - - # Generate and sum square waves for each frequency with corresponding effects - waves = [amplitude * (effect / 100) * np.sign(np.sin(2 * np.pi * freq * t)) for freq, effect in zip(frequencies, effects)] - - # Add optional noise channel - if noise_amplitude > 0: - noise = noise_amplitude * np.random.uniform(-1, 1, len(t)) - waves.append(noise) - - combined_wave = np.sum(waves, axis=0) - - combined_wave = combined_wave.astype(np.float32) - - output_stream.write(combined_wave) - -def play_csv_file(file_path): - with open(file_path, 'r') as csv_file: - csv_reader = csv.DictReader(csv_file) - header = csv_reader.fieldnames - num_columns = len(header) - num_pairs = (num_columns - 1) // 2 - - with sd.OutputStream(channels=1) as output_stream: - for row in csv_reader: - frequencies = [float(row[f'Frequency{i}']) for i in range(1, num_pairs + 1)] - effects = [float(row[f'Effect{i}']) for i in range(1, num_pairs + 1)] - duration = float(row['Duration']) - - # Check if 'Noise' column exists in the CSV file - noise_amplitude = float(row.get('Noise', 0)) - - play_square_waves(output_stream, frequencies, effects, duration, noise_amplitude=noise_amplitude) - -if __name__ == "__main__": - print(' ') - print(' Mueller\'s Software Domain proudly presents:') - print('________ _____ _____._____________ __ ') - print('\_____ \_/ ____\/ ____\__\__ ___/___________ ____ | | __ ___________ ') - print(' / | \ __\\\\ __\| | | | \_ __ \__ \ _/ ___\| |/ // __ \_ __ \\') - print('/ | \ | | | | | | | | | \// __ \\\\ \___| <\ ___/| | \/') - print('\_______ /__| |__| |__| |____| |__| (____ /\___ >__|_ \\\\___ >__| ') - print(' \/ \/ \/ \/ \/ ') - print(' Version 1.1') - if len(sys.argv) > 1: - csv_file_path = sys.argv[1] - else: - csv_file_path = input("Choose a CSV file: ") - play_csv_file(csv_file_path) - +import sys +import csv +import numpy as np +import sounddevice as sd +import time +# OffiTracker, the tracker that no one asked for but I made it anyways :3 +# Usage: Make a CSV table in Excel or LibreOffice with the following format: +# Frequency1 Effect1 Frequency2 Effect2 .... Noise Duration +# You can make as many channels as you want. +# Effect = pulse width from 0 to 100 +# Frequency = tone in Hz. +# Noise = noise amplitude from 0 to 10 +# Duration = tone duration in ms +# (c) 2024 mueller_minki, Feel free to modify or share. +stop_signal = False + +def stop_playback(): + stop_signal = True + +def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): + if stop_signal == True: + output_stream.stop() + pass + else: + num_waves = len(frequencies) + t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), endpoint=False) + + # Generate and sum square waves for each frequency with corresponding effects + waves = [amplitude * (effect / 100) * np.sign(np.sin(2 * np.pi * freq * t)) for freq, effect in zip(frequencies, effects)] + + # Add optional noise channel + if noise_amplitude > 0: + noise = noise_amplitude * np.random.uniform(-1, 1, len(t)) + waves.append(noise) + + combined_wave = np.sum(waves, axis=0) + + combined_wave = combined_wave.astype(np.float32) + + output_stream.write(combined_wave) + +def play_csv_file(file_path): + stop_signal = False + + with open(file_path, 'r') as csv_file: + csv_reader = csv.DictReader(csv_file) + header = csv_reader.fieldnames + num_columns = len(header) + num_pairs = (num_columns - 1) // 2 + + with sd.OutputStream(channels=1) as output_stream: + for row in csv_reader: + frequencies = [float(row[f'Frequency{i}']) for i in range(1, num_pairs + 1)] + effects = [float(row[f'Effect{i}']) for i in range(1, num_pairs + 1)] + duration = float(row['Duration']) + + # Check if 'Noise' column exists in the CSV file + noise_amplitude = float(row.get('Noise', 0)) + if stop_signal == False: + play_square_waves(output_stream, frequencies, effects, duration, noise_amplitude=noise_amplitude) + +if __name__ == "__main__": + print(' ') + print(' Mueller\'s Software Domain proudly presents:') + print('________ _____ _____._____________ __ ') + print('\_____ \_/ ____\/ ____\__\__ ___/___________ ____ | | __ ___________ ') + print(' / | \ __\\\\ __\| | | | \_ __ \__ \ _/ ___\| |/ // __ \_ __ \\') + print('/ | \ | | | | | | | | | \// __ \\\\ \___| <\ ___/| | \/') + print('\_______ /__| |__| |__| |____| |__| (____ /\___ >__|_ \\\\___ >__| ') + print(' \/ \/ \/ \/ \/ ') + print(' Version 1.1') + if len(sys.argv) > 1: + csv_file_path = sys.argv[1] + else: + csv_file_path = input("Choose a CSV file: ") + play_csv_file(csv_file_path) + -- 2.25.1 From 0aa15b600c4b430bc09d67315e64e0e5bf9a08dd Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:29:30 +0000 Subject: [PATCH 2/7] offitracker.py aktualisiert --- offitracker.py | 154 ++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/offitracker.py b/offitracker.py index 8d27ff7..3ecd8ce 100644 --- a/offitracker.py +++ b/offitracker.py @@ -1,77 +1,77 @@ -import sys -import csv -import numpy as np -import sounddevice as sd -import time -# OffiTracker, the tracker that no one asked for but I made it anyways :3 -# Usage: Make a CSV table in Excel or LibreOffice with the following format: -# Frequency1 Effect1 Frequency2 Effect2 .... Noise Duration -# You can make as many channels as you want. -# Effect = pulse width from 0 to 100 -# Frequency = tone in Hz. -# Noise = noise amplitude from 0 to 10 -# Duration = tone duration in ms -# (c) 2024 mueller_minki, Feel free to modify or share. -stop_signal = False - -def stop_playback(): - stop_signal = True - -def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): - if stop_signal == True: - output_stream.stop() - pass - else: - num_waves = len(frequencies) - t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), endpoint=False) - - # Generate and sum square waves for each frequency with corresponding effects - waves = [amplitude * (effect / 100) * np.sign(np.sin(2 * np.pi * freq * t)) for freq, effect in zip(frequencies, effects)] - - # Add optional noise channel - if noise_amplitude > 0: - noise = noise_amplitude * np.random.uniform(-1, 1, len(t)) - waves.append(noise) - - combined_wave = np.sum(waves, axis=0) - - combined_wave = combined_wave.astype(np.float32) - - output_stream.write(combined_wave) - -def play_csv_file(file_path): - stop_signal = False - - with open(file_path, 'r') as csv_file: - csv_reader = csv.DictReader(csv_file) - header = csv_reader.fieldnames - num_columns = len(header) - num_pairs = (num_columns - 1) // 2 - - with sd.OutputStream(channels=1) as output_stream: - for row in csv_reader: - frequencies = [float(row[f'Frequency{i}']) for i in range(1, num_pairs + 1)] - effects = [float(row[f'Effect{i}']) for i in range(1, num_pairs + 1)] - duration = float(row['Duration']) - - # Check if 'Noise' column exists in the CSV file - noise_amplitude = float(row.get('Noise', 0)) - if stop_signal == False: - play_square_waves(output_stream, frequencies, effects, duration, noise_amplitude=noise_amplitude) - -if __name__ == "__main__": - print(' ') - print(' Mueller\'s Software Domain proudly presents:') - print('________ _____ _____._____________ __ ') - print('\_____ \_/ ____\/ ____\__\__ ___/___________ ____ | | __ ___________ ') - print(' / | \ __\\\\ __\| | | | \_ __ \__ \ _/ ___\| |/ // __ \_ __ \\') - print('/ | \ | | | | | | | | | \// __ \\\\ \___| <\ ___/| | \/') - print('\_______ /__| |__| |__| |____| |__| (____ /\___ >__|_ \\\\___ >__| ') - print(' \/ \/ \/ \/ \/ ') - print(' Version 1.1') - if len(sys.argv) > 1: - csv_file_path = sys.argv[1] - else: - csv_file_path = input("Choose a CSV file: ") - play_csv_file(csv_file_path) - +import sys +import csv +import numpy as np +import sounddevice as sd +import time +# OffiTracker, the tracker that no one asked for but I made it anyways :3 +# Usage: Make a CSV table in Excel or LibreOffice with the following format: +# Frequency1 Effect1 Frequency2 Effect2 .... Noise Duration +# You can make as many channels as you want. +# Effect = pulse width from 0 to 100 +# Frequency = tone in Hz. +# Noise = noise amplitude from 0 to 10 +# Duration = tone duration in ms +# (c) 2024 mueller_minki, Feel free to modify or share. +stop_signal = False + +def stop_playback(): + stop_signal = True + +def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): + if stop_signal == True: + output_stream.stop() + pass + else: + num_waves = len(frequencies) + t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), endpoint=False) + + # Generate and sum square waves for each frequency with corresponding effects + waves = [amplitude * (effect / 100) * np.sign(np.sin(2 * np.pi * freq * t)) for freq, effect in zip(frequencies, effects)] + + # Add optional noise channel + if noise_amplitude > 0: + noise = noise_amplitude * np.random.uniform(-1, 1, len(t)) + waves.append(noise) + + combined_wave = np.sum(waves, axis=0) + + combined_wave = combined_wave.astype(np.float32) + + output_stream.write(combined_wave) + +def play_csv_file(file_path): + stop_signal = False + + with open(file_path, 'r') as csv_file: + csv_reader = csv.DictReader(csv_file) + header = csv_reader.fieldnames + num_columns = len(header) + num_pairs = (num_columns - 1) // 2 + + with sd.OutputStream(channels=1) as output_stream: + for row in csv_reader: + frequencies = [float(row[f'Frequency{i}']) for i in range(1, num_pairs + 1)] + effects = [float(row[f'Effect{i}']) for i in range(1, num_pairs + 1)] + duration = float(row['Duration']) + + # Check if 'Noise' column exists in the CSV file + noise_amplitude = float(row.get('Noise', 0)) + if stop_signal == False: + play_square_waves(output_stream, frequencies, effects, duration, noise_amplitude=noise_amplitude) + +if __name__ == "__main__": + print(' ') + print(' Mueller\'s Software Domain proudly presents:') + print('________ _____ _____._____________ __ ') + print('\_____ \_/ ____\/ ____\__\__ ___/___________ ____ | | __ ___________ ') + print(' / | \ __\\\\ __\| | | | \_ __ \__ \ _/ ___\| |/ // __ \_ __ \\') + print('/ | \ | | | | | | | | | \// __ \\\\ \___| <\ ___/| | \/') + print('\_______ /__| |__| |__| |____| |__| (____ /\___ >__|_ \\\\___ >__| ') + print(' \/ \/ \/ \/ \/ ') + print(' Version 1.2') + if len(sys.argv) > 1: + csv_file_path = sys.argv[1] + else: + csv_file_path = input("Choose a CSV file: ") + play_csv_file(csv_file_path) + -- 2.25.1 From df56cf37d4b0be55f6079a02801beb34673be17c Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:31:33 +0000 Subject: [PATCH 3/7] README.md aktualisiert --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 06df4ea..66797f9 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ Assuming `python3` is already installed, you can use the following command to in pip3 install csv numpy sounddevice ``` +If you need the GUI, additionally install PySimpleGui + +```bash +pip3 install PySimpleGui +``` + After that, simply run `python3 offitracker.py` and enjoy. The command can also take a path to a file as a parameter if you wish to use your shells autocompletion. ____ -- 2.25.1 From f6d730cd0015ed668d460abdf25b60a7db3be4f5 Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:31:59 +0000 Subject: [PATCH 4/7] README.md aktualisiert --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66797f9..50d4fb4 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Assuming `python3` is already installed, you can use the following command to in pip3 install csv numpy sounddevice ``` -If you need the GUI, additionally install PySimpleGui +If you need the GUI, additionally install PySimpleGui: ```bash pip3 install PySimpleGui -- 2.25.1 From d359f5e4ba06aeb959ed71821125e8b58d7700c6 Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:33:14 +0000 Subject: [PATCH 5/7] offitracker.py aktualisiert --- offitracker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/offitracker.py b/offitracker.py index 3ecd8ce..3e1c44b 100644 --- a/offitracker.py +++ b/offitracker.py @@ -2,7 +2,7 @@ import sys import csv import numpy as np import sounddevice as sd -import time + # OffiTracker, the tracker that no one asked for but I made it anyways :3 # Usage: Make a CSV table in Excel or LibreOffice with the following format: # Frequency1 Effect1 Frequency2 Effect2 .... Noise Duration -- 2.25.1 From 478ad98720b026d4a8a481d4fd68da8c11abb72e Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:33:37 +0000 Subject: [PATCH 6/7] offitracker.py aktualisiert --- offitracker.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/offitracker.py b/offitracker.py index 3e1c44b..3013212 100644 --- a/offitracker.py +++ b/offitracker.py @@ -14,9 +14,6 @@ import sounddevice as sd # (c) 2024 mueller_minki, Feel free to modify or share. stop_signal = False -def stop_playback(): - stop_signal = True - def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): if stop_signal == True: output_stream.stop() -- 2.25.1 From f81956bed760ed24f3048bb42efef07c662dcf02 Mon Sep 17 00:00:00 2001 From: Emanulator Date: Tue, 2 Jan 2024 20:36:28 +0000 Subject: [PATCH 7/7] offitracker.py aktualisiert --- offitracker.py | 1 - 1 file changed, 1 deletion(-) diff --git a/offitracker.py b/offitracker.py index 3013212..ba8190c 100644 --- a/offitracker.py +++ b/offitracker.py @@ -17,7 +17,6 @@ stop_signal = False def play_square_waves(output_stream, frequencies, effects, duration, amplitude=1, noise_amplitude=0, sample_rate=44100): if stop_signal == True: output_stream.stop() - pass else: num_waves = len(frequencies) t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), endpoint=False) -- 2.25.1