Last active
March 20, 2016 16:56
-
-
Save Enkerli/0687533338c5e40516fc to your computer and use it in GitHub Desktop.
Sonic Pi script to play with licks (short melodies notated in scale degrees). The function to convert degrees to notes is cobbled together from the built-in `resolve_degree` and `resolve_degree_index` methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Sonic Pi script to play with licks (short melodies notated in scale degrees). The function to convert degrees to notes is cobbled together from the built-in `resolve_degree` and `resolve_degree_index` methods. | |
| # Defining two new functions. Once defined, they don’t need to be included in other scripts. | |
| # Lick player | |
| def play_lick(lick, root, scale, time) # A “lick” is a list of scale degree numbers, with a set timing (i.e. “isorhythmic”). | |
| spark lick # Show the lick as a text-based graph | |
| lick.each{|note| play((degree_to_note note, root, scale)) ; sleep time } # Convert each degree number into a note and play it for the set amount of time. This function doesn’t use all the other `play` arguments such as `release:`and `amp:`. Could be useful in a future version, especially for timing. | |
| end | |
| DEGREES = {:i => 0, # Thought these were defined by default. They’re necessary for the degree conversion. | |
| :ii => 1, | |
| :iii => 2, | |
| :iv => 3, | |
| :v => 4, | |
| :vi => 5, | |
| :vii => 6, | |
| :viii => 7, | |
| :ix => 8, | |
| :x => 9, | |
| :xi => 10, | |
| :xii => 11, | |
| :r => 999 # While we’re at it, why not allow `:r` to become a rest, as elsewhere in Sonic Pi code? | |
| } | |
| # Degree to note converter | |
| def degree_to_note(degree, tonic, scale) # Degree '0' should become a rest, the others should be converted to scale notes. | |
| local_scale = Scale.new(tonic, scale) # Build a scale on the root note. | |
| if degree.is_a?(Numeric) && degree==0 # Main change from the built-in `degree` function: we transform degree '0' into a rest. | |
| return 0 | |
| elsif idx = DEGREES[degree] # Accommodate the notation in Roman numerals, e.g. “:iv” for the fourth degree of the scale. | |
| index=idx | |
| elsif degree.is_a? Numeric # If degree is a non-null integer, return the previous index in the scale, even if it’s negative | |
| index=degree - 1 | |
| else # Catch non-numeric degrees. | |
| raise InvalidDegreeError, "Invalid scale degree #{degree.inspect}, expecting #{DEGREES.keys.join ','} or a number" | |
| end | |
| local_scale.notes[index] # Return the scale note at the index position below the degree, if it’s a valid non-zero integer. Degree '1' returns the root note, degree '3' returns the third, degree "-1" returns the next to last note in the scale (the “subtonic”), etc. | |
| end | |
| # The “composition”: a simple loop allowing to change a lick in realtime. | |
| root=52 # Put the tonic in a variable so it’s easy to change | |
| scale=:minor # Put the scale type in a variable so it’s easy to change | |
| use_tuning :just, root+1 # Since we can get acoustically perfect intervals, why not use them? Since the tuning is based on the major scale, adjustment may be needed for non-major scales | |
| use_synth :pretty_bell # Some of the “softer” synths make sense, here, as we want to hear consonance. | |
| live_loop :licking do # Infinite loop for live coding. | |
| a=tick # Setting the first note in the lick to vary. At first, ticking through scale degrees, sequentially. Can then change this to a number, getting other degrees. | |
| play_lick((ring a-7, 0, 3, 1).stretch(3), # Ha! Just found out that making the lick into a `ring` allows for the “ring chains” methods to be applied. Doh! <https://github.com/samaaron/sonic-pi/issues/1075#issuecomment-198870143> | |
| root, scale, 0.1) # Otherwise, as simple a lick as possible, in a “dactyl” or “cretic” meter (depending on the duration after the lick), ending on the root. | |
| sleep 0.45 # This duration causes the last lick note to play longer and then allows for a rest between licks. | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # “Lix Explorer” | |
| # Coded by Alex Enkerli, March 20, 2016 | |
| # Sonic Pi script to play with licks (short melodies notated in scale degrees). The function to convert degrees to notes is cobbled together from the built-in `resolve_degree` and `resolve_degree_index` methods. | |
| def play_lick(lick, root, scale, time) | |
| spark lick | |
| lick.each{|note| play((degree_to_note note, root, scale)) ; sleep time } | |
| end | |
| DEGREES = {:i => 0, | |
| :ii => 1, | |
| :iii => 2, | |
| :iv => 3, | |
| :v => 4, | |
| :vi => 5, | |
| :vii => 6, | |
| :viii => 7, | |
| :ix => 8, | |
| :x => 9, | |
| :xi => 10, | |
| :xii => 11, | |
| :r => 999 | |
| } | |
| def degree_to_note(degree, tonic, scale) | |
| local_scale = Scale.new(tonic, scale) | |
| if degree.is_a?(Numeric) && degree==0 | |
| return 0 | |
| elsif idx = DEGREES[degree] | |
| index=idx | |
| elsif degree.is_a? Numeric | |
| index=degree - 1 | |
| else | |
| raise InvalidDegreeError, "Invalid scale degree #{degree.inspect}, expecting #{DEGREES.keys.join ','} or a number" | |
| end | |
| local_scale.notes[index] | |
| end | |
| root=52 | |
| use_tuning :just, root+1 | |
| use_synth :pretty_bell | |
| live_loop :licking do | |
| a=tick | |
| scale=:minor | |
| play_lick((ring a-7, :r, 5, 1).stretch(3), root, scale, 0.1) | |
| sleep 0.45 | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment