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)