Spaces:
Runtime error
Runtime error
import mido | |
mido.set_backend('mido.backends.pygame') | |
from mido import Message, MidiFile, MidiTrack | |
import time | |
import pynput | |
import sys | |
sys.path.append('../../') | |
from src.music.config import SYNTH_RECORDED_MIDI_PATH | |
from datetime import datetime | |
#TODO: debug this with other cable, keyboard and sound card | |
global KEY_PRESSED | |
KEY_PRESSED = None | |
def on_press(key): | |
global KEY_PRESSED | |
try: | |
KEY_PRESSED = key.name | |
except: | |
pass | |
def on_release(key): | |
global KEY_PRESSED | |
KEY_PRESSED = None | |
def is_pressed(key): | |
global KEY_PRESSED | |
return KEY_PRESSED == key | |
# keyboard listener | |
listener = pynput.keyboard.Listener(on_press=on_press, on_release=on_release) | |
listener.start() | |
LEN_MIDI_RECORDINGS = 30 | |
class MidiRecorder: | |
def __init__(self, place='', len_midi_recordings=LEN_MIDI_RECORDINGS): | |
self.place = place | |
self.len_midi_recordings = len_midi_recordings | |
self.port = mido.open_input(mido.get_input_names()[0]) | |
def get_filename(self): | |
now = datetime.now() | |
return self.place + '_' + now.strftime("%b_%d_%Y_%Hh%Mm%Ss") + '.mid' | |
def read_last_midi_msgs(self): | |
return list(self.port.iter_pending()) | |
def live_read(self): | |
while not is_pressed('esc'): | |
for msg in self.read_last_midi_msgs(): | |
print(msg) | |
def check_if_recording_started(self, msgs, t_init): | |
started = False | |
if len(msgs) > 0: | |
for m in msgs: | |
if m.type == 'note_on': | |
started = True | |
t_init = time.time() | |
return started, t_init | |
def create_empty_midi(self): | |
mid = MidiFile() | |
track = MidiTrack() | |
mid.tracks.append(track) | |
track.append(Message('program_change', program=0, time=0)) | |
return mid, track | |
def record_next_N_seconds(self, n=None, saving_path=None): | |
if saving_path is None: | |
saving_path = SYNTH_RECORDED_PATH + self.get_filename() | |
if n is None: | |
n = self.len_midi_recordings | |
print(f'Recoding the next {n} secs.' | |
f'\n\tRecording starts when the first key is pressed;' | |
f'\n\tPress Enter to end the recording;' | |
f'\n\tPress BackSpace (<--) to cancel the recording;' | |
f'\n\tSaving to {saving_path}') | |
try: | |
mid, track = self.create_empty_midi() | |
started = False | |
backspace_pressed = False | |
t_init = time.time() | |
while not is_pressed('enter') and (time.time() - t_init) < n: | |
msgs = self.read_last_midi_msgs() | |
if not started: | |
started, t_init = self.check_if_recording_started(msgs, t_init) | |
if started: | |
print("\n\t--> First note pressed, it's on!") | |
for m in msgs: | |
print(m) | |
if m.type == 'note_on' and m.velocity == 0: | |
m_off = Message(type='note_off', velocity=127, note=m.note, channel=m.channel, time=m.time) | |
track.append(m_off) | |
track.append(m) | |
if is_pressed('backspace'): | |
backspace_pressed = True | |
print('\n \t--> Recording cancelled! (you pressed BackSpace)') | |
break | |
# save the file | |
if not backspace_pressed and len(mid.tracks[0]) > 0: | |
mid.save(saving_path) | |
print(f'\n--> Recording saved, duration: {mid.length:.2f} secs, {len(mid.tracks[0])} events.') | |
except: | |
print('\n --> The recording failed.') | |
def run(self): | |
# with pynput.Listener( | |
# on_press=self.on_press) as listener: | |
# listener.join() | |
ready_msg = False | |
print('Starting the recording loop!\n\tPress BackSpace to cancel the current recording;\n\tPress Esc to quit the loop (only works while not recording)') | |
while True: | |
if not ready_msg: | |
print('-------\nReady to record!') | |
print('Press space to start a recording\n') | |
ready_msg = True | |
if is_pressed('space'): | |
self.record_next_N_seconds() | |
ready_msg = False | |
if is_pressed('esc'): | |
print('End of the recording session. See you soon!') | |
break | |
midi_recorder = MidiRecorder(place='home') | |
midi_recorder.live_read() | |
# midi_recorder.run() | |
# try: | |
# controls[msg.control] = msg.value | |
# except: | |
# notes.append(msg.note) | |
# port = mido.open_input() | |
# while True: | |
# for msg in port.iter_pending(): | |
# print(msg) | |
# | |
# print('start pause') | |
# time.sleep(5) | |
# print('stop pause') |