Untitled
unknown
plain_text
a year ago
4.2 kB
4
Indexable
import tkinter as tk
from tkinter import ttk
import numpy as np
import sounddevice as sd
import threading
class ToneGenerator:
def __init__(self):
self.sample_rate = 44100
self.frequency = 200 # Default frequency in Hz
self.phase_shift = 0 # Phase shift in radians
self.is_playing = False
self.stream = None
def generate_tone(self):
def callback(outdata, frames, time, status):
t = (np.arange(frames) + self.sample_rate * time.inputBufferAdcTime) / self.sample_rate
tone = np.sin(2 * np.pi * self.frequency * t + self.phase_shift)
outdata[:, 0] = tone
with sd.OutputStream(callback=callback, samplerate=self.sample_rate, channels=1):
while self.is_playing:
sd.sleep(100)
def start(self):
if not self.is_playing:
self.is_playing = True
self.stream = threading.Thread(target=self.generate_tone)
self.stream.start()
def stop(self):
if self.is_playing:
self.is_playing = False
if self.stream is not None:
self.stream.join()
self.stream = None
def set_frequency(self, freq):
self.frequency = freq
def set_phase_shift(self, shift):
self.phase_shift = shift
def main():
generator = ToneGenerator()
def start_stop_tone():
if generator.is_playing:
generator.stop()
start_button.config(text="Включить")
else:
generator.start()
start_button.config(text="Выключить")
def update_frequency(val):
generator.set_frequency(float(val))
freq_label.config(text=f"Частота: {float(val):.1f} Hz")
def update_phase(val):
generator.set_phase_shift(float(val))
phase_label.config(text=f"Фаза: {float(val):.2f} радиан")
def increment_frequency():
freq = frequency_slider.get() + 0.5
frequency_slider.set(freq)
update_frequency(freq)
def decrement_frequency():
freq = frequency_slider.get() - 0.5
frequency_slider.set(freq)
update_frequency(freq)
root = tk.Tk()
root.title("Генератор звукового тона")
frame = ttk.Frame(root, padding=10)
frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
start_button = ttk.Button(frame, text="Включить", command=start_stop_tone)
start_button.grid(row=0, column=0, pady=10, sticky=(tk.W, tk.E))
freq_label = ttk.Label(frame, text=f"Частота: {generator.frequency} Hz")
freq_label.grid(row=1, column=0, pady=10, sticky=(tk.W, tk.E))
frequency_slider = ttk.Scale(frame, from_=100, to=300, orient="horizontal", command=update_frequency)
frequency_slider.set(generator.frequency)
frequency_slider.grid(row=2, column=0, pady=10, sticky=(tk.W, tk.E))
freq_buttons = ttk.Frame(frame)
freq_buttons.grid(row=3, column=0, pady=5, sticky=(tk.W, tk.E))
freq_buttons.columnconfigure(0, weight=1)
freq_buttons.columnconfigure(1, weight=1)
freq_down_button = ttk.Button(freq_buttons, text="-", command=decrement_frequency)
freq_down_button.grid(row=0, column=0, padx=5, sticky=(tk.W, tk.E))
freq_up_button = ttk.Button(freq_buttons, text="+", command=increment_frequency)
freq_up_button.grid(row=0, column=1, padx=5, sticky=(tk.W, tk.E))
phase_label = ttk.Label(frame, text=f"Фаза: {generator.phase_shift:.2f} радиан")
phase_label.grid(row=4, column=0, pady=10, sticky=(tk.W, tk.E))
phase_slider = ttk.Scale(frame, from_=-np.pi, to=np.pi, orient="horizontal", command=update_phase)
phase_slider.set(generator.phase_shift)
phase_slider.grid(row=5, column=0, pady=10, sticky=(tk.W, tk.E))
def resize_ui(event):
frame.config(padding=max(10, event.width // 50))
start_button.config(width=max(10, event.width // 20))
root.bind("<Configure>", resize_ui)
root.mainloop()
generator.stop()
if __name__ == "__main__":
main()
Editor is loading...
Leave a Comment