Untitled

 avatar
unknown
plain_text
15 days ago
4.2 kB
0
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()
Leave a Comment