TastyPiano / src /music /pipeline /synth2midi.py
Cédric Colas
initial commit
e775f6d
raw
history blame
4.8 kB
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')