File size: 4,804 Bytes
e775f6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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')