{"id":2814,"date":"2017-06-09T22:23:20","date_gmt":"2017-06-09T22:23:20","guid":{"rendered":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=2814"},"modified":"2020-06-06T11:22:53","modified_gmt":"2020-06-06T11:22:53","slug":"sonic-pi-advanced-programming","status":"publish","type":"post","link":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=2814","title":{"rendered":"Sonic Pi &#8211; Advanced programming"},"content":{"rendered":"\n<p>Recently I stumbled upon <strong>Sonic Pi<\/strong>, a <strong>sequencer<\/strong> with which you can generate music programmatically. There exist versions for Windows, Mac, Linux and Raspberry Pi (that&#8217;s where the names comes from). For Windows you can get it as stickware, no installation needed. And the best: it&#8217;s free!<\/p>\n\n\n\n<p>If you don&#8217;t have it yet, go and get it: <a href=\"http:\/\/sonic-pi.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/sonic-pi.net\/<\/a><\/p>\n\n\n\n<p>I was fascinated and spent hours exploring the endless possibilities of this software. As a developer my focus was on the possibilities of the programming language.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot.jpg\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"715\" src=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-1024x715.jpg\" alt=\"Sonic Pi Music Sequencer\" class=\"wp-image-2820\" srcset=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-1024x715.jpg 1024w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-300x210.jpg 300w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-768x537.jpg 768w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-150x105.jpg 150w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot-400x279.jpg 400w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/SonicPiScreenshot.jpg 1301w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>In this article I sum up some of the programming questions I stumbled upon. As Sonic Pi aims at electronic artist, musicians and music teachers, the documentation is much better on the musical possibilities than on documenting programming features. Just try to find such topics as operators or data types in the official Sonic Pi documentation!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Some sort of Ruby<\/h1>\n\n\n\n<p>This is not an introduction into Sonic Pi, the basics you can perfectly learn in the excellent tutorial integrated in the program. No need to repeat this here. As I said before, here I document some advanced undocumented topics. The most important thing you have to know is that the <strong>programming language of Sonic Pi is a simplified Ruby<\/strong>. If you don&#8217;t find an answer to your programming question in the official Sonic Pi documentation you can just google it&nbsp;with Ruby. Many features of Ruby work, just try it out.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">The wonders of division<\/h1>\n\n\n\n<p>Very early I stumbled over a phenomenon that can drive a programming newbie to tears. Just look at the following code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n\nmy_number1 = 5\/4\nprint my_number1 # result 1\n\nmy_number2 = 3\/4\nprint my_number2 # result 0\n\n<\/pre><\/pre>\n\n\n\n<p>Oops! As a Java programmer I&#8217;m not really astonished: <strong>The types of the two numbers define the type of the result<\/strong>. If you want to have a decimal as a result, at least one number has to be a decimal. If this is not the case, for example because the numbers are the lengths of lists (more of this later), then multiply one of them with 1.0, this will do the trick.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n\nmy_number1 = 1.0\/3\nprint my_number1 # result 0.3333333333333333\n\nmy_number2 = 1\/0.25\nprint my_number2 # result 4.0\n\nmy_number3 = 5\/4\nprint my_number3 # result 1\n\nmy_number4 = 3\/4\nprint my_number4 # result 0\n\nmy_number4 = (3*1.0)\/4\nprint my_number4 # result 0.75\n\n<\/pre><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Note Names and Note Numbers<\/h1>\n\n\n\n<p>When using play in Sonic Pi you can use it with the note name, for example :c4 or its number value 60.<\/p>\n\n\n\n<p>Of course, you can convert the names in numbers and vice versa.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n# from note name to note value\nprint :c4.to_i&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; 60\n\n# from note value to note name\nprint note_info(60).midi_string&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; C4\n\n# note name without octave\nprint Note.resolve_note_name(60) # =&amp;amp;amp;amp;gt; :C\n\nprint note_info(60).octave&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; 4\nprint note_info(60).pitch_class&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; :C\nprint note_info(60).midi_note&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; 60\nprint note_info(60).inspect&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; &quot;#&amp;amp;amp;amp;lt;SonicPi::Note :C4&amp;amp;amp;amp;gt;&quot;\n\n# convert midi to Hertz value\nprint midi_to_hz(:c4)&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; 261.6255653005986\n\n# calculate interval difference\nprint :c4 - :d4&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; # =&amp;amp;amp;amp;gt; -2\n\n# play midi_string\nplay note_info(61).midi_string\n<\/pre><\/pre>\n\n\n\n<p>Source: http:\/\/www.rubydoc.info\/github\/samaaron\/sonic-pi\/SonicPi\/Note#resolve_midi_note-class_method<\/p>\n\n\n\n<p>To make a <strong>lowercase symbol<\/strong> from the values of a scale is more complicated:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n#define a minor scale\nmy_scale = scale :c4, :minor, num_octaves: 1\n#fetch the second note and transform it to a symbol\nmy_note = note_info(my_scale&#91;1]).midi_string.downcase.to_sym\nprint my_note # output :d4\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">String Concatenation<\/h1>\n\n\n\n<p>What a word! Basically it&#8217;s just the question how can sew text snippets together. Why do we need this an a music sequencer? For debugging I recommend to print out messages to the protocol window. The beginning is easy: Just put a +-sign between to texts:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nprint \"Hello\" + \" World\"\n<\/pre><\/div>\n\n\n<p>Works like a charm! But then you want to know the length of a sample:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nprint \"Duration of ambi_glass_hum: \" + sample_duration :ambi_glass_hum\n<\/pre><\/div>\n\n\n<p>Don&#8217;t be astonished that this gives you an <strong>ugly error message.<\/strong> Of course, it&#8217;s types again. Although you see nothing like a type declaration, <strong>Sonic Pi is a typed language<\/strong>. And as the result of sample_duration is a number, this cannot be concatenated with a string. There are two solutions for this problem:<\/p>\n\n\n\n<ol><li>Use your number in the string with <strong>#{your_number}<\/strong><\/li><li>Convert the number to a string with <strong>.to_s<\/strong><\/li><\/ol>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_string_1 = \"one\"\nmy_string_2 = \"two\"\nmy_result_1 = \"my_result_1: #{my_string_1}, #{my_string_2}\"\nprint my_result_1\n\nmy_result_2 = \"my_result_2: \" + my_string_1 + \", \" + my_string_2\nprint my_result_2\n\nmy_length = sample_duration :ambi_glass_hum\nprint \"sample: #{my_length}\"\n# or\nprint \"sample: \" + my_length.to_s\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">Arrays, Maps and Rings<\/h1>\n\n\n\n<p>As many other programming languages, Sonic Pi knows <strong>arrays<\/strong> (or lists, there seems to be no difference) and <strong>maps<\/strong>. I can use these to save sequences of notes or note lengths. But there is a third element, which is very specific to music sequencers: <strong>rings<\/strong>. A <strong>ring<\/strong> is nothing else than <strong>an array that automatically starts again when it has reached the last element<\/strong>. This is very handy because in Sonic Pi you don&#8217;t work with counters as in a conventional progamming language (although it is possible). The universal counter that controls all your parallel loops is the <strong>tick<\/strong>. And as the loops can run a long time, the ticks will soon be much larger than the length of any array. If you convert an array, you don&#8217;t have to care for your index, Sonic Pi handles this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">From lists to rings and back<\/h2>\n\n\n\n<p>So it&#8217;s very useful, if you know how to convert an array to a ring and back with .ring and .to_a. Here is the code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_ring = &#91;1, 2, 3].ring\nmy_array = my_ring.to_a\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Reusable procedures with lists<\/h2>\n\n\n\n<p>But why use these collections at all? As a software developer, I&#8217;m interested in reusability. I don&#8217;t want to write dozens of lines of code for every new melody. My vision is to make procedures that can play any sort of melody you give them as an argument. The most simple form is a procedure with to arguments, a list of notes and list of note lengths.<\/p>\n\n\n\n<p>Another important property of lists and maps is its lenght. You can get it just with .lenght, for example <strong>[1, 2, 3].length<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n#use this procedure to play any simple melody\ndefine :play_my_melody do |my_note_list, my_sleep_list|\n  tick_reset(:my_melody_tick)\n  my_length = my_note_list.length\n\n  my_length.times do\n    my_counter = tick(:my_melody_tick)\n    play my_note_list.ring&#91;my_counter]\n    sleep my_sleep_list.ring&#91;my_counter]\n  end\nend\n\nmy_melody_twinkle = &#91;:c4, :c4, :g4, :g4, :a4, :a4, :g4]\nmy_sleep_twinkle = &#91;1, 1, 1, 1, 1, 1, 2]\nplay_my_melody my_melody_twinkle, my_sleep_twinkle\nsleep 2\n\nmy_melody_godownmoses = &#91;:d4, :bb4, :bb4, :a4, :a4, :bb4, :bb4, :g4]\nmy_sleep_godownmoses = &#91;1, 1, 1, 1, 1, 1, 1, 2]\nplay_my_melody my_melody_godownmoses, my_sleep_godownmoses\n<\/pre><\/div>\n\n\n<p>From a musical standpoint the result is not really convincing, but as a program it works.<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/blog_simple_melody_twinkle.mp3\"><\/audio><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Readability with nested lists<\/h2>\n\n\n\n<p>The weaknesses of this first version are evident: My control over the sound is pretty limited with the result, that the melody sounds extremely mechanical. And the t<strong>wo list must have the same length<\/strong>. With a longer melody it can be a pretty tedious task to count which note has which length. It would be nice to be able to safe a note and its length together. And even better if I could use more of the endless possibilities to change single note, for example its loudness. This is possible, if I use a <strong>nested array<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n#use this procedure to play any simple melody\ndefine :play_my_melody do |my_melody_list|\n  #reset the local tick\n  tick_reset(:my_melody_tick)\n  my_length = my_melody_list.length\n\n  #loop through the notes of the outer list\n  my_length.times do\n    my_counter = tick(:my_melody_tick)\n    #fetch the first element of the inner list\n    play my_melody_list.ring&#91;my_counter]&#91;0]\n    #fetch the second element of the inner list\n    sleep my_melody_list.ring&#91;my_counter]&#91;1]\n  end\nend\n\nmy_melody_godownmoses = &#91;&#91;:d4, 1],\n&#91;:bb4, 1],\n&#91;:bb4, 1],\n&#91;:a4,  1],\n&#91;:a4,  1],\n&#91;:bb4, 1],\n&#91;:bb4, 1],\n&#91;:g4,  2]\n]\nplay_my_melody my_melody_godownmoses\n<\/pre><\/div>\n\n\n<p>It sounds as mechanical as before, but at least the code is more readable and a melody is easier to write. And you see, that with a third or a forth element in the nested array I can control other aspects like the amplitude (loudness). I leave it to you to go on in this direction.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ruby Hashes (Hash Maps)<\/h2>\n\n\n\n<p>A very useful element in Ruby are hashes (in other programming languages called hash maps or just maps). Hashes&nbsp;store keys and their values. There are several ways to define a map:<\/p>\n\n\n\n<p>The first syntax I found only for Sonic Pi, but not for Ruby:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_map = (map note: :c4, times: 4, amp: 0.5, bpm: 120)\n<\/pre><\/div>\n\n\n<p>The second syntax is pure Ruby and the shortest and most elegant way:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_map3 = {note: :c4, times: 4, amp: 0.5, bpm: 120}\n<\/pre><\/div>\n\n\n<p>The third syntax is called hash rocket syntax in Ruby. It&#8217;s quite awkward, I wouldn&#8217;t use it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_map3 = {:note =&gt; :c4, :times =&gt; 4, :amp =&gt; 0.5, :bpm =&gt; 120}\n<\/pre><\/div>\n\n\n<p>And that&#8217;s how you use the named values:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nplay my_map2&#91;:note], amp: my_map2&#91;:amp]\n<\/pre><\/div>\n\n\n<p>Of course, Ruby hashes are objects with a lot of useful methods:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n#show all keys\nprint my_map2.keys\n\n#show all values\nprint my_map2.values\n\n#iterate over map\nmy_map2.each {|key, value| print \"#{key} is #{value}\" }\n\n#iterate over keys\nmy_map2.each_key {|key| print \"#{key} is #{my_map2&#91;key]}\" }\n\n#is key existing\nprint 'my_map2.has_key?(:note): ' + my_map2.has_key?(:note).to_s\nprint \"my_map2.has_key?(:x): #{my_map2.has_key?(:x)}\"\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Defaulting Option maps as arguments<\/h2>\n\n\n\n<p>Some things I want to control only once per melody, for exaple, how quick it is played or with which instrument it is played. Instead of using another array to control general settings like beats per minute (bpm) and the instrument (synth), I could <strong>use a map<\/strong>. This is <strong>more readable<\/strong> and I can <strong>program a fallback for all the settings that are not in the map<\/strong>.<\/p>\n\n\n\n<p>This is the combined code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n#use this procedure to play any simple melody\ndefine :play_my_melody do |my_melody_list, my_option_map|\n  #this inline if falls back to a bpm of 80\n  #if no element bpm is present in the map\n  use_bpm my_option_map&#91;:bpm] == nil ? 80 : my_option_map&#91;:bpm]\n\n  #fallback to piano if there is no element synth\n  use_synth my_option_map&#91;:synth] == nil ? :piano : my_option_map&#91;:synth]\n\n  #reset the local tick\n  tick_reset(:my_melody_tick)\n  my_length = my_melody_list.length\n\n  #the melody is repeated once if the map contains no times element\n  my_times = my_option_map&#91;:times] == nil ? 1 : my_option_map&#91;:times]\n\n  #repeat the whole melody\n  my_times.times do\n    #loop through the notes of the outer list\n    my_length.times do\n      my_counter = tick(:my_melody_tick)\n      #fetch the first element of the inner list\n      play my_melody_list.ring&#91;my_counter]&#91;0]\n      #fetch the second element of the inner list\n      sleep my_melody_list.ring&#91;my_counter]&#91;1]\n    end\n  end\nend\n\n#my_option_map = (map times: 2, bpm: 100, synth: :prophet)\nmy_option_map = (map times: 1, synth: :beep)\nmy_melody_godownmoses = &#91;&#91;:d4, 1],\n&#91;:bb4, 1],\n&#91;:bb4, 1],\n&#91;:a4,  1],\n&#91;:a4,  1],\n&#91;:bb4, 1],\n&#91;:bb4, 1],\n&#91;:g4,  2]\n]\nplay_my_melody my_melody_godownmoses, my_option_map\n<\/pre><\/div>\n\n\n<p>This last example uses some other advanced stuff: <strong>Inline-Ifs<\/strong>. I take it for granted that you know the normal if. A more compact form, which exists also in other programming languages, compresses the three parts, condition, then part, else part just in one line, separated by ? and <strong>:<\/strong>.<\/p>\n\n\n\n<p>In the line &#8220;use_bpm my_option_map[:bpm] == nil ? 80 : my_option_map[:bpm]&#8221;, the condition is &#8220;my_option_map[:bpm] == nil&#8221;, the then part is &#8220;80&#8221; and the else part is &#8220;my_option_map[:bpm]&#8221;. The result of this inline if gives you the value for use_bpm.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Looping over a list or map<\/h2>\n\n\n\n<p>With the method <strong>.each<\/strong> you can loop over a list or map. This can be used to listen to all available synths, as the function&nbsp;<strong>synth_names<\/strong> gives you a list of all synths.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nsynth_names.each do |my_synth|\n  use_synth my_synth\n  play :c4\n  sleep 1\n  play :e4\n  sleep 2\nend\n\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Merging maps<\/h2>\n\n\n\n<p>Sometimes it&#8217;s useful to split someting into more than one map. With the following code the maps can be merged again:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_map = my_map.merge(my_map_external)\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">Colons in front or after?<\/h1>\n\n\n\n<p>You may survive sonic pi programming quite well without knowing why the colons are sometimes in front and sometimes after. There event exists :: in Ruby, but in Sonic Pi I doubt that you ever will see it. Let me try to explain the mystery of colons:<\/p>\n\n\n\n<p>If&nbsp;a colon is&nbsp;<strong>in front<\/strong> of a string, it defines a <strong>symbol<\/strong>. Symbols in Ruby are <strong>immutable<\/strong> and <strong>reusable<\/strong> constants. They are often used instead of string variables, because <strong>two symbols with the same name are identical<\/strong> and <strong>exist only once in memory<\/strong>. This makes comparing symbols really <strong>fast<\/strong>.<\/p>\n\n\n\n<p>I assume that this performance advantage is the main reason, why you see them so often in Sonic Pi. With music you don&#8217;t want&nbsp;any programming to delay your sound, especially if you are not on a desktop or notebook but on a microcontroller like the raspberry pi with its limited memory and CPU.<\/p>\n\n\n\n<p>A colon after a string we have just seen in the chapter of hashes: In a hash in the short syntax version, the key name is followed by a colon and then by the value:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_map3 = {note: :c4, times: 4, amp: 0.5, bpm: 120}\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">Working with the length of samples<\/h1>\n\n\n\n<p>In Sonic Pi you work not only with notes (synth and play), but also with <strong>samples<\/strong>, recordes snippets of music. Samples have a certain length. This might be a problem, if the sample length goes not along with your tick.<\/p>\n\n\n\n<p>There are two solutions for this problem. The first one is to read the <strong>length of the sample with sample_duration<\/strong> and to set the following sleep to this length. The second one is to <strong>stretch or compress it with beat_stretch<\/strong> according to your needs. But be careful, these manipulations change not only the length, but also the tone height. If you compress it, it becomes shorter and higher. If you stretch it, it becomes longer and deeper.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nprint sample_duration :ambi_dark_woosh # result: 3.702...\n\n#play sample in full length\nsample :ambi_dark_woosh\nsleep sample_duration :ambi_dark_woosh\nsleep 0.5\n\n#make it longer\nsample :ambi_dark_woosh, beat_stretch: 5\nsleep 5\nsleep 0.5\n\n#make it shorter\nsample :ambi_dark_woosh, beat_stretch: 2\nsleep 2\nsleep 0.5\n\nsample :ambi_dark_woosh, beat_stretch: 1\nsleep 1\nsleep 0.5\n<\/pre><\/div>\n\n\n<p>Listen by yourself:<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2017\/06\/blog_sample_duration.mp3\"><\/audio><figcaption>Sonic Pi Sample Duration<\/figcaption><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">OSC and Python<\/h1>\n\n\n\n<p>Since Sonic Pi 3 there exists an interface to control Sonic Pi from an external application. The means for this is <a href=\"https:\/\/en.wikipedia.org\/wiki\/Open_Sound_Control\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"OSC (Open Sound Control). (\u00f6ffnet in neuem Tab)\">OSC (Open Sound Control).<\/a> I tried the example with Python that can be found in the link below. Python should already be installed. Before you can start, you have to load the necessary library with the following steps in Windows:<\/p>\n\n\n\n<ul><li>open a command line<\/li><li>type &#8220;pip3 install python-osc&#8221; and press Return<\/li><li>you should a message like &#8220;Successfully installed python-osc-1.7.0&#8221;<\/li><li>control whether the package was installed with &#8220;pip3 list&#8221;<\/li><\/ul>\n\n\n\n<p>In Sonic Pi you should start a basic OSC listener as described in the link below. Just copy the code in the editor and run it. Don&#8217;t worry, you will hear&nbsp;nothing yet. Here is my slightly changed version of the listener code in Sonic Pi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nlive_loop :my_loop do\n use_real_time\n a, b, c, d, e = sync \"\/osc\/trigger\/synth\"\n print a\n synth a.to_sym, note: b, cutoff: c, sustain: d, amp: e\nend\n<\/pre><\/div>\n\n\n<p>Now you can open your <strong>python<\/strong> tool and copy the&nbsp;python code. As soon as you run it, you will hear a sound:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nfrom pythonosc import osc_message_builder\nfrom pythonosc import udp_client\n\nsender = udp_client.SimpleUDPClient('127.0.0.1', 4559)\nsender.send_message('\/trigger\/synth', &#91;\"prophet\", 60, 100, 8, 0.5])\nsender.send_message('\/trigger\/synth', &#91;\"dpulse\", 62, 100, 8, 1])\n<\/pre><\/div>\n\n\n<p>Source:&nbsp;<a href=\"https:\/\/github.com\/samaaron\/sonic-pi\/blob\/master\/etc\/doc\/tutorial\/12.1-Receiving-OSC.md\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/github.com\/samaaron\/sonic-pi\/blob\/master\/etc\/doc\/tutorial\/12.1-Receiving-OSC.md<\/a><\/p>\n\n\n\n<p>In the meantime I have written another article <a rel=\"noopener noreferrer\" href=\"https:\/\/blog.ecotronics.ch\/wordpress\/2019\/tablet-as-drum-pad-for-sonic-pi\/\" target=\"_blank\">how to control Sonic Pi with an android tablet<\/a> by OSC.\u00a0<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Modularisation<\/h1>\n\n\n\n<p>Unfortunately, there is <strong>no such thing as include<\/strong> in Sonic Pi to load stuff from another file. There exists the <strong>load_buffer<\/strong> command, but with this you can only replace the code in your buffer window with the one from a file. That&#8217;s not exactly a replacement for include. However, <strong>definitions of functions are global for all buffer windows<\/strong>. A way to modularization would therefore be to place often used functions in a seperate file. Before you can use them, you load them with load_buffer, for example (Windows version):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nload_buffer \"D:\/my_directory\/my_pattern.rb\"\n<\/pre><\/div>\n\n\n<p>As I have a lot of samples and user defined synths on my NAS, which is not always running, the following code is quite useful to find out whether the NAS is on.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\nmy_external_root = \"Z:\/my_directory\/\"\nif File.exists?(my_external_root)\n  my_external_sample_directory = my_external_root + \"freewavesamplescom\/korg\/\"\n  my_sample_hat = my_external_sample_directory + \"korg-n1r-closed-hi-hat.wav\"\n  load_sample my_sample_hat\nelse\n  print \"NAS not loaded or mapped, map to drive Z:\"\nend\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">More Sonic Pi stuff<\/h1>\n\n\n\n<p>Well, for the moment, that&#8217;s all from me. But of course there is a lot of stuff out there, here some of my favority links:<\/p>\n\n\n\n<ul><li><a href=\"https:\/\/www.raspberrypi.org\/magpi-issues\/Essentials_Sonic_Pi-v1.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.raspberrypi.org\/magpi-issues\/Essentials_Sonic_Pi-v1.pdf<\/a>: A whole 110 pages about Sonic Pi<\/li><li><a href=\"http:\/\/sonic-pi.mehackit.org\/exercises\/en\/01-introduction\/01-introduction.html\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/sonic-pi.mehackit.org\/exercises\/en\/01-introduction\/01-introduction.html<\/a>: A very good tutorial, which helped me especially with external samples<\/li><li><a href=\"http:\/\/ruby-doc.com\/docs\/ProgrammingRuby\/\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/ruby-doc.com\/docs\/ProgrammingRuby\/<\/a>: Just what the title says, tutorial about programming Ruby<\/li><li><a href=\"https:\/\/learnxinyminutes.com\/docs\/de-de\/ruby-de\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/learnxinyminutes.com\/docs\/de-de\/ruby-de\/<\/a>: A compact Ruby tutorial in German<\/li><li><a href=\"https:\/\/gistpages.com\/posts\/ruby_arrays_insert_append_length_index_remove\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gistpages.com\/posts\/ruby_arrays_insert_append_length_index_remove<\/a>: Some more stuff about arrays in Ruby<\/li><li><a href=\"https:\/\/docs.ruby-lang.org\/en\/2.5.0\/Hash.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/docs.ruby-lang.org\/en\/2.5.0\/Hash.html<\/a>: Some stuff about hashes in Ruby<\/li><\/ul>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n\n\n\n<p><span style=\"border-radius: 2px; text-indent: 20px; width: auto; padding: 0px 4px 0px 0px; text-align: center; font: bold 11px\/20px 'Helvetica Neue',Helvetica,sans-serif; color: #ffffff; background: #bd081c no-repeat scroll 3px 50% \/ 14px 14px; position: absolute; opacity: 1; z-index: 8675309; display: none; cursor: pointer; top: 180px; left: 277px;\">Merken<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"\n<p>Recently I stumbled upon Sonic Pi, a sequencer with which you can generate music programmatically. There exist versions for Windows, Mac, Linux and Raspberry Pi (that&#8217;s where the names comes from). For Windows you can get it as stickware, no installation needed. And the best: it&#8217;s free!<\/p>\n<p>If you don&#8217;t have it yet, go [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":2820,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[375,130,3,377,319],"tags":[321,323,349,324,350,347,348,320,322],"_links":{"self":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2814"}],"collection":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2814"}],"version-history":[{"count":77,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2814\/revisions"}],"predecessor-version":[{"id":3119,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2814\/revisions\/3119"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/2820"}],"wp:attachment":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}