{"id":1142,"date":"2017-07-23T01:13:41","date_gmt":"2017-07-23T00:13:41","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=1142"},"modified":"2017-07-23T23:23:48","modified_gmt":"2017-07-23T22:23:48","slug":"bluetooth-audio-with-ev3dev","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2017\/bluetooth-audio-with-ev3dev","title":{"rendered":"Bluetooth audio with ev3dev"},"content":{"rendered":"<p>Just a quick review on how to get Bluetooth Audio working with ev3dev.<\/p>\n<p>This is based on the method explained <a href=\"https:\/\/github.com\/ev3dev\/ev3dev\/issues\/198\">here<\/a>. It was tested with a snapshot image (&#8220;snapshot-ev3dev-stretch-ev3-generic-2017-06-27.img&#8221;) but it should work with the latest stable image from the ev3dev <a href=\"http:\/\/www.ev3dev.org\/downloads\/\">downloads<\/a> page.<\/p>\n<p>Even with a snapshot image, that already includes many updates released after the stable version, it&#8217;s a good practice to update everything before start:<\/p>\n<pre>sudo apt update\r\nsudo apt upgrade\r\nsudo apt dist-upgrade<\/pre>\n<p>On my case one of the updates available is for the &#8220;libpulse0&#8221; package, used by pulseaudio (and Bluetooth Audio uses pulseaudio).<\/p>\n<p>As of today I ended up with a 4.9.34 kernel:<\/p>\n<pre>robot@ev3dev:~$ uname -a\r\nLinux ev3dev 4.9.34-ev3dev-1.2.0-ev3 #1 PREEMPT Mon Jun 26 20:45:12 CDT 2017 armv5tejl GNU\/Linux<\/pre>\n<p>Now we install some packages needed:<\/p>\n<pre>sudo apt-get install --no-install-recommends pulseaudio pulseaudio-module-bluetooth<\/pre>\n<p>This will in fact install much more than just those 2 packages:<\/p>\n<pre>...\r\n0 upgraded, 33 newly installed, 0 to remove and 0 not upgraded.\r\nNeed to get 9587 kB of archives.<\/pre>\n<p>Now we should enable Bluetooth. The easy way is by using &#8216;brickman&#8217; &#8211; the text based User Interface that runs on ev3dev after boot: on the &#8216;Wireless&#8217; menu, choose &#8216;Bluetooth&#8217; then &#8216;Powered&#8217; and &#8216;Visible&#8217;. After EV3 finds our BT audio device (a speaker or an headset) we can pair with it.<\/p>\n<p>In my case I&#8217;m using a BT speaker named &#8220;BS-400&#8221; and EV3 shows something like this:<\/p>\n<pre>      BS-400\r\nC7:B5:42:B4:72:EC\r\nconnect    remove<\/pre>\n<p>After connecting (sometimes I need to try it a second time) we need to go to the command line:<\/p>\n<pre>pactl list sinks<\/pre>\n<p>This will show two audio devices &#8211; the EV3 speaker and my BT speaker:<\/p>\n<pre>Sink #0\r\n State: SUSPENDED\r\n Name: alsa_output.platform-sound.analog-mono\r\n Description: LEGO MINDSTORMS EV3 Speaker Analog Mono\r\n...\r\n\r\nSink #1\r\n State: SUSPENDED\r\n Name: <strong>bluez_sink.C7_B5_42_B4_72_EC.a2dp_sink<\/strong>\r\n Description: BS-400\r\n...<\/pre>\n<p>As far as I know the name of the second device always includes the BT address of our device, it can be useful if we have several devices of the same type.<\/p>\n<p>Now we can test it using one of the audio samples available at &#8216;\/usr\/share\/sounds\/alsa\/&#8217;:<\/p>\n<pre>paplay -d bluez_sink.C7_B5_42_B4_72_EC.a2dp_sink \/usr\/share\/sounds\/alsa\/Front_Center.wav<\/pre>\n<p>We can control the volume with &#8216;&#8211;volume=x&#8217; where x is an integer up to 65536.<\/p>\n<p>Instead of using a wav file we can also redirect the output of &#8216;espeak&#8217; to convert text to speech:<\/p>\n<pre>espeak \"Hello\" --stdout | paplay -d bluez_sink.C7_B5_42_B4_72_EC.a2dp_sink<\/pre>\n<p>(Note: this is a one-line command)<\/p>\n<p>This is great for shell scripts but for python it poses a problem &#8211; how to access PulseAudio?<\/p>\n<p>Will post about that later on but for now I show a simple way to use applications that expect ALSA to seamless work with our BT device by activating the PulseAudio plugin for alsalibs:<\/p>\n<pre>sudo nano \/etc\/asound.conf<\/pre>\n<p>The asound.conf file should contain just this 6 lines:<\/p>\n<pre>pcm.pulse {\r\n type pulse\r\n}\r\n\r\nctl.pulse {\r\n type pulse\r\n}<\/pre>\n<p>This redirects ALSA to the default PulseAudio device. So we can now use &#8216;aplay&#8217; instead of &#8216;paplay&#8217;:<\/p>\n<pre>aplay -Dpulse \/usr\/share\/sounds\/alsa\/Front_Center.wav<\/pre>\n<p>and we can control the volume with &#8216;alsamixer&#8217;. But better yet, we can use python with the <a href=\"http:\/\/ev3dev-lang.readthedocs.io\/projects\/python-ev3dev\/en\/stable\/other.html#sound\">ev3.Sound methods<\/a> like play or speak:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n\r\n#!\/usr\/bin\/env python3\r\nfrom time import sleep\r\nimport ev3dev.ev3 as ev3\r\n\r\nev3.Sound.speak('Hello').wait()\r\nsleep(1)\r\nev3.Sound.play('\/usr\/share\/sounds\/alsa\/Front_Center.wav')\r\n\r\n<\/pre>\n<p>There are however two methods that will not work with BT: tone and beep. That&#8217;s because instead of using ALSA they are hardwired to the onboard EV3 speaker.<\/p>\n<p>And finally we can also play MIDI files locally on the EV3 through BT:<\/p>\n<pre>sudo apt install timidity<\/pre>\n<p>Timidity++ is a soft synth that allows us to play MIDI without a MIDI card:<\/p>\n<pre>timidity brahms_waltz.mid -Os<\/pre>\n<p>It works through BT but takes about 30 seconds to start playing and the sound is very poor, mostly glitches:<\/p>\n<pre>Requested buffer size 32768, fragment size 8192\r\nALSA pcm 'default' set buffer size 32768, period size 8192 bytes\r\nPlaying brahms_waltz.mid\r\nMIDI file: brahms_waltz.mid\r\nFormat: 1 Tracks: 2 Divisions: 256\r\nSequence: Waltz\r\nText: Brahms\r\nTrack name: Harp\r\n\r\nPlaying time: ~57 seconds\r\nNotes cut: 86\r\nNotes lost totally: 141<\/pre>\n<p>We can tune timidity to use less CPU resources by adding arguments (see the output of &#8216;timidity &#8211;help&#8217;) or by editing the configuration file:<\/p>\n<pre>sudo nano \/etc\/timidity\/timidity.cfg<\/pre>\n<p>We uncomment all options recommended for a slow CPU except the default sample frequency:<\/p>\n<pre>...\r\n## If you have a slow CPU, uncomment these:\r\nopt EFresamp=d #disable resampling\r\nopt EFvlpf=d #disable VLPF\r\nopt EFreverb=d #disable reverb\r\nopt EFchorus=d #disable chorus\r\nopt EFdelay=d #disable delay\r\nopt anti-alias=d #disable sample anti-aliasing\r\nopt EWPVSETOZ #disable all Midi Controls\r\nopt p32a #default to 32 voices with auto reduction\r\n#opt s32kHz #default sample frequency to 32kHz\r\nopt fast-decay #fast decay notes\r\n...<\/pre>\n<p>Now the same command takes about 13 seconds to start playing and the music is played correctly (although with some white noise background).<\/p>\n<p>We can reduce start time a bit more by using Timidity in server mode &#8211; it takes a few seconds to start completely:<\/p>\n<pre>robot@ev3dev:~$ timidity -iA -Os &amp;\r\n[1] 8527\r\nrobot@ev3dev:~$ Requested buffer size 32768, fragment size 8192\r\nALSA pcm 'default' set buffer size 32768, period size 8192 bytes\r\nTiMidity starting in ALSA server mode\r\nOpening sequencer port: 128:0 128:1 128:2 128:3<\/pre>\n<p>if we now press ENTER we get back to the shell and Timidity keeps running:<\/p>\n<pre>robot@ev3dev:~$ pgrep timidity\r\n8527<\/pre>\n<p>so now we can use our own MIDI programs to play MIDI through one of the 4 MIDI ports that Timidity created:<\/p>\n<pre>aplaymidi -p 128:0 brahms_waltz.mid<\/pre>\n<p>It starts playing after 6 seconds.<\/p>\n<p>Not great but at least we can now use one of the several python libraries that can play MIDI music &#8211; perhaps after loading the library in memory this initial delay doesn&#8217;t happen when playing individal notes instead of a full music.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just a quick review on how to get Bluetooth Audio working with ev3dev. This is based on the method explained here. It was tested with a snapshot image (&#8220;snapshot-ev3dev-stretch-ev3-generic-2017-06-27.img&#8221;) but it should work with the latest stable image from the ev3dev downloads page. Even with a snapshot image, that already includes many updates released after &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2017\/bluetooth-audio-with-ev3dev\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;Bluetooth audio with ev3dev&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[1],"tags":[],"series":[],"class_list":["post-1142","post","type-post","status-publish","format-standard","hentry","category-sem-categoria"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-iq","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/1142","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/comments?post=1142"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/1142\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=1142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=1142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=1142"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=1142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}