Untitled

 avatar
unknown
plain_text
2 months ago
4.6 kB
2
Indexable
import pyaudio
import wave
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
from tkinter import messagebox
import threading
import time

class SimpleDAW:
    def __init__(self, root):
        self.root = root
        self.root.title("Simple DAW")
        self.chunk = 1024  # Audio chunk size
        self.sample_rate = 44100  # Standard sample rate
        self.format = pyaudio.paInt16
        self.channels = 2  # Stereo
        self.audio = pyaudio.PyAudio()
        self.recording = False
        self.playing = False
        self.frames = []  # Store recorded audio frames
        self.audio_file = "output.wav"  # Temp file for saving recordings

        # GUI Setup
        self.setup_gui()

    def setup_gui(self):
        # Control Buttons
        self.btn_record = tk.Button(self.root, text="Record", command=self.start_recording)
        self.btn_record.pack(pady=5)

        self.btn_stop = tk.Button(self.root, text="Stop", command=self.stop)
        self.btn_stop.pack(pady=5)

        self.btn_play = tk.Button(self.root, text="Play", command=self.play_recording)
        self.btn_play.pack(pady=5)

        # Timeline (simulated with a label for now)
        self.timeline_label = tk.Label(self.root, text="Timeline: [Empty]")
        self.timeline_label.pack(pady=5)

        # Waveform Plot
        self.fig, self.ax = plt.subplots()
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
        self.canvas.get_tk_widget().pack(pady=10)

    def start_recording(self):
        if not self.recording:
            self.recording = True
            self.frames = []
            self.btn_record.config(text="Recording...")
            threading.Thread(target=self.record_audio, daemon=True).start()

    def record_audio(self):
        stream = self.audio.open(format=self.format,
                                 channels=self.channels,
                                 rate=self.sample_rate,
                                 input=True,
                                 frames_per_buffer=self.chunk)
        
        while self.recording:
            data = stream.read(self.chunk)
            self.frames.append(data)

        stream.stop_stream()
        stream.close()
        self.btn_record.config(text="Record")
        self.save_recording()

    def save_recording(self):
        wf = wave.open(self.audio_file, 'wb')
        wf.setnchannels(self.channels)
        wf.setsampwidth(self.audio.get_sample_size(self.format))
        wf.setframerate(self.sample_rate)
        wf.writeframes(b''.join(self.frames))
        wf.close()
        self.update_waveform()
        self.timeline_label.config(text=f"Timeline: {self.audio_file} [Recorded]")

    def stop(self):
        self.recording = False
        self.playing = False

    def play_recording(self):
        if not self.playing and self.frames:
            self.playing = True
            threading.Thread(target=self.play_audio, daemon=True).start()

    def play_audio(self):
        wf = wave.open(self.audio_file, 'rb')
        stream = self.audio.open(format=self.audio.get_format_from_width(wf.getsampwidth()),
                                 channels=wf.getnchannels(),
                                 rate=wf.getframerate(),
                                 output=True)
        
        data = wf.readframes(self.chunk)
        while data and self.playing:
            stream.write(data)
            data = wf.readframes(self.chunk)

        stream.stop_stream()
        stream.close()
        wf.close()
        self.playing = False

    def update_waveform(self):
        wf = wave.open(self.audio_file, 'rb')
        signal = wf.readframes(-1)
        signal = np.frombuffer(signal, dtype=np.int16)
        wf.close()

        # Normalize for visualization
        signal = signal / np.max(np.abs(signal)) if np.max(np.abs(signal)) > 0 else signal
        time_axis = np.linspace(0, len(signal) / self.sample_rate, num=len(signal))

        self.ax.clear()
        self.ax.plot(time_axis, signal)
        self.ax.set_title("Waveform")
        self.ax.set_xlabel("Time (s)")
        self.ax.set_ylabel("Amplitude")
        self.canvas.draw()

    def on_closing(self):
        self.stop()
        self.audio.terminate()
        self.root.destroy()

def main():
    root = tk.Tk()
    app = SimpleDAW(root)
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()

if __name__ == "__main__":
    main()
Editor is loading...
Leave a Comment