Yummy Fillings!

I’ve been working for quite a while on a collection of useful methods to help with Sonic Pi, and it’s finally ready to share with y’all!
It’s called YummyFillings.rb, and it’s on github here:

I found myself having to reinvent the wheel, so I decided to build some reusable methods for really common tasks. Examples are lfos and envelopes for any slidable param, trancegates, strumming and arpeggiating chords, making a straight rhythm swing (even to odd beats), arranging multiple voices for more compositional approaches (as opposed to live-coding in the moment), converting drum notation and a simplified musical notation into playable arrays of values to drive performance, etc.
Two things might be of particular interest. The method arrange supports very sophisticated arrangements of multiple voices together. And convertdrumnotation supports simple notation like “x—x—x—x—”, but also controlling dynamics with numerals like “2—4—6—8” (with 9 the loudest and 1 the quietest), easy polyrhythms by subdividing the bar into however many beats you specify (e.g. “x–x–x–x–” will play a 3/4 beat on one line, while “xxxx” is a four-on the floor kick). It also supports nesting subdivisions, a la Tidal Cycles, so “x[x[xx]]” gives the equivalent of “hqee”.
Lots to explore here.
To quote from the readme.md:
Yummyfillings.rb is a collection of ruby methods to make life easier when making music with Sonic Pi.
Load it using eval_file (e.g,: eval_file “E:/Yummy/YummyFillings.rb” )
at the top of the buffer.
There are methods providing envelopes, lfos, trancegates, stutter effects, arpeggiation, transposition of samples,
orchestration of multiple voices, swinging rhythms, euclidean rhythms, etc.
There are also utilities and testing methods to make programming simpler and more readable.

Methods grouped by purpose

Music performance

Method Name Description
arpeggiate plays a given chord/scale/array/ring in sequence, with the timing you specify
arrange play multiple musical voices, each with their own rhythm, melody, etc.
funkify plays a given synth/sample in a randomly generated funky rhythm
playdegreematrix play melodies in a scale by specifying scale degrees
playline simplified wrapper for arrange, plays one instrument line. Threaded by default.
strum strums the chord passed in. Convenience wrapper for arpeggiate.
stuttersample plays a sample, chopping it up and stuttering/reversing sections.
transposesample transposes a sample, hiding the nasty math involved in pitch_stretch and rpitch.

Sound manipulation

Method Name Description
env apply an envelope to any sliding param for any synth or sample.
lfo apply an lfo/mseg to any sliding param for any synth or sample.
trancegate apply a polyrhythmic trancegate to any synth or sample.

Melody/rhythm manipulation

Method Name Description
convertdrumnotation converts drum notation (“x—x—x—x—”) to note-type notation (“q,q,q,q”).
cooktime converts notation (“q”) to time duration (1.0).
cooktimes converts a sequence of notation (“q, dq, dq”) to an array of time durations [1, 1.5, 1.5].
degreestoabsolutenotes converts scale degrees to absolute notes.
euclidiate applies euclidean rhythms to generate metrical sequence, in notation ([1.5, 1.5, 1]). Convenience wrapper for spreadtobeats.
funkyrandom generates a random funky rhythm, returned as an array of times.
humanize applies a random amount of humanization to a given time array.
spreadtobeats turns a spread into notation for rhythm. Euclidiate wraps this in a friendlier interface.
swing converts straight rhythms to swing rhythms. Supports oddball swings (7, 5.3, etc.).
tuples generates tuples of any time amount. Returns notation if possible.

Array/hash/ring manipulation

Method Name Description
argstohash converts an argument string (“amp: 2, cutoff: 60”) to a hash.
argstostring converts an argument hash ({amp: 2, cutoff: 60}) to a string.
arrayhashtohasharray converts a hash of arrays to an array of hashes.
cleanchordorscale turns a chord or scale into a flat array.
paddedrowstocolumns transforms an array of arrays, pivoting rows to columns and padding short arrays by repeating values.
rowstocolumns transforms an array of arrays, pivoting rows to columns, but padding short arrays with nils.
setarg set arguments in an argument hash.
tickargs if argument values are specified as arrays, will tick through individual values on consecutive calls.
striptrailingnils strips trailing nils from an array. Useful with rowstocolumns.

Tests and comparisons

Method Name Description
boolish test for values that are kinda false, e.g., “”, empty array, 0, etc.
divisibleby tests whether one number is evenly divisible by another.
equalish tests for approximate equality. Useful for comparing floats, e.g. triplets.
listorring tests whether a value is an array, hash or ring.
ringorlist same as listorring
samplebpm returns the bpm of a given sample.
tickable same as listorring

Utilities

Method Name Description
debugprint prints anything to stdout, optionally logging to a file, optionally expanding arrays and hashes.
overridekwargs used to support passing named parameters to methods.
stripparams used to strip parameters from kwargs that match method params. Useful for collecting params to pass to methods like play or sample.
yummyhelp print help info to stdout for methods herein.
yh wrapper for yummyhelp

I’d love to hear feedback. I hope y’all find these things useful. If you run into any bugs, please hit me up and I’ll fix it asap. I’ve done a bunch of testing – I’ve worked on this for months – but no doubt I have blind spots.
Enjoy!

6 Likes

Fixed 2 bugs in convertdrumnotation. If you downloaded original, please update.

Wow, this must have been an enormous amount of work, thank you! I’ve been wondering about some of the Ruby methods people are using, x-x-x- etc and v interested in arpeggiation and transposing samples.

I’ve downloaded, using eval + amended path, is playing notes, have tried with egs (these are very useful) from the read.me but getting a runtime error referencing a directory which looks to be on your system? I’m new to Ruby so may be doing something basic wrong, sorry! Is it OK to post q’s here, or do you prefer we send somewhere else? Thank you.

Yikes! Sorry about that!
It’s probably the logfile path in debugprint. Just open YummyFillings.rb in a text editor (too big for sonic pi’s editor), search for “define :debugprint”, and you’ll see an argument that is logfile. Change it to a path that points to something on your system. Or, just set logtofile to false.
If that doesn’t fix it, please post the code & the error message.

1 Like

Actually, I just turned file logging off, so re-download it & it should work fine.
Sorry about that!

1 Like

Hurray! Thank you - removing that line has worked and I’ve had a quick play. It will need a lot more playing, there’s so much in there :slight_smile: - have had fun with arpeggiate, and transposesample is something else! Being able to pitchshift and put relative pitches into an array is fantastic (plus duration), means you can easily make melodic sequences from samples. I’ve tried this a bit in other ways, but have v limited skills and this makes it easier.
Aside: have been playing with moog Werkstatt and through that, getting into :mod_pulse and :mod_range (relative intervals) as a way to do polyphony with monophonic sound source (oscillator or recorder sample). Arpeggiate and transposesample are great for this.
Will no doubt be back with more q’s! Thank you for super festive pressie for the Sonic Pi community.

PS your examples in the READ.ME are very useful as a starting-point for Ruby-new people. Here’s my wee transposesample. The SonicPi guitar works really well.
PS the 2nd array, for anyone trying this, is 0= tonic, 5 = +5 semitones, +7 semitones etc

live_loop :pitchshift do
  mysample = :guit_em9

  [60, 120, 60].each do  | thisbpm |
    [0, 5, 7,5].each do  | thispitch |
      use_bpm thisbpm
      transposesample mysample, 8, thispitch
      sleep 4
    end
    sleep 1
  end
end

I’m glad it’s working for you. I love your example.
I’ve tweaked it a bit, by adding some variables to allow more musical language, and to use samplebpm to synchronize to the sample:

bar = 16.0
whole = 4.0
half =2.0
quarter =1.0
eighth =0.5
sixteenth =0.25
dotted =1.5
triplet =2.0 / 3
halftone = 1
second = 2
wholetone = 2
min3 = 3
maj3 = 4
fourth = 5
tritone = 6
fifth = 7
min6 = 8
maj6 = 9
min7 = 10
maj7 = 11
octave = 12

mysample = :guit_em9


live_loop :pitchshift do
  
  [2, 2, 1, 0.5].each do  | thismult |
    [0, fourth, fifth, octave].each do  | thispitch |
      use_bpm thismult * (samplebpm mysample, 8)
      transposesample mysample, 8, thispitch
      sleep whole
    end #intervals
    sleep quarter
  end #thismult
end #liveloop

Enjoy exploring! Sonic Pi is a blast, and I hope YummyFillings makes it easier & more fun.

1 Like

Wow, thanks - how did you get such variation out of this? It keeps on evolving. Something to do with thismult but can’t get my head round it :slight_smile:

Aha - samplebpm is one of the new yums.

Yeah, samplebpm returns the sample rate of any given sample. A useful widget that simplifies a common task.