pythonkeyboardpygamemidipiano

Reading piano notes on Python


I'd like to listen to the port having my midi output device (a piano) with my RPi, running on Debian. I've looked into pygame.midi, I managed to listen to the port, but somehow can not extract all midi information. Please find code below [edited code snippet]

EDIT: Fixed, thanks a lot!


Solution

  • First of all you need to find out which device-id your keyboard has inside pygame. I wrote this little function to find out:

    import pygame.midi
    
    def print_devices():
        for n in range(pygame.midi.get_count()):
            print (n,pygame.midi.get_device_info(n))
    
    if __name__ == '__main__':
        pygame.midi.init()
        print_devices()
    

    It looks something like this:

    (0, ('MMSystem', 'Microsoft MIDI Mapper', 0, 1, 0))
    (1, ('MMSystem', '6- Saffire 6USB', 1, 0, 0))
    (2, ('MMSystem', 'MK-249C USB MIDI keyboard', 1, 0, 0))
    (3, ('MMSystem', 'Microsoft GS Wavetable Synth', 0, 1, 0))
    

    From the pygame manual you can learn that the first One inside this info-tuple determines this device as a suitable Input-Device. So let's read some data from it in an endless-loop:

    def readInput(input_device):
        while True:
            if input_device.poll():
                event = input_device.read(1)
                print (event)
    
    if __name__ == '__main__':
        pygame.midi.init()
        my_input = pygame.midi.Input(2) #only in my case the id is 2
        readInput(my_input)
    

    That shows:

    [[[144, 24, 120, 0], 1321]]
    

    that we have a list of a list with 2 items:

    The second value is the one you're interested in. So we print it out as a note:

    def number_to_note(number):
        notes = ['c', 'c#', 'd', 'd#', 'e', 'f', 'f#', 'g', 'g#', 'a', 'a#', 'b']
        return notes[number%12]
    
    def readInput(input_device):
        while True:
            if input_device.poll():
                event = input_device.read(1)[0]
                data = event[0]
                timestamp = event[1]
                note_number = data[1]
                velocity = data[2]
                print (number_to_note(note_number), velocity)
    

    I hope this helped. It's my first answer, I hope it's not too long. :)