{"id":951,"date":"2016-08-23T14:50:06","date_gmt":"2016-08-23T13:50:06","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=951"},"modified":"2016-08-23T15:06:10","modified_gmt":"2016-08-23T14:06:10","slug":"lego-laser-harp-part-ii","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2016\/lego-laser-harp-part-ii","title":{"rendered":"LEGO laser harp &#8211; part II"},"content":{"rendered":"<div class=\"seriesmeta\">This post is part 2 of 2 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/lego-laser-harp\" class=\"series-275\" title=\"LEGO Laser Harp\">LEGO Laser Harp<\/a><\/div><p>About 10 years ago I offered my wife a <a href=\"http:\/\/www.m-audio.com\/products\/view\/keystation-61es\">M-Audio USB MIDI Keyboard<\/a> and installed <a href=\"https:\/\/ubuntustudio.org\/\">Ubuntu Studio<\/a> on a computer so she could play some piano at home. She was so amazed with the possibility to generate music sheet while playing that almost accepted the idea of using Linux&#8230; almost \ud83d\ude42<\/p>\n<p>I remember that at that time I used <a href=\"http:\/\/timidity.sourceforge.net\/\">timidity++<\/a> as a software MIDI synthesizer, tuned <a href=\"http:\/\/www.alsa-project.org\/main\/index.php\/Main_Page\">ALSA<\/a> (one of the several Linux sound systems, perhaps the most generally used) and the preemptive kernel to work almost flawlessly with the Creative Labs sound card. My wife didn&#8217;t enjoy the KDE experience, Firefox was OK for her but OpenOffice were terribly with the spreadsheets she used and finally, when our first kid was born, she attended some English lessons at Wall Street Institute and we found out that the online lessons required an odd combination of an old version on Java, ActiveX and IE&#8230; so she returned to Windows XP and never looked back.<\/p>\n<p>10 years is a LOT of time in computer systems but ALSA is still around, even on ev3dev. So I installed timidity++ and tried to play a MIDI file&#8230; to find that an ALSA module that is not currently available in ev3dev kernel is required just for MIDI.<\/p>\n<p>I googled for alternatives and found <a href=\"http:\/\/www.fluidsynth.org\/\">fluidsynth<\/a> with an unexpected bonus: there is a quite interesting python library, <a href=\"https:\/\/github.com\/bspaans\/python-mingus\">mingus<\/a>, that works with fluidsynth. So I installed it in my Ubuntu laptop and in a few minutes I was playing harp &#8211; amazing!<\/p>\n<pre>sudo apt-get install fluidsynthsudo easy_install mingus\r\npython\r\n&gt;&gt;&gt; from mingus.midi import fluidsynth\r\n&gt;&gt;&gt; from mingus.containers.note import Note\r\n&gt;&gt;&gt; fluidsynth.init(\"\/usr\/share\/sounds\/sf2\/FluidR3_GM.sf2\", \"alsa\")\r\n&gt;&gt;&gt; fluidsynth.set_instrument(1, 46)\r\n&gt;&gt;&gt; fluidsynth.play_Note(Note(\"C-3\"))<\/pre>\n<p>In the previous example I just import the fluidsynth and Note parts of the library, initialize fluidsynth to work with ALSA loading the soundfount that cames with it, choose harp (instrument number 46) and play C3.<\/p>\n<p>Well and polyphony? The correct way is to use a NoteContainer<\/p>\n<pre>from mingus.containers import NoteContainer\r\nfluidsynth.play_NoteContainer(NoteContainer([\"B-3\", \"C-3\", \"F-3\"]))<\/pre>\n<p>but the lazy way is&#8230; just play several notes in a fast sequence.<\/p>\n<p>So, let&#8217;s do it in the ev3dev!<\/p>\n<p>Oops, fluidsynth also needs an ALSA module not available in current ev3dev kernel.<\/p>\n<p>I&#8217;m not a linux music expert. Not even a linux expert! So after some more googling I gave up and <a href=\"https:\/\/github.com\/ev3dev\/ev3dev\/issues\/726\">asked for help<\/a> in ev3dev&#8217; GitHub project. And once again David accepted to include ALSA MIDI suport in future kernels, so I&#8217;ll just wait a bit.<\/p>\n<p>Oh, but I can&#8217;t wait&#8230;<\/p>\n<p>And if I read the color sensors in ev3dev and play the music in my laptop?<\/p>\n<p>ALSA, once again, suports something like client\/server MIDI communication with &#8220;aseqnet&#8221; and &#8220;aconnect&#8221; commands and some people are already <a href=\"https:\/\/www.raspberrypi.org\/forums\/viewtopic.php?t=47946&amp;p=454424\">using it with Raspberry Pi<\/a>!<\/p>\n<p>Yeah, I should have guessed&#8230; &#8220;aconnect&#8221; requires an ALSA MIDI module that is not available in current ev3dev kernel.<\/p>\n<p>OK, let&#8217;s use MQTT: configure my EV3 as a publisher and my Ubuntu laptop as a subscriber and just send some notes as messages.<\/p>\n<p>On the EV3:<\/p>\n<pre>sudo apt-get install mosquitto\r\nsudo easy_install paho-mqtt<\/pre>\n<p>The publisher script is &#8220;harp-mqtt-pub.py&#8221;:<\/p>\n<pre>#!\/usr\/bin\/env python\r\n\r\nfrom ev3dev.auto import *\r\nfrom time import sleep\r\nimport paho.mqtt.client as mqtt\r\n\r\nDELAY = 0.01\r\n\r\n# should have an auto-calibrate function\r\nAMB_THRESHOLD = 9\r\n\r\nsensor1 = ColorSensor('in1:i2c80:mux1')\r\nsensor1.mode = 'COL-AMBIENT'\r\nsensor2 = ColorSensor('in1:i2c81:mux2')\r\nsensor2.mode = 'COL-AMBIENT'\r\nsensor3 = ColorSensor('in1:i2c82:mux3')\r\nsensor3.mode = 'COL-AMBIENT'\r\nsensor4 = ColorSensor('in2')\r\nsensor4.mode = 'COL-AMBIENT'\r\nsensor5 = ColorSensor('in3')\r\nsensor5.mode = 'COL-AMBIENT'\r\nsensor6 = ColorSensor('in4')\r\nsensor6.mode = 'COL-AMBIENT'\r\n\r\n# there is no sensor7 yet, I need another MUX\r\n\r\ns1 = 0\r\ns2 = 0\r\ns3 = 0\r\ns4 = 0\r\ns5 = 0\r\ns6 = 0\r\ns7 = 0\r\n\r\nclient = mqtt.Client()\r\nclient.connect(\"localhost\",1883,60)\r\n\r\nprint 'Running...'\r\n\r\nwhile True:\r\n\u00a0\u00a0\u00a0 key_touched = False\r\n\u00a0\u00a0\u00a0 s1 = sensor1.value(0)\r\n\u00a0\u00a0\u00a0 s2 = sensor2.value(0)\r\n\u00a0\u00a0\u00a0 s3 = sensor3.value(0)\r\n\u00a0\u00a0\u00a0 s4 = sensor4.value(0)\r\n\u00a0\u00a0\u00a0 s5 = sensor5.value(0)\r\n\u00a0\u00a0\u00a0 s6 = sensor6.value(0)\r\n#\u00a0\u00a0\u00a0 s7 = sensor7.value(0)\r\n\r\n\u00a0\u00a0\u00a0 if s1 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"C-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\u00a0\u00a0\u00a0 if s2 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"D-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\u00a0\u00a0\u00a0 if s3 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"E-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\u00a0\u00a0\u00a0 if s4 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"F-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\u00a0\u00a0\u00a0 if s5 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"G-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\u00a0\u00a0\u00a0 if s6 &lt; AMB_THRESHOLD:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"A-3\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n#\u00a0\u00a0\u00a0 if s7 &lt; AMB_THRESHOLD:\r\n#\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 client.publish(\"topic\/Harp\", \"B-3\")\r\n#\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key_touched=True\r\n\r\n\u00a0\u00a0\u00a0 if key_touched == True:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sleep(DELAY)<\/pre>\n<p>On the Ubuntu laptop side:<\/p>\n<pre>sudo easy_install paho-mqtt<\/pre>\n<p>The subscriber script is &#8220;harp-mqtt-sub.py&#8221;<\/p>\n<pre>#!\/usr\/bin\/env python\r\n\r\nimport paho.mqtt.client as mqtt\r\nfrom mingus.midi import fluidsynth\r\nfrom mingus.containers.note import Note\r\n\r\nEV3_IP = \"192.168.43.35\"\r\n\r\nSOUNDFONT = 'Concert_Harp.sf2'\r\nINSTRUMENT = 46 # Harp\r\n\r\nNOTES = ['C-3','D-3','E-3','F-3','G-3','A-3','B-3']\r\n\r\ndef on_connect(client, userdata, flags, rc):\r\n\u00a0\u00a0\u00a0 print(\"Connected with result code \"+str(rc))\r\n\u00a0\u00a0\u00a0 client.subscribe(\"topic\/Harp\")\r\n\r\ndef on_message(client, userdata, msg):\r\n\u00a0\u00a0\u00a0 global i\r\n\u00a0\u00a0\u00a0 if (msg.payload in NOTES):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print msg.payload\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fluidsynth.play_Note(Note(msg.payload))\r\n\u00a0\u00a0 \u00a0\r\nclient = mqtt.Client()\r\nclient.connect(EV3_IP,1883,60)\r\n\r\nclient.on_connect = on_connect\r\nclient.on_message = on_message\r\n\r\nfluidsynth.init(SOUNDFONT, \"alsa\")\r\nfluidsynth.set_instrument(1, INSTRUMENT)\r\n\r\nclient.loop_forever()<\/pre>\n<p>And guess what? It works!!! I just love linux and open source!<\/p>\n<div class=\"jetpack-video-wrapper\"><iframe loading=\"lazy\" title=\"EV3 laser harp v0.2\" width=\"840\" height=\"473\" src=\"https:\/\/www.youtube.com\/embed\/eKW4_QbIFak?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<p>I will keep waiting for David Lechner to include ALSA MIDI support in ev3dev&#8217; kernel. I&#8217;m not so sure if there is enough horsepower in the EV3 to load a soundfont and play it with acceptable latency but if I can at least use the MIDI client\/server functionality I can drop MQTT.<\/p>\n<p>An interesting possibility that this client\/server design allows is to scale my harp easily: with just a second EV3 (2 MUX each) I can make a 13-string harp with almost no modification on my code.<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">This post is part 2  of 2 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/lego-laser-harp\" class=\"series-275\" title=\"LEGO Laser Harp\">LEGO Laser Harp<\/a><\/div><p>About 10 years ago I offered my wife a M-Audio USB MIDI Keyboard and installed Ubuntu Studio on a computer so she could play some piano at home. She was so amazed with the possibility to generate music sheet while playing that almost accepted the idea of using Linux&#8230; almost \ud83d\ude42 I remember that at &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2016\/lego-laser-harp-part-ii\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;LEGO laser harp &#8211; part II&#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":[13,157,154,18,19,158,148,20,98,26,156],"tags":[278,279,276],"series":[275],"class_list":["post-951","post","type-post","status-publish","format-standard","hentry","category-ev3dev","category-ev3dev-en","category-lego-en","category-lego","category-lego-mindstorms","category-lego-mindstorms-en","category-linux-en","category-linux","category-python","category-ubuntu","category-ubuntu-en","tag-harp","tag-midi","tag-music","series-lego-laser-harp"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-fl","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/951","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=951"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/951\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=951"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=951"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=951"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=951"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}