Arpeggios on a tb303 bass


code link

For another interesting variation change line 83 as below

ch.each do |n| #play each chord as an arpeggio #interesting variation is to change to ch.shuffle.each do |n|

That sounds very nice! It’s great to have an example with harmonic, dynamic, and temporal structure.

I suspect I’m going to learn a lot by studying your code. Thanks!


Thanks Mike
I enjoyed working on the piece, which just seemed to “click” as I added more features and let it grow from very humble beginnings, starting with just triad apreggios, then adding a fourth bass note to each triad, then transposing using 0,5,7,-5 (C,F,G,G-Lower octave) and adding a pedal note for each progression. I always like to add dynamic structure as well and the use of teh at command with timed amp_slides gives a nice way to achieve crescendos and diminuendos.

BTW I enjoyed reading your article on Tbon on github. I have worked in the past on manujally converting a lilypond script to Sinic Pi, and also on converting midi to Sonic Pi format using MuseScore to convert the midi to monophonic parts and then to MusicXML and then a processing script modified from one by Tachibani to convert that to Sonic Pi forma. It has fairly stringent constraints, but I have used it successfully for many conversions. I also did some work with JoeMac’s script which achieves a similar result. I look foward to having a more detailed look at Tonb.

Probably the most ambitious work I converted from midi to Sonic Pi was the whole of Mozart’s Requiem, which I voiced with samples. see


@robin.newman Looking through your code, I think I get the gist, but there some Sonic Pi / Ruby -isms I’m unclear about. For example in line 19 I see

with_fx :level, amp: 0 do |v|
  • Is with_fx similar to a Python context manager with statement?
  • What type of variable is |v|? It doesn’t seem quite like a function argument. Is it a local reference to a the :level effect?

A couple of lines down I see

at [51.2,102.4,153.2,204.8],[0.5,1,0.4,1] do |t|

I get that this is specifying a time (in beats?) at which to begin sliding the volume to a target value but where is at documented? I searched in the tutorial and with google but didn’t find anything.

I’m approaching bringing Tbon into SP with a sense of humility. I don’t want to reinvent the wheel and I don’t want to do something that’s a kluge just for the sake of doing it. That being said, it looks like a quick and dirty test might be to call a modified version of Tbon with Ruby’s system call notation and eval a returned string to get a pair of lists with times and durations suitable for use with play_pattern_timed, e.g.

# Greensleeves. First 4 bars, no pickup.

melody = [
    [:c4,1], [:d4,0.5], [:e4,0.75], [:f4,0.25], [:e4,0.5],
    [:d4,1], [:b3,0.5], [:g3,0.75], [:a3,0.25], [:b3,0.5],
    [:c4,1], [:a3,0.5], [:a3,0.75], [:gs3,0.25], [:a3,0.5],
    [:b3,1], [:gs3,0.5], [:e3,1.5],

# Tbon notation for same four bar fragment is:
# K=a T=90 B=4.
# c-d e--fe- | d-b g--ab- | c-a a--#ga- | b-#g e |
# So a system call and ruby eval of the result could
# look something like:
# melody = (eval `tbon "c-d e--fe- | d-b g--ab- | ..."`)

use_bpm 90
use_synth :piano
play_pattern_timed melody[0], melody[1]

To make that work, I’d need to put different backend onto Tbon to emit a string representing a list of lists with the appropriate note names and beat durations.

If you’d like to play with Tbon outside of SP, there’s a live online demo where you can enter Tbon notation and play it through a JS synth in your browser. Have fun!

I found your Mozart Requiem a couple of days ago. Wow, that’s a monumental effort. The Requiem is one of the great choral works. There’s something new to appreciate every time I’ve sung it.


In asnwer to your questions, with_fx do…end is the construct used for wrapping some code with a named effect. It is documented in several places in the help system.
First in the Lang tab look up with_fx (Note the built in help system contains other sections than the tutorial which is the section available on line).
Second there is a separate Fx tab which gives details of all the individual Fx available, together with details of their options.
In my example v is indeed a reference to the running effect which can be used to control various opts in the effect. In this case I control tha :amp setting of the :leve effect, and also use the amp_slide: paraneter to control the time over which changes take place. There is an example of using such a variable in the with_fx docucumentation in the Lang section of the help file. (note you can use a puts v command inside the do…end loop to see the information it holds.)

Similarly the at command is detailed in the Lang section of the help file, with some examples there. eg

at [1, 2, 3], [75, 76, 77] do |n| 
    play n         #plays three different notes (at beats 1,2 and 3

Thanks! I totally missed the Lang tab. :open_mouth: