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') |