Raspberry Pi

MIDI Synthesizer Engine

Instructions for configuring a Raspberry Pi 3B or 4 as a portable, headless, ultra-low latency MIDI synthesizer using the FluidSynth synthesizer.

Shopping list:

Raspberry Pi 3B/3B+ (lower power requirement when using a battery bank):

  • (Discontinued, but still widely available)

OR

Raspberry Pi 4 (2GB+ allows for larger SoundFont options):

USB sound card (required for low latency):

USB MIDI device

  • A USB MIDI keyboard, guitar, or perhaps something that you have built yourself?

Setup Instructions:

  • Download the latest version of Raspbian Lite from: https://www.raspberrypi.org/downloads/raspbian/

  • Burn the image to a 4GB+ MicroSD card, and follow the excellent instructions for headless SSH configuration at: https://www.tomshardware.com/reviews/raspberry-pi-headless-setup-how-to,6028.html

  • Run sudo apt update && sudo apt upgrade to upgrade all installed software to current versions.

  • Run sudo raspi-config, change the default password, configure the device for your locale, and enable console autologin in the boot options.

  • Run sudo apt install alsa-utils fluidsynth screen to install the required synthesizer packages.

  • Run cd ~/ && wget https://raw.githubusercontent.com/KOOPInstruments/raspi-synth/master/synth.sh && chmod +x ~/synth.sh to download the headless raspi-synth script, and mark it for execution.

  • Run nano ~/.bashrc, add the line /home/pi/synth.sh to the end of the file, and press Ctrl-o Ctrl-x to save and quit nano. This will tell the Pi to launch the script automatically on login (which also means launch on boot due to console autologin enabled earlier).

  • Run cat /proc/asound/cards to get a list of connected sound devices, and take note of the unique sound device name string on the same line as the device number, example in bold: 2 [CODEC ]: USB-Audio - USB AUDIO CODEC.

  • Run nano ~/synth.sh and edit the line beginning with audioDevice=$ to insert your unique sound device name between the double-quotes in the 'grep' statement. Press Ctrl-o Ctrl-x to save and quit nano.

  • Run alsamixer press F6 to select your sound card, set the master volume to a reasonable level, and press Esc to exit.

  • Run sudo reboot and test out your new synthesizer!

Using Different SoundFonts:

  • Download your General MIDI SoundFont (.SF2) file to the /home/pi/ folder, run nano ~/synth.sh and change the end of the line beginning with screen -dmS FluidSynth0 to modify the path for your SoundFont file name and location, for example: /home/pi/Timbres\ Of\ Heaven\ GM_GS_XG_SFX\ V\ 3.4\ Final.sf2

RasPi-Synth Script:

## Raspberry Pi 4 FluidSynth MIDI Sound Engine

## 2019 - KOOP Instruments (koopinstruments@gmail.com)


# Remount the file system read/write to allow modifications

sudo mount -o remount,rw /


# Update the clock

sudo ntpd -q -g


echo "Starting synth script in 5 seconds (press Ctrl-c to cancel)..."

sleep 1

echo "4..."

sleep 1

echo "3..."

sleep 1

echo "2..."

sleep 1

echo "1..."

sleep 1


# If the script was not cancelled, remount the file system readonly

sudo mount -o remount,r /


## Optional power saving (uncomment if desired):

# sudo ifconfig wlan0 down # Disable the Wi-Fi adapter

sudo tvservice --off # Disable HDMI video output


echo "Killing any existing fluidsynth processes..."


sudo killall -s SIGKILL fluidsynth &>/dev/null


# Run the rest of the script on a loop in case a new sound card is connected, the FluidSynth server crashes, or a new MIDI instrument is connected

while [[ 1 -eq 1 ]]; do


# Run 'cat /proc/asound/cards' to get a list of audio devices, and modify the grep statement below with a unique identifying string

# Examples:

# audioDevice=$(cat /proc/asound/cards | grep "bcm2835_alsa" | awk -F" " '{ print $1 }') # Raspberry Pi on-board audio (high latency - only use if no other options)

# audioDevice=$(cat /proc/asound/cards | grep "USB-Audio - USB Audio Device" | awk -F" " '{ print $1 }') # Sabrent USB sound card

# audioDevice=$(cat /proc/asound/cards | grep "USB-Audio - Logitech" | awk -F" " '{ print $1 }') # Logitech USB sound card


audioDevice=$(cat /proc/asound/cards | grep "USB-Audio - USB AUDIO" | awk -F" " '{ print $1 }') # Peavy USB mixer sound card



if pgrep -x "fluidsynth" > /dev/null

then

sleep 1

else

echo "Starting fluidsynth server..."

# Blink both lights to let the user know that the synth is starting

sudo echo 1 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 1 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

sudo echo 1 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 1 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

sudo echo 1 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 1 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led0/brightness &>/dev/null

sudo echo 0 | sudo tee /sys/class/leds/led1/brightness &>/dev/null

# Start the FluidSynth server in a new screen session to allow reattaching for troubleshooting purposes

screen -dmS FluidSynth0 bash -c "sudo nice -n -20 fluidsynth -i -s -g 0.6 -a alsa -o audio.alsa.device=hw:$audioDevice -c 1 -z 1 -o synth.cpu-cores=4 -o synth.polyphony=128 /usr/share/sounds/sf2/FluidR3_GM.sf2"

sleep 5

fi


# Scrape the ALSA port number of the FluidSynth Server

fsClientNum=$(aconnect -l | grep "FLUID Synth" | awk -F" " '{ print $2 -0 }')


# Enable one light to let the user know that device discovery is running

echo 1 | sudo tee /sys/class/leds/led1/brightness &>/dev/null


myCounter=1


while [[ $myCounter -lt $fsClientNum ]]; do

aconnect $myCounter:0 $fsClientNum:0 2>/dev/null

let myCounter=myCounter+1

done


echo 0 | sudo tee /sys/class/leds/led1/brightness &>/dev/null


sleep 1


done