It’s no trouble to get Sonic Pi going on a Raspberry Pi (Raspbian comes with it), and as I wrote about last week I had great fun with that. But my Raspberry Pi is slow, so it would often choke, and the interface is meant for kids so they can learn to make music and program, not for middle-aged librarians who love Emacs, so I wanted to get it running on my Ubuntu laptop. Here’s how I did it.
There’s nothing really new here, but it might save someone some time, because it involved getting JACK working, which is one of those things where you begin carefully documenting everything you do and an hour later you have thirty browser tabs open, three of them to the same mailing list archive showing a message from 2005, and you’ve edited some core system files but you’re sure you’ve forgotten one and don’t have a backup, and then everything works and you don’t want to touch it in case it breaks.
Linux and Unix users should go to the GitHub Sonic Pi repo and follow the generic Linux installation instructions, which is what I did. I run Ubuntu; I had some of the requirements already installed, but not all. Then:
cd /usr/local/src/ git clone email@example.com:samaaron/sonic-pi.git cd sonic-pi/app/server/bin ./compile-extensions cd ../../gui/qt ./rp-build-app ./rp-app-bin
sudo apt-get install qjackctl
qjackctl is a little GUI front end to control JACK. I installed it and ran it and got an error:
JACK is running in realtime mode, but you are not allowed to use realtime scheduling. Please check your /etc/security/limits.conf for the following line and correct/add it if necessary: @audio - rtprio 99 After applying these changes, please re-login in order for them to take effect. You don't appear to have a sane system configuration. It is very likely that you encounter xruns. Please apply all the above mentioned changes and start jack again!
Editing that file isn’t the right way to do it, though. This is:
sudo apt-get install jackd2 sudo dpkg-reconfigure -p high jackd2
/etc/security/limits.d/audio.conf look so:
# Provided by the jackd package. # # Changes to this file will be preserved. # # If you want to enable/disable realtime permissions, run # # dpkg-reconfigure -p high jackd @audio - rtprio 95 @audio - memlock unlimited #@audio - nice -19
qjackctl gave me this error:
JACK is running in realtime mode, but you are not allowed to use realtime scheduling. Your system has an audio group, but you are not a member of it. Please add yourself to the audio group by executing (as root): usermod -a -G audio (null) After applying these changes, please re-login in order for them to take effect.
Replace “(null)” with your username. I ran:
usermod -a -G audio wtd
Logged out and back in and ran
qjackctl again and got:
ACK compiled with System V SHM support. cannot lock down memory for jackd (Cannot allocate memory) loading driver .. apparent rate = 44100 creating alsa driver ... hw:0|hw:0|1024|2|44100|0|0|nomon|swmeter|-|32bit ALSA: Cannot open PCM device alsa_pcm for playback. Falling back to capture-only mode cannot load driver module alsa
Here I searched online, looked at all kinds of questions and answers, made a cup of tea, tried again, gave up, tried again, then installed something that may not be necessary, but it was part of what I did so I’ll include it:
sudo apt-get install pulseaudio-module-jack
Then, thanks to some helpful answer somewhere, I got onto the real problem, which is about where the audio was going. I grew up in a world where home audio signals (not including the wireless) were transmitted on audio cables with RCA jacks. (Pondering all the cables I’ve used in my life, I think the RCA jack is the closest to perfection. It’s easy to identify, it has a pleasing symmetry and design, and there is no way to plug it in wrong.) Your cassette deck and turntable would each have one coming out and you’d plug them into your tuner and then everything just worked, because when you needed you’d turn a knob that meant “get the audio from here.” I have only the haziest idea of how audio on Linux really works, but at heart there seems to be something similar going on, because what made it work was telling JACK which audio thingie I wanted.
You can pull up that window by clicking on Settings in
qjackctl. The Interface line said “Default,” but I changed it to “hw:PCH (HDA Intel PCH (hw: 1)”, whatever that means) and it worked. What’s in the screenshot is different, and it works too. I don’t know why. Don’t ask me. Just fiddle those options and maybe it will work for you too.
I hit Start and got JACK going, then back in the Sonic Pi source tree I ran
./rp-app-bin and it worked! Sound came out of my speakers! I plugged in my headphones and they worked. Huzzah!
That was all well and good, but nothing is fully working until it can be run from Emacs. A thousand thanks go to sonic-pi.el!
I used the package manager (
M-x list-packages) to install
sonic-pi; I didn’t need to install
osc because I already had them for some reason. Then I added this to
;; Sonic Pi (https://github.com/repl-electric/sonic-pi.el) (require 'sonic-pi) (add-hook 'sonic-pi-mode-hook (lambda () ;; This setq can go here instead if you wish (setq sonic-pi-path "/usr/local/src/sonic-pi/") (define-key ruby-mode-map "\C-c\C-c" 'sonic-pi-send-buffer)))
That last line is a customization of my own: I wanted
C-c C-c to do the right thing the way it does in Org mode: here, I want it to play the current buffer. A good key combination like that is good to reuse.
Then I could open up
test.rb and try whatever I wanted. After a lot of fooling around I wrote this:
define :throb do |note, seconds| use_synth :square with_fx :reverb, phase: 2 do s = play note, attack: seconds/2, release: seconds/2, note_slide: 0.25 (seconds*4).times do control s, note: note sleep 0.25 control s, note: note-2 sleep 0.25 end end end throb(40, 32)
To get it connected, I ran
M-x sonic-pi-mode then
M-x sonic-pi-connect (it was already running, otherwise
M-x sonic-pi-jack-in would do; sometimes
M-x sonic-pi-restart is needed), then I hit
C-c C-c … and a low uneasy throbbing sound comes out.
Amazing. Everything feels better when you can do it in Emacs. Especially coding music.