Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions audio_stuff/midi/midi_piano.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,12 @@ def send_midi_note(note, velocity=127, type="note_on"):
)
button.grid(row=0, column=white_keys[i] + a * 12)

def press(event, i=i, a=a):
def press(event, button=button, i=i, a=a):
button.config(relief="sunken")
return send_midi_note(white_keys[i] + a * 12, type="note_on")

def release(event, i=i, a=a):
def release(event, button=button, i=i, a=a):
button.config(relief="raised")
return send_midi_note(white_keys[i] + a * 12, type="note_off")

button.bind("<ButtonPress-1>", press)
Expand Down
4 changes: 4 additions & 0 deletions pythonaisynth/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .main import main

if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion pythonaisynth/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = "3.1.0"
version = "3.2.0"
21 changes: 21 additions & 0 deletions pythonaisynth/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ def __init__(self, *args, manager: SyncManager = None, **kwargs):
self.graph.grid(row=1, column=0, columnspan=3, sticky="NSEW")
self.create_controll_column()
self.create_status_bar()
self.is_recording = False
# self.is_paused = False
# sys.stdout = utils.QueueSTD_OUT(self.std_queue)

# def destroy(self):
Expand Down Expand Up @@ -327,6 +329,8 @@ def create_menu(self):
("Play Music from MIDI Port", self.play_music),
("Play Music from MIDI File", self.play_music_file),
("Play Example", self.play_example),
("Record to File", self.start_recording),
("Stop Recording", self.stop_recording),
],
)

Expand Down Expand Up @@ -535,6 +539,23 @@ def play_example(self):
# path = os.path.join(os.path.dirname(__file__), "fuer_elise.py")
# subprocess.Popen(["python", path])

def start_recording(self):
if self.synth and not self.is_recording:
file_path = filedialog.asksaveasfilename(
title="Save Recording",
defaultextension=".wav",
filetypes=(("WAV files", "*.wav"), ("All files", "*.*")),
)
if file_path:
print(f"Recording will be saved to: {file_path}")
self.synth.start_recording(file_path)
self.is_recording = True

def stop_recording(self):
if self.synth and self.is_recording:
self.synth.stop_recording()
self.is_recording = False


# for "invalid command" in the tk.TK().after() function when programm gets closed
# def start_server():
Expand Down
56 changes: 50 additions & 6 deletions pythonaisynth/music.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import ctypes
import multiprocessing
import wave
import mido
import scipy
import torch
from .fourier_neural_network import FourierNN
from pythonaisynth import utils
import atexit
from multiprocessing import Process, Queue, current_process
from multiprocessing import Process, Queue, Value, current_process
import sys
from tkinter import filedialog
import numpy as np
import sounddevice as sd
import pyaudio

START = 0
STOP = 1
PAUSE = 2


def musik_from_file(fourier_nn: FourierNN):
import sounddevice as sd
Expand Down Expand Up @@ -275,7 +282,12 @@ def apply(self, sound):


class Synth2:
def __init__(self, fourier_nn, stdout: Queue = None, port_name=None):
def __init__(
self,
fourier_nn,
stdout: Queue = None,
port_name=None,
):
self.stdout = stdout
self.live_synth: Process = None
self.notes_ready = False
Expand All @@ -292,6 +304,16 @@ def __init__(self, fourier_nn, stdout: Queue = None, port_name=None):
self.t_buffer = torch.tensor(t, dtype=torch.float32)
print(self.t_buffer.shape)
self.port_name = port_name
self.command_queue = multiprocessing.Queue()

def start_recording(self, file_name):
self.command_queue.put((START, file_name))

def stop_recording(self):
self.command_queue.put((STOP,))

def pause_recording(self):
self.command_queue.put((PAUSE,))

def set_port_name(self, port_name):
self.port_name = port_name
Expand Down Expand Up @@ -350,9 +372,27 @@ def live_synth_loop(self):
notes = {}
model = self.fourier_nn.current_model.to(self.fourier_nn.device)
self.play_init_sound()
output_file = None
is_recoding = False

with mido.open_input(self.port_name) as midi_input:
while True:
if not self.command_queue.empty():
c = self.command_queue.get_nowait()
if is_recoding and not (output_file is None):
if c[0] == STOP:
output_file.close()
output_file = None
is_recoding = False
elif c[0] == PAUSE:
is_recoding = False
else:
if c[0] == START:
is_recoding = True
output_file = wave.open(c[1], "wb")
output_file.setnchannels(1) # Mono
output_file.setsampwidth(4)
output_file.setframerate(self.sample_rate)
# for _ in utils.timed_loop(True):
available_buffer = stream.get_write_available()
if available_buffer == 0:
Expand Down Expand Up @@ -423,8 +463,13 @@ def live_synth_loop(self):
audio_data = normalize(audio_data)
audio_data *= 1 # oscilating_amplitude
audio_data = np.clip(audio_data, -1, 1)
audio_data = audio_data.astype(np.float32)

if is_recoding:
output_file.writeframes(audio_data)

stream.write(
audio_data.astype(np.float32),
audio_data,
available_buffer,
exception_on_underflow=True,
)
Expand All @@ -447,10 +492,9 @@ def run_live_synth(self):
atexit.register(utils.DIE, self.live_synth, 0, 0)

def __getstate__(self) -> object:
live_synth = self.live_synth
del self.live_synth
Synth_dict = self.__dict__.copy()
self.live_synth = live_synth
del Synth_dict["live_synth"]
# del Synth_dict["command_queue"]
return Synth_dict

def __setstate__(self, state):
Expand Down
Loading