{"id":18,"date":"2017-06-27T05:04:18","date_gmt":"2017-06-27T12:04:18","guid":{"rendered":"https:\/\/lucidbeaming.com\/blog\/?p=18"},"modified":"2022-06-01T12:37:21","modified_gmt":"2022-06-01T19:37:21","slug":"running-fluidsynth-on-a-raspberry-pi-zero-w","status":"publish","type":"post","link":"https:\/\/lucidbeaming.com\/blog\/running-fluidsynth-on-a-raspberry-pi-zero-w\/","title":{"rendered":"Running Fluidsynth on a Raspberry PI Zero W"},"content":{"rendered":"<p>One of the reasons I&#8217;ve spent so much time experimenting with audio software on Raspberry Pis is to build standalone music sculpture. I want to make machines that explore time and texture, in addition to generating interesting music.<\/p>\n<p>The first soft synth I tried was Fluidsynth. It&#8217;s one of the few that can run headless, without a GUI. I set it up on a Pi 3 and it worked great. It&#8217;s used as a basic General MIDI synthesizer engine for a variety of packages and even powers game soundtracks on Android.<\/p>\n<div data-mode=\"normal\" data-oembed=\"1\" data-provider=\"youtube\" id=\"arve-youtube-pkbfhrptfwk\" class=\"arve\">\n<div class=\"arve-inner\">\n<div class=\"arve-embed arve-embed--has-aspect-ratio\">\n<div class=\"arve-ar\" style=\"padding-top:56.250000%\"><\/div>\n<p>\t\t\t<iframe allow=\"accelerometer &apos;none&apos;;autoplay &apos;none&apos;;bluetooth &apos;none&apos;;browsing-topics &apos;none&apos;;camera &apos;none&apos;;clipboard-read &apos;none&apos;;clipboard-write;display-capture &apos;none&apos;;encrypted-media &apos;none&apos;;gamepad &apos;none&apos;;geolocation &apos;none&apos;;gyroscope &apos;none&apos;;hid &apos;none&apos;;identity-credentials-get &apos;none&apos;;idle-detection &apos;none&apos;;keyboard-map &apos;none&apos;;local-fonts;magnetometer &apos;none&apos;;microphone &apos;none&apos;;midi &apos;none&apos;;otp-credentials &apos;none&apos;;payment &apos;none&apos;;picture-in-picture;publickey-credentials-create &apos;none&apos;;publickey-credentials-get &apos;none&apos;;screen-wake-lock &apos;none&apos;;serial &apos;none&apos;;summarizer &apos;none&apos;;sync-xhr;usb &apos;none&apos;;web-share;window-management &apos;none&apos;;xr-spatial-tracking &apos;none&apos;;\" allowfullscreen=\"\" class=\"arve-iframe fitvidsignore\" credentialless data-arve=\"arve-youtube-pkbfhrptfwk\" data-lenis-prevent=\"\" data-src-no-ap=\"https:\/\/www.youtube-nocookie.com\/embed\/pkbfHrPtFWk?feature=oembed&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;autohide=1&amp;playsinline=0&amp;autoplay=0\" frameborder=\"0\" height=\"0\" loading=\"lazy\" name=\"\" referrerpolicy=\"strict-origin-when-cross-origin\" sandbox=\"allow-scripts allow-same-origin allow-presentation allow-popups allow-popups-to-escape-sandbox\" scrolling=\"no\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/pkbfHrPtFWk?feature=oembed&#038;iv_load_policy=3&#038;modestbranding=1&#038;rel=0&#038;autohide=1&#038;playsinline=0&#038;autoplay=0\" title=\"\" width=\"0\"><\/iframe><\/p><\/div>\n<\/p><\/div>\n<p>\t<script type=\"application\/ld+json\">{\"@context\":\"http:\\\/\\\/schema.org\\\/\",\"@id\":\"https:\\\/\\\/lucidbeaming.com\\\/blog\\\/running-fluidsynth-on-a-raspberry-pi-zero-w\\\/#arve-youtube-pkbfhrptfwk\",\"type\":\"VideoObject\",\"embedURL\":\"https:\\\/\\\/www.youtube-nocookie.com\\\/embed\\\/pkbfHrPtFWk?feature=oembed&iv_load_policy=3&modestbranding=1&rel=0&autohide=1&playsinline=0&autoplay=0\"}<\/script><\/p>\n<\/div>\n<p>This video is a demo of the same sound set used in this project, but on an earlier iteration using a regular Raspberry Pi 3 and a Pimoroni Displayotron HAT. I ended up switching to the smaller Raspberry Pi Zero W and using a webapp instead of a display.<\/p>\n<p>The sounds are not actually generated from scratch, like a traditional synthesizer. It draws on a series of predefined sounds collected and mapped in SoundFonts. The .sf2 format was made popular by the now defunct\u00a0Sound Blaster AWE32 sound card that was ubiquitous on 90s PCs.<\/p>\n<p>Back then, there was a niche community of people producing custom SoundFonts. Because of that, development in library tools and players was somewhat popular. Fluidsynth came long after, but benefits from the early community work and a few nostalgic archivists.<\/p>\n<p>The default SoundFont that comes with common packages is FluidR3_GM. It is a full General Midi set with 128 instruments a small variety of drum kits. It&#8217;s fine for building a basic keyboard or MIDI playback utility. But, it&#8217;s not very high fidelity or interesting.<\/p>\n<p>What hooked me was finding a repository of commercial SoundFonts (no longer active). That site has an amazing collection of 70s-90s synths in SoundFont format, including Jupiter-8, TB-303, Proteus 1\/2\/3, Memory Moog, and an E-MU Modular. The E-MU Modular sounds pretty rad and is the core of the sound set I put together for this. They&#8217;re all cheap and I picked up a few to work with. The sound is excellent.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"img-responsive aligncenter wp-image-137 size-full\" src=\"https:\/\/lucidbeaming.com\/blog\/wp-content\/uploads\/2017\/06\/fluid-open.jpg\" alt=\"Raspberry Pi Zero W\" width=\"800\" height=\"435\" \/><\/p>\n<p>For this particular project, I ended up using a Raspberry Pi Zero W for its size and versatility. Besides running Fluidsynth, it also serves up a Node.js webapp over wifi for changing instruments. It&#8217;s controllable by any basic USB MIDI keyboard and runs on a mid-sized USB battery pack for around 6 hours. Pretty good for such a tiny footprint and it costs around $12.<\/p>\n<h3>Setting it up<\/h3>\n<p>If you want to get something working fast or just want to make a kid&#8217;s keyboard, setup is a breeze.<\/p>\n<p>After configuring the Pi Zero and audio:<\/p>\n<pre>sudo apt-get install fluidsynth<\/pre>\n<p>That&#8217;s it.<\/p>\n<p>But, if you want more flexibility or interactivity, things get a bit more complex. The basic setup is the same as what I laid out in my <a href=\"https:\/\/lucidbeaming.com\/blog\/setting-up-a-raspberry-pi-3-to-run-zynaddsubfx-in-a-headless-configuration\/\">ZynAddSubFX post<\/a>.<\/p>\n<p><a href=\"https:\/\/www.raspberrypi.org\/downloads\/raspbian\/\">Download Jessie Lite<\/a> and find a usable Micro SD card. The following is for Mac OS. Instructions for Linux are similar and Windows details can be found on the <a href=\"https:\/\/www.raspberrypi.org\/downloads\/\">raspberrypi.org<\/a> site.<\/p>\n<p>Insert the SD card into your computer and find out what designation the OS gave it. The unmount it and write the Jessie Lite image to it.<\/p>\n<pre>diskutil list\n\n\/dev\/disk1 (external, physical):\n #: TYPE NAME SIZE IDENTIFIER\n 0: FDisk_partition_scheme *8.0 GB disk1\n 1: Windows_FAT_32 NO NAME 8.0 GB disk1s1\n\ndiskutil unmountDisk \/dev\/disk1\n\nsudo dd bs=1m if=2017-04-10-raspbian-jessie-lite.img of=\/dev\/rdisk1<\/pre>\n<p>Pull the card out and reinsert it. Then, add two files to the card to make setup a little faster and skip a GUI boot.<\/p>\n<pre>cd \/Volumes\/boot\ntouch ssh\n\nsudo nano wpa_supplicant.conf<\/pre>\n<p>Put this into the file you just opened.<\/p>\n<pre>ctrl_interface=DIR=\/var\/run\/wpa_supplicant GROUP=netdev\nupdate_config=1\n\nnetwork={\n ssid=\"&lt;your_ssid&gt;\"\n psk=\"&lt;your_password&gt;\"\n}<\/pre>\n<p>Put the card in the Pi Zero and power it up, then configure the box with raspi-config. One trick I learned was not to change the root password and expand the file system at the same time. I&#8217;m not sure what the problem is, but often it corrupts the ssh password to do both at the same time.<\/p>\n<p>Update the Pi:<\/p>\n<pre>sudo apt-get update\nsudo apt-get upgrade<\/pre>\n<p>Fluidsynth needs a higher thread priority than the default, so I use the same approach as setting up Realtime Priority. It might be overkill, but it&#8217;s consistent with the other Pi boxes I set up. Add the user &#8220;pi&#8221; to the group &#8220;audio&#8221; and then set expanded limits.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"img-responsive aligncenter wp-image-140 size-full\" src=\"https:\/\/lucidbeaming.com\/blog\/wp-content\/uploads\/2017\/06\/setup.gif\" alt=\"Pi commands\" width=\"650\" height=\"340\" \/><\/p>\n<pre>sudo usermod -a -G audio pi\n\nsudo nano \/etc\/security\/limits.d\/audio.conf<\/pre>\n<p>The file should be empty. Add this to it.<\/p>\n<pre>@audio - rtprio 80\n@audio - memlock unlimited<\/pre>\n<p>If you&#8217;re not using an external USB audio dongle or interface, you don&#8217;t need to do this. But, after you hear what the built-in audio sounds like, you&#8217;ll want something like this.<\/p>\n<pre>sudo nano \/boot\/config.txt<\/pre>\n<p>Comment out the built-in audio driver.<\/p>\n<pre># Enable audio (loads snd_bcm2835)\n# dtparam=audio=on<\/pre>\n<pre>sudo nano \/etc\/asound.conf<\/pre>\n<p>Set the USB audio to be default. It&#8217;s useful to use the name of the card instead of the stack number.<\/p>\n<pre>pcm.!default {\n type hw card Device\n }\n ctl.!default {\n type hw card Device\n }<\/pre>\n<p>Reboot and then test your setup.<\/p>\n<pre>sudo reboot\n\naplay -l\n\nlsusb -t\n\nspeaker-test -c2 -twav<\/pre>\n<p>A voice should speak out the left and right channels. After verifying that, it&#8217;s time to set up Fluidsynth.<\/p>\n<p>The reason I compile it from the git repo is to get the latest version. The version in the default Raspbian repository used by <em>apt-get<\/em> is\u00a01.1.6-2. The latest is 1.1.6-4. The reason we need this is <a href=\"https:\/\/en.wikipedia.org\/wiki\/Telnet\">Telnet<\/a>.<\/p>\n<p>That&#8217;s right, Fluidsynth uses Telnet to receive commands and as its primary shell. It&#8217;s a classic text based network communication protocol used for remote administration. Think <a href=\"http:\/\/www.imdb.com\/title\/tt0086567\/trivia?tab=qt\">Wargames<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"img-responsive alignnone wp-image-139 size-full\" src=\"https:\/\/lucidbeaming.com\/blog\/wp-content\/uploads\/2017\/06\/giphy.gif\" alt=\"Telnet\" width=\"500\" height=\"333\" \/><\/p>\n<p>But, there&#8217;s a bug in the standard package that causes remote sessions to get rejected in Jessie. It&#8217;s been addressed in the later versions of Fluidsynth. I needed it to work to run the web app.<\/p>\n<p>Grab the dependencies and then compile Fluidsynth. It&#8217;s not complicated, but there are some caveats.<\/p>\n<pre>sudo apt-get install git libgtk2.0-dev cmake cmake-curses-gui build-essential libasound2-dev telnet\n\ngit clone git:\/\/git.code.sf.net\/p\/fluidsynth\/code-git\n\ncd code-git\/fluidsynth\n mkdir build\n cd build\n cmake ..\n sudo make install<\/pre>\n<p>The install script misses a key path definition that aptitude usually handles, so I add it manually. It&#8217;s needed so\u00a0<em>libfluidsynth.so.1<\/em> can be found. If you see an error about that file, this is why.<\/p>\n<pre>sudo nano \/etc\/ld.so.conf<\/pre>\n<p>Add this line:<\/p>\n<pre>\/usr\/local\/lib<\/pre>\n<p>Then:<\/p>\n<pre>sudo ldconfig\n export LD_LIBRARY_PATH=\/usr\/local\/lib<\/pre>\n<p>Now we need to grab the default SoundFont. This is available easily with apt-get.<\/p>\n<pre>sudo apt-get install fluid-soundfont-gm<\/pre>\n<p>That&#8217;s it for Fluidsynth. It should run fine and you can test it with a help parameter.<\/p>\n<pre>fluidsynth -h<\/pre>\n<p>Now to install Node.js and the webapp to change instruments with.<\/p>\n<pre>curl https:\/\/raw.githubusercontent.com\/creationix\/nvm\/master\/install.sh | sh<\/pre>\n<p>Logout and log back into an ssh session. That makes <em>nvm<\/em> available.<\/p>\n<pre>nvm install v6.10.1<\/pre>\n<p>Grab the webapp from my repo and install it.<\/p>\n<pre>git clone https:\/\/github.com\/lucidbeaming\/Fluidsynth-Webapp.git fluidweb\n\ncd fluidweb\n\nnpm install --save<\/pre>\n<p>Find the IP address of you Pi on your local network. Visit &lt;ip address&gt; port 7000 on any other device.<\/p>\n<pre>http:\/\/192.168.1.20:7000<\/pre>\n<p>If Fluidsynth isn&#8217;t running, it will display a blank page. If it is running, it will list all instruments available, dynamically. This won&#8217;t be much of a problem once the launch script is setup. It launches Fluidsynth, connects any keyboards attached through ALSA, and launches the webapp.<\/p>\n<p>Create the script and add the following contents. It&#8217;s offered as a guideline and probably won&#8217;t work if copied and pasted. You should customize it according to your own environment, devices, and tastes.<\/p>\n<pre>sudo nano fluidsynth.sh<\/pre>\n<pre>#!\/bin\/bash\n\nif pgrep -x \"fluidsynth\" &gt; \/dev\/null\nthen\necho fluidsynth already flowing\nelse\nfluidsynth -si -p \"fluid\" -C0 -R0 -r48000 -d -f .\/config.txt -a alsa -m alsa_seq &amp;\nfi\n\nsleep 3\n\nmini=$(aconnect -o | grep \"MINILAB\")\nmpk=$(aconnect -o | grep \"MPKmini2\")\nmio=$(aconnect -o | grep \"mio\")\n\nif [[ $mini ]]\nthen\naconnect 'Arturia MINILAB':0 'fluid':0\necho MINIlab connected\nelif [[ $mpk ]]\nthen\naconnect 'MPKmini2':0 'fluid':0\necho MPKmini connected\nelif [[ $mio ]]\nthen\naconnect 'mio':0 'fluid':0\necho Mio connected\nelse\necho No known midi devices available. Try aconnect -l\nfi\n\ncd fluidweb\nnode index.js\ncd ..\n\nexit<\/pre>\n<p>Note that I included the settings -C0 -R0 in the Fluidsynth command. That turns off reverb and chorus, which saves a bit of processor power and doesn&#8217;t sound good anyway.<\/p>\n<p>Now, create a configuration file for Fluidsynth to start with.<\/p>\n<pre>sudo nano config.txt<\/pre>\n<pre>echo \"Exploding minds\"\ngain 3\nload \".\/soundfonts\/lucid.sf2\"\nselect 0 1 0 0\nselect 1 1 0 1\nselect 2 1 0 2\nselect 3 1 0 3\nselect 4 1 0 4\nselect 5 1 0 5\nselect 6 1 0 6\nselect 7 1 0 7\nselect 8 1 0 8\nselect 10 1 0 9\nselect 11 1 0 10\nselect 12 1 0 11\nselect 13 1 0 12\nselect 14 1 0 13\nselect 15 1 0 14\necho \"bring it on\"<\/pre>\n<p>The select command chooses instruments for various channels.<\/p>\n<pre>select &lt;channel&gt; &lt;soundfont&gt; &lt;bank&gt; &lt;program&gt;<\/pre>\n<p>Note that channel 9 is the drumkit.<\/p>\n<p>To get the launch script to run on boot(or session) it needs to have the right permissions first.<\/p>\n<pre>sudo chmod a+x fluidsynth.sh<\/pre>\n<p>Then, add the script to the end of .bash_profile. I do that instead of other options for running scripts at boot so that fluidsynth and node.js run as a user process for &#8220;pi&#8221; instead of root.<\/p>\n<pre>sudo nano .bash_profile<\/pre>\n<p>At the end of the file&#8230;<\/p>\n<pre>.\/fluidsynth.sh<\/pre>\n<p>Reboot the Pi Zero and when it gets back up, it should run the script and you&#8217;ll be good to go. If you run into problems, a good place to get feedback is <a href=\"https:\/\/linuxmusicians.com\/\">LinuxMusicians.com<\/a>. They have an active community with some helpful folks.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"img-responsive alignnone wp-image-144 size-full\" src=\"https:\/\/lucidbeaming.com\/blog\/wp-content\/uploads\/2017\/06\/fluid-closed.jpg\" alt=\"Raspberry Pi Zero W in a case\" width=\"800\" height=\"413\" \/><\/p>\n<p>Here&#8217;s another quick demo I put together. Not much in terms my own playing, haha, but does exhibit some of the sounds I&#8217;m going for.<\/p>\n<div data-mode=\"normal\" data-oembed=\"1\" data-provider=\"youtube\" id=\"arve-youtube-z4pjqsnjrc8\" class=\"arve\">\n<div class=\"arve-inner\">\n<div class=\"arve-embed arve-embed--has-aspect-ratio\">\n<div class=\"arve-ar\" style=\"padding-top:56.250000%\"><\/div>\n<p>\t\t\t<iframe allow=\"accelerometer &apos;none&apos;;autoplay &apos;none&apos;;bluetooth &apos;none&apos;;browsing-topics &apos;none&apos;;camera &apos;none&apos;;clipboard-read &apos;none&apos;;clipboard-write;display-capture &apos;none&apos;;encrypted-media &apos;none&apos;;gamepad &apos;none&apos;;geolocation &apos;none&apos;;gyroscope &apos;none&apos;;hid &apos;none&apos;;identity-credentials-get &apos;none&apos;;idle-detection &apos;none&apos;;keyboard-map &apos;none&apos;;local-fonts;magnetometer &apos;none&apos;;microphone &apos;none&apos;;midi &apos;none&apos;;otp-credentials &apos;none&apos;;payment &apos;none&apos;;picture-in-picture;publickey-credentials-create &apos;none&apos;;publickey-credentials-get &apos;none&apos;;screen-wake-lock &apos;none&apos;;serial &apos;none&apos;;summarizer &apos;none&apos;;sync-xhr;usb &apos;none&apos;;web-share;window-management &apos;none&apos;;xr-spatial-tracking &apos;none&apos;;\" allowfullscreen=\"\" class=\"arve-iframe fitvidsignore\" credentialless data-arve=\"arve-youtube-z4pjqsnjrc8\" data-lenis-prevent=\"\" data-src-no-ap=\"https:\/\/www.youtube-nocookie.com\/embed\/z4pJQSNJRC8?feature=oembed&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;autohide=1&amp;playsinline=0&amp;autoplay=0\" frameborder=\"0\" height=\"0\" loading=\"lazy\" name=\"\" referrerpolicy=\"strict-origin-when-cross-origin\" sandbox=\"allow-scripts allow-same-origin allow-presentation allow-popups allow-popups-to-escape-sandbox\" scrolling=\"no\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/z4pJQSNJRC8?feature=oembed&#038;iv_load_policy=3&#038;modestbranding=1&#038;rel=0&#038;autohide=1&#038;playsinline=0&#038;autoplay=0\" title=\"\" width=\"0\"><\/iframe><\/p><\/div>\n<\/p><\/div>\n<p>\t<script type=\"application\/ld+json\">{\"@context\":\"http:\\\/\\\/schema.org\\\/\",\"@id\":\"https:\\\/\\\/lucidbeaming.com\\\/blog\\\/running-fluidsynth-on-a-raspberry-pi-zero-w\\\/#arve-youtube-z4pjqsnjrc8\",\"type\":\"VideoObject\",\"embedURL\":\"https:\\\/\\\/www.youtube-nocookie.com\\\/embed\\\/z4pJQSNJRC8?feature=oembed&iv_load_policy=3&modestbranding=1&rel=0&autohide=1&playsinline=0&autoplay=0\"}<\/script><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>For this particular project, I ended up using a Raspberry Pi Zero W for its size and versatility. Besides running Fluidsynth, it also serves up a Node.js webapp over wifi for changing instruments. It&#8217;s controllable by any basic USB MIDI keyboard and runs on a mid-sized USB battery pack for around 6 hours. Pretty good for such a tiny footprint and it costs around $12.<\/p>\n","protected":false},"author":1,"featured_media":137,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[2],"tags":[4,6,14,5,7],"class_list":["post-18","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-building","tag-diy","tag-raspberry-pi","tag-raspberry-pi-zero-w","tag-synthesizer","tag-tutorial"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/comments?post=18"}],"version-history":[{"count":13,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/posts\/18\/revisions"}],"predecessor-version":[{"id":812,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/posts\/18\/revisions\/812"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/media\/137"}],"wp:attachment":[{"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/media?parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/categories?post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lucidbeaming.com\/blog\/wp-json\/wp\/v2\/tags?post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}