I've been developing a program in Python that uses MIDI. Part of that program allows the user to play a note with a MIDI input device and hear that same note played back to them. I had previously been developing this on a Windows PC and got it working but recently moved to macOS and found that my program now no longer plays any sound.
The following code is designed (for testing purposes) to play a note for one second. It doesn't return any errors but does not output any sound on my Mac.
import pygame.midi
import time
pygame.midi.init()
player = pygame.midi.Output(1)
player.set_instrument(0)
player.note_on(60, 127)
print("PLAYING")
time.sleep(1)
player.note_off(60, 127)
print("STOPPED")
del player
pygame.midi.quit()
I have tried installing sound fonts, changing the output device, changing the instrument, but no joy. As I said before, this program worked perfectly on my Windows machine. I'm pretty sure I need to do something on macos but I'm not sure what.
Any help would be much appreciated!
MIDI events must be sent to a MIDI synthesizer to be converted into sound that you may listen. Windows has always an available MIDI synth (the infamous "Microsoft GS Wavetable Synth"). It is a system driver, so it behaves like a hardware synth although it is not, it is a program (provided by Roland, by the way).
The situation is different in other operating systems. In macOS, Apple includes another MIDI soft synth, but it is not a program, it is a library (provided by Roland as well) that programs must load and activate. Fortunately, there are several free programs available like SimpleSynth. You can also play with my VMPK (connecting MIDI IN to CoreMIDI and MIDI OUT to the Apple DLS synth). If you want an alternative for Windows, my recommendation is virtualMIDIsynth.
Once you start your synth in macOS, you need to select the device ID that you need. For instance, with these modifications to your program:
pygame.midi.init()
#list all midi devices
for x in range( 0, pygame.midi.get_count() ):
print(x,"=",pygame.midi.get_device_info(x))
player = pygame.midi.Output(2)
...
I can produce sound in my Linux, and this is the console output:
0 = (b'ALSA', b'Midi Through Port-0', 0, 1, 0)
1 = (b'ALSA', b'Midi Through Port-0', 1, 0, 0)
2 = (b'ALSA', b'UM-2 MIDI 1', 0, 1, 0) <-- here is my synth
3 = (b'ALSA', b'UM-2 MIDI 1', 1, 0, 0)
4 = (b'ALSA', b'UM-2 MIDI 2', 0, 1, 0)
5 = (b'ALSA', b'UM-2 MIDI 2', 1, 0, 0)
PLAYING
STOPPED
In Windows, with VirtualMIDISynth running I can use id=2 and id=1
C:\tmp>python3 testpygame.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
0 = (b'MMSystem', b'Microsoft MIDI Mapper', 0, 1, 0)
1 = (b'MMSystem', b'VirtualMIDISynth #1', 0, 1, 0)
2 = (b'MMSystem', b'Microsoft GS Wavetable Synth', 0, 1, 0)
PLAYING
STOPPED
And finally in my mac book, with VMPK (id=1) and SimpleSynth (id=2):
$ python3 testpygame.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
0 = (b'CoreMIDI', b'VMPK Output', 1, 0, 0)
1 = (b'CoreMIDI', b'VMPK Input', 0, 1, 0)
2 = (b'CoreMIDI', b'SimpleSynth virtual input', 0, 1, 0)
PLAYING
STOPPED
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With