the short answer is that this isn’t supported. Sonic Pi isn’t a standard Ruby library, it’s a DSL built on top of Ruby. Whilst many aspects of Ruby are available to Sonic Pi, only the code described in the tutorials is officially supported.
For people that want to do this nevertheless:
I found out, that you can do this:
class MyClass
def initialize(play, in_thread)
@play = play
@in_thread = in_thread
end
def myFn
@play.call 70
@in_thread.call do
@play.call 60
end
end
end
x = MyClass.new(lambda {|*args| play *args}, lambda {|*args, &block| in_thread *args, &block})
x.myFn
However that is not elegant, because you must pass every function, you want to use, to the new function.
Sam’s been pretty vocal about not wanting Sonic Pi to head into an object oriented direction. Still, for people who are really familiar with Ruby it feels weird to be locked into the procedural model of the Sonic Pi DSL.
Though it’s not supported, I do this all the time and I’ve developed a pretty elegant way of going about using my own classes as libraries.
You can really shoot yourself in the foot with this approach, especially with threads, so if you don’t know ruby in and out, avert your gaze.
This is how I do it:
# Usually, put this defonce in a file like "/path/to/my/doorbell.rb"
# You must set override to true to make changes
defonce :use_doorbell, :override => false do
class Doorbell
def initialize(amp=1.0)
@amp = amp
end
def self.set_runtime(rt)
@@runtime = rt
end
def runtime
@@runtime
end
def ring
runtime.with_synth :pretty_bell do
runtime.play 67, amp: @amp
sleep 0.75
runtime.play 60, amp: @amp
end
end
end
Doorbell.set_runtime(self)
end
# Usually load the library from the file
# run_file "/path/to/my/doorbell.rb"
use_doorbell
Doorbell.new(0.7).ring