Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 564
YanisM Avatar asked Apr 02 '13 15:04

YanisM


Video Answer


1 Answers

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:

  • A list of midi-data and
  • a timestamp

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. :)

like image 164
Fusselgesicht Avatar answered Nov 04 '22 16:11

Fusselgesicht