├── 01-play-a-note.rb ├── 02-play-notes-in-a-row.rb ├── 03-attack.rb ├── 04-release.rb ├── 05-attack-and-release.rb ├── 06-text-output.rb ├── 07-loop.rb ├── 08-synths.rb ├── 09-tempo-play-pattern.rb ├── 10-play-pattern-timed.rb ├── 11-chord.rb ├── 12-thread.rb ├── 13-global-local.rb ├── 14-ruby-variables.rb ├── 15-ruby-conditional.rb ├── 16-ruby-while.rb ├── 17-ruby-iterable.rb ├── 18-ruby-object-operations.rb ├── LICENSE └── README.md /01-play-a-note.rb: -------------------------------------------------------------------------------- 1 | # Lines starting with a # (like this one) are comments ignored by the computer 2 | # Sonic-Pi uses the midi note system 3 | # Each note has a number value 4 | # 60 is a C note 5 | # To play a note we use a command : play 6 | # We need to give the command an argument which is the note number to play 7 | 8 | # command = play 9 | # argument = 60 10 | play 60 11 | -------------------------------------------------------------------------------- /02-play-notes-in-a-row.rb: -------------------------------------------------------------------------------- 1 | # If we want to play successive notes we need to put a sleep inbetween notes 2 | # To do this we use the command : sleep 3 | # The sleep command makes the computer wait 4 | # We need to give it an argument or value which is a number of seconds 5 | # This can also be a fractional value such as 0.5 for half a second 6 | 7 | play 60 8 | # command = sleep 9 | # argument = 0.5 (half a second) 10 | sleep 0.5 11 | play 68 12 | -------------------------------------------------------------------------------- /03-attack.rb: -------------------------------------------------------------------------------- 1 | # A note rises in volume to a peak (the attack) and then decreases (the release) 2 | # To control the time taken for the rise and fall we give additional arguments 3 | # The play command can take multiple arguments, each one separated by a comma , 4 | # To change the rise we use a pair of arguments 5 | # The first one is : "attack" 6 | # The double quotes are required 7 | # This first argument is separated from the next by a comma 8 | # The second argument is the time taken in seconds for the rise 9 | 10 | # If you execute this script you hear the time for the rise in volume increase 11 | 12 | # command = play 13 | # argument 1 = 60 14 | # argument 2 = "attack" 15 | # argument 3 = 0.25 16 | play 60, "attack", 0.25 17 | sleep 1 18 | 19 | play 60, "attack", 0.5 20 | sleep 1 21 | 22 | play 60, "attack", 0.75 23 | sleep 1 24 | 25 | play 60, "attack", 1.0 26 | 27 | -------------------------------------------------------------------------------- /04-release.rb: -------------------------------------------------------------------------------- 1 | # A note rises in volume to a peak (the attack) and then decreases (the release) 2 | # To control the time taken for the rise and fall we give additional arguments 3 | # The play command can take multiple arguments, each one separated by a comma , 4 | # To change the fall we use a pair of arguments 5 | # The first one is : "release" 6 | # The double quotes are required 7 | # This first argument is separated from the next by a comma 8 | # The second argument is the time taken in seconds for the fall 9 | 10 | # If you execute this script you hear the time for the fall in volume increase 11 | 12 | # command = play 13 | # argument 1 = 60 14 | # argument 2 = "release" 15 | # argument 3 = 0.25 16 | play 60, "release", 0.25 17 | sleep 1 18 | 19 | play 60, "release", 0.5 20 | sleep 1 21 | 22 | play 60, "release", 0.75 23 | sleep 1 24 | 25 | play 60, "release", 1.0 26 | sleep 1 27 | 28 | play 60, "release", 1.5 29 | 30 | -------------------------------------------------------------------------------- /05-attack-and-release.rb: -------------------------------------------------------------------------------- 1 | # A note rises in volume to a peak (the attack) and then decreases (the release) 2 | # To control the time taken for the rise and fall we give additional arguments 3 | # The play command can take multiple arguments, each one separated by a comma , 4 | # We can change both rise and fall at the same time using multiple arguments 5 | 6 | # command = play 7 | # argument 1 = 60 8 | # argument 2 = "attack" 9 | # argument 3 = 0.25 10 | # argument 4 = "release" 11 | # argument 5 = 0.25 12 | play 60, "attack", 0.25, "release", 0.75 13 | sleep 1 14 | 15 | play 60, "attack", 0.25, "release", 1.0 16 | sleep 1 17 | 18 | play 60, "attack", 0.25, "release", 1.5 19 | sleep 1 20 | 21 | play 60, "attack", 0.5, "release", 1.5 22 | sleep 1 23 | 24 | play 60, "attack", 1.0, "release", 1.5 25 | 26 | -------------------------------------------------------------------------------- /06-text-output.rb: -------------------------------------------------------------------------------- 1 | # To print text to the Output panel we use the command : puts 2 | # The argument is a piece of text known as a String 3 | # Text surrounded by double quotes is a String 4 | # For example : "this is a string" 5 | 6 | # command = puts 7 | # argument = "play 1st note" 8 | puts "play 1st note" 9 | play 60 10 | sleep 1 11 | puts "play 2nd note" 12 | play 76 13 | -------------------------------------------------------------------------------- /07-loop.rb: -------------------------------------------------------------------------------- 1 | # If we want to do the same thing multiple times we use a loop 2 | # This is a block of code statements that are executed a number of times 3 | # To do this we use N.times where N can be 1,2,3... 4 | # Each block of code to be repeated must be surrounded by do and end 5 | # Alternatively use curly brackets { } 6 | # You should indent any code in a loop by 4 spaces at the start of each line 7 | 8 | puts "start first loop" 9 | 3.times do 10 | # Note all these lines indented by 4 spaces 11 | play 60 12 | sleep 0.5 13 | play 68 14 | sleep 0.5 15 | play 76 16 | sleep 0.5 17 | end 18 | 19 | puts "sleep for a second" 20 | sleep 1 21 | 22 | puts "start second loop" 23 | 3.times { 24 | play 76 25 | sleep 0.5 26 | play 68 27 | sleep 0.5 28 | play 60 29 | sleep 0.5 30 | } 31 | -------------------------------------------------------------------------------- /08-synths.rb: -------------------------------------------------------------------------------- 1 | # There are multiple instruments or synthesisers available in Sonic-Pi 2 | # The current synthesiser is selected with the command : use_synth 3 | # The argument is the name of a synthesiser as a string 4 | # The available synths are (note some names have an underscore): 5 | # "dull_bell" 6 | # "pretty_bell" 7 | # "beep" 8 | # "saw_beep" 9 | # "fm" 10 | # If no synth is selected, then "pretty_bell" is used 11 | 12 | 13 | use_synth "dull_bell" 14 | play 60 15 | sleep 1 16 | use_synth "pretty_bell" 17 | play 60 18 | sleep 1 19 | use_synth "beep" 20 | play 60 21 | sleep 1 22 | use_synth "saw" 23 | play 60 24 | sleep 1 25 | use_synth "fm" 26 | play 60 27 | sleep 1 28 | 29 | -------------------------------------------------------------------------------- /09-tempo-play-pattern.rb: -------------------------------------------------------------------------------- 1 | # If our notes are separated by the same sleep time we can use the command : play_pattern 2 | # play_pattern takes an argument that is a set of notes, known as an Array 3 | # An array is a set of values separated by commas surrounded by square brackets 4 | # The play_pattern command uses the current tempo to define the sleep time 5 | # Tempo is the number of beats per minute 6 | # The current tempo can be set using the command : use_bpm 7 | # use_bpm has an argument which is the beats per minute value 8 | # The tempo defaults to 60 beats per minute if no tempo is defined 9 | # The current tempo can be found using the command current_bpm 10 | 11 | use_bpm 120 12 | # If you look at the output window this is the time per beat 13 | # 60 seconds in a minute 14 | # 120 beats per minute 15 | # Therefore seconds per beat = 60/120 = 0.5 16 | puts "bpm= #{current_bpm}" 17 | 18 | # command = play_pattern 19 | # argument = [60,68,76] 20 | play_pattern [60,68,76] 21 | 22 | sleep 1 23 | 24 | use_bpm 240 25 | # If you look at the output window this is the time per beat 26 | # 60 seconds in a minute 27 | # 240 beats per minute 28 | # Therefore seconds per beat = 60/240 = 0.25 29 | puts "bpm= #{current_bpm}" 30 | play_pattern [60,68,76] -------------------------------------------------------------------------------- /10-play-pattern-timed.rb: -------------------------------------------------------------------------------- 1 | # If we have a set of notes separated with different sleep times 2 | # We can use the command : play_pattern_timed 3 | # This takes 2 arguments 4 | # The first is a set of notes, known as an Array 5 | # The second is a set of times, also an Array 6 | # If the set of times contains fewer values than sleep gaps, it will repeat the sleep time sequence 7 | # An Array with two sleep times is [Time 1, Time 2] 8 | # If more times were needed after Time 2 it would reuse Time 1 and then Time 2 and so on 9 | 10 | # For example 11 | puts "The concise form" 12 | # This is a concise form of the below sequence of notes in Array 13 | 14 | # command = play_pattern_timed 15 | # argument 1 = [60,68,76,82,84] 16 | # argument 2 = [0.5,1] 17 | play_pattern_timed [60,68,76,82,84], [0.5,1] 18 | 19 | puts "The Long Form" 20 | sleep 2 21 | # The previous can be written in an expanded form as below 22 | # Note 1 23 | play 60 24 | # Time 1 25 | sleep 0.5 26 | # Note 2 27 | play 68 28 | # Time 2 29 | sleep 1 30 | # Note 3 31 | play 76 32 | # Time 1 33 | sleep 0.5 34 | # Note 4 35 | play 82 36 | # Time 2 37 | sleep 1 38 | # Note 5 39 | play 84 40 | 41 | puts "With a release value" 42 | sleep 2 43 | # We can also apply a release value to all notes in the Array 44 | play_pattern_timed [60,68,76], [1,2],"release",1 45 | -------------------------------------------------------------------------------- /11-chord.rb: -------------------------------------------------------------------------------- 1 | # If we wanted to play multiple notes at once we use the command : play_chord 2 | # play_chord takes an argument which is an Array of Notes (the chord) 3 | 4 | # command = play_chord 5 | # argument = [60,68,76] 6 | play_chord [60,68,76] 7 | sleep 1 8 | # We can also apply a release to a chord 9 | # Note the first argument is separated from the command by a space 10 | # But the additional arguments are separated by commas 11 | play_chord [60,68,76], "release", 1.5 12 | -------------------------------------------------------------------------------- /12-thread.rb: -------------------------------------------------------------------------------- 1 | # If we want multiple patterns of notes to play simultaneously we use threads 2 | # Each thread works independently and executes the code block contained by do and end 3 | # For example on a piano you would have the left hand and right hand 4 | # To define a block as belonging to a thread we use : in_thread 5 | # The block of code should be contained in a do and end 6 | 7 | # The notes play alternately and then simultaneously in each thread 8 | 9 | #left-hand 10 | in_thread(name: :lh) do 11 | play 60 12 | sleep 1 13 | play 62 14 | sleep 1 15 | play 64 16 | sleep 1 17 | play 66 18 | sleep 1 19 | play 68 20 | sleep 1 21 | play 70 22 | end 23 | 24 | #right-hand 25 | in_thread(name: :rh) do 26 | use_synth "saw" 27 | sleep 0.5 28 | play 68 29 | sleep 1 30 | play 66 31 | sleep 1 32 | play 64 33 | sleep 0.5 34 | play 62 35 | sleep 1 36 | play 60 37 | sleep 1 38 | play 58 39 | end 40 | -------------------------------------------------------------------------------- /13-global-local.rb: -------------------------------------------------------------------------------- 1 | # You can see that the threads use different tempo/bpm 2 | # The right hand thread inherits the setting from the main section 3 | # The left hand thread use a tempo local to that thread 4 | 5 | use_bpm 40 6 | puts "before threads tempo = #{current_bpm}" 7 | 8 | #left hand 9 | in_thread do 10 | use_bpm 120 11 | use_synth "saw_beep" 12 | puts "In left hand tempo = #{current_bpm}" 13 | play_pattern [60,68,76] 14 | end 15 | 16 | #right hand 17 | in_thread do 18 | use_synth "dull_bell" 19 | puts "In right hand tempo = #{current_bpm}" 20 | sleep 0.25 21 | play_pattern [76,68,60] 22 | end 23 | -------------------------------------------------------------------------------- /14-ruby-variables.rb: -------------------------------------------------------------------------------- 1 | # We can use variables to store values 2 | # A variable is a named representation that can hold different values 3 | # We assign values to a variable by using the equals sign = 4 | # If the variable does not already exist it is created by the computer 5 | 6 | # variable : note 7 | # value : 60 8 | note = 60 9 | puts "note is #{note}" 10 | 11 | # Wherever we use the variable note, it is replaced by the chosen value 12 | play note 13 | sleep 2 14 | 15 | # We can also do some maths on a variable 16 | # note(new value) = note (old value) + 1 17 | # For example here : 18 | # note (old value) = 60 19 | # so note becomes : note = 60 + 1 = 61 20 | note = note + 1 21 | puts "note is #{note}" 22 | play note 23 | sleep 2 24 | 25 | # Another shorter form of writing this is 26 | note += 1 # note = note + 1 27 | puts "note is #{note}" 28 | play note 29 | sleep 2 30 | 31 | 6.times do 32 | note += 1 # note = note + 1 33 | puts "In loop note is #{note}" 34 | play note 35 | sleep 0.25 36 | end 37 | 38 | #We can also go down 39 | 6.times do 40 | puts "In loop note is #{note}" 41 | play note 42 | sleep 0.25 43 | note -= 1 # note = note - 1 44 | end 45 | 46 | # We reassign the value of note at any time 47 | note = 50 48 | puts "note is #{note}" 49 | play note 50 | sleep 2 51 | 52 | 53 | # Sonic-Pi will play decimal numbers such as 60.7 but this doesn't match MIDI notes 54 | note = 60.6 55 | puts "note is #{note}" 56 | play note 57 | sleep 2 58 | # But we have to round to the nearest integer (whole number) to make sense 59 | # To do this we use the method : round 60 | # We do this by writing : note.round 61 | note = note.round 62 | puts "note is #{note}" 63 | play note 64 | sleep 2 65 | 66 | # We can also multiply and divide variables in the same way 67 | 6.times do 68 | note *= 1.1 # note = note * 1.1 69 | note = note.round 70 | puts "In loop note is #{note}" 71 | play note 72 | sleep 0.25 73 | end -------------------------------------------------------------------------------- /15-ruby-conditional.rb: -------------------------------------------------------------------------------- 1 | # A conditional is a logical comparison or test 2 | # Depending on whether this test passes or fails the program alters 3 | # To make an exact equals comparison we use : == 4 | # Note single equal is used for assigning a value to a variable 5 | # Other comparisions are: 6 | # greater than : > 7 | # greater than or equal to : > 8 | # less than : < 9 | # less than or equal to : <= 10 | # not equal to : != 11 | # The comparison evaluates to True or False 12 | # The result of this comparison defines which code section is executed 13 | # The conditional constructs used for this can be one of three types : 14 | # if 15 | # if else 16 | # if elsif else 17 | 18 | # conditional : if 19 | # This uses conditionals to control whether a piece of code is executed 20 | # This is based on the current value of the variable : note 21 | note = 59 22 | puts "note=#{note}" 23 | puts "is note equal to 59?#{(note == 59)}" 24 | if (note == 59) 25 | puts "this is executed as note is equal" 26 | play note 27 | end # Note an If must be closed with an end 28 | 29 | sleep 1 30 | 31 | # The value of note is now different 32 | note = 61 33 | puts "note=#{note}" 34 | puts "is note equal to 59?#{(note == 59)}" 35 | if (note == 59) 36 | puts "this is not executed" 37 | play note 38 | end 39 | 40 | sleep 1 41 | 42 | note = 66 43 | puts "note=#{note}" 44 | 45 | puts "is note not equal to 59?#{(note != 59)}" 46 | if (note != 59) 47 | puts "this is executed as note not equal" 48 | play note 49 | end 50 | 51 | sleep 1 52 | 53 | # conditional : if else 54 | note = 64 55 | puts "note=#{note}" 56 | puts "is note equal to 59?#{(note == 59)}" 57 | if (note == 59) 58 | puts "this is not executed" 59 | play note 60 | else 61 | puts "this else section is executed" 62 | play 50 63 | sleep 0.5 64 | play note 65 | end 66 | 67 | sleep 2 68 | 69 | # conditional : if elsif else 70 | # This plays notes in an ascending order 71 | # The notes go from an initial value to a specified maximum value 72 | # A shorter sleep time is used when the note is more than a specified value 73 | # When the note 76 is reached the loop is exited 74 | puts "Starting loop with conditionals" 75 | # This defines our starting or initial note 76 | note = 62 77 | # This defines the last note when the longer sleep time is used 78 | transitionNote = 68 79 | # This defines the last note that will be played before loop exit 80 | highestNote = 77 81 | 82 | # This will repeat forever unless the loop is broken out of 83 | loop do 84 | play note 85 | puts "Is note more than or equal to highestNote?" 86 | puts (note >= highestNote) 87 | puts "Is note more than transitionNote?" 88 | puts (note > transitionNote) 89 | # The test in the elsif is only done when the IF test is false 90 | # The code in the else block is only executed when the IF and the ELSIF tests are false 91 | if (note >= highestNote) 92 | puts "in if block" 93 | puts "stopping" 94 | # To exit this loop we need to break 95 | break 96 | elsif (note > transitionNote) 97 | puts "in elsif block" 98 | sleep 0.25 99 | else 100 | puts "in else block" 101 | sleep 0.75 102 | end # this end closes the If Elsif Else blocks 103 | note += 1 # note(new value) = note(old value) + 1 104 | end 105 | puts "stopped" -------------------------------------------------------------------------------- /16-ruby-while.rb: -------------------------------------------------------------------------------- 1 | # Another form of a loop with a condition is a while loop 2 | # This loop continues repeating a block of code until the comparison is false 3 | 4 | note = 70 5 | # The while loop must be completed with an end 6 | # A while loop performs the test at the beginning of loop iteration 7 | # The last note to play will be the note 77 8 | while (note < 78) 9 | puts "note is=#{ note} , is note less than 78?#{(note < 78)}" 10 | play note 11 | sleep 0.5 12 | note += 1 # note = note+1 13 | end 14 | puts "outside loop, note is=", note 15 | puts "stopped" -------------------------------------------------------------------------------- /17-ruby-iterable.rb: -------------------------------------------------------------------------------- 1 | # If we wanted to access each element of an array in order we iterate over the array 2 | # There are two forms of looping we can use 3 | 4 | # The array can be stored in a variable 5 | note_pattern = [60,64,68,72,76] 6 | 7 | # The most readable form of loop is probably this one 8 | # Iterates over the array note_pattern 9 | # Assigns the value of each element to the variable note in order 10 | for note in note_pattern 11 | play note 12 | sleep 0.5 13 | end 14 | # Be aware that the variable note now exists after this loop 15 | # This means we can do this 16 | puts "note is #{note}" 17 | 18 | sleep 1 19 | 20 | # This is not as readable but is equally valid 21 | # Iterates over array 22 | # Assigns vaue of each element to a temporary variable 23 | note_pattern.each do |elementValue| 24 | play elementValue 25 | sleep 0.5 26 | end 27 | # the variable elementValue does not exist outside of the loop 28 | -------------------------------------------------------------------------------- /18-ruby-object-operations.rb: -------------------------------------------------------------------------------- 1 | # The arrays of notes can have operations applied to them 2 | # This avoids retyping and possible typos 3 | 4 | use_bpm 240 5 | # Arrays can be assigned to variables 6 | note_pattern = [60,64,68,72,76] 7 | 8 | # This plays the array as normal 9 | play_pattern note_pattern 10 | 11 | sleep 1 12 | 13 | # This plays the array in reverse 14 | play_pattern note_pattern.reverse 15 | 16 | sleep 1 17 | 18 | #This plays the array in a random order 19 | play_pattern note_pattern.shuffle 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sonic-Pi-Examples 2 | ================= 3 | 4 | Contains simple examples of the usage of Sonic-Pi 5 | 6 | NOTE: Only compatible with version 2.0 of Sonic-Pi 7 | 8 | To use these examples: 9 | 10 | 1. Open Sonic-Pi 11 | * This can be done in two ways 12 | 1. Click on: Start Menu > Programming > Sonic-Pi 13 | 2. Using the Terminal 14 | * Open LXTerminal by double clicking on the desktop icon 15 | * Type `sonic-pi &` and press enter 16 | * Note: Do not quit the terminal as it will also quit sonic-pi! 17 | 2. Open any of these files in a text editor 18 | 3. Copy and Paste all the text from a file into a workspace in Sonic-Pi 19 | 4. Click on the play script button in the top left to run them 20 | 5. Enjoy the Music! 21 | 22 | Note: Sonic-Pi should be installed by default on the Raspbian OS 23 | 24 | If it is not installed it can be installed by using LXTermainal. Open LXTerminal and type: 25 | `sudo apt-get install sonic-pi` 26 | 27 | If you have another distribution such as ArchLinux or Pidora you may have to search the repositories for sonic-pi 28 | 29 | 30 | --------------------------------------------------------------------------------