Hello there. I’m a professional software tester and hobby musician (guitarist) of 20 years and have recently started tinkering in the world of electronic music production (synthwavey sort of stuff). I’ve been exploring the possibilities of Sonic Pi and am very excited by the concept of having a highly customized environment in which to write and perform, without the need to learn and experiment with many different user interfaces, VST features etc etc
I’m just trying to understand the tonal possibilities of the synths. I’ve noticed that the TB303 is the only synth with a filter cutoff envelope. Is it possible to simulate an envelope somehow by "control"ing the cutoff for other synths? I’ve seen the feature request and discussion around using a wave to control a parameter. This would be cool for a modulation type effect but I’m referring more to movement of the parameter triggered by each note and eventually ending in silence.
Althugh :tb303 is the most obvious synth to be affected by cutoff settings, if you look at the details on the synths in the help file synth tab you will see that quite a large number of them can be affected by cutoff values. This can be particularly noticeable if you control the cutoff while a note is playing. You can also do this be means of applying fx :lpf which can again be controlled, or perhaps by sweeping a band pass filter as the note plays.
Here is an example which alters cutoff and sweeps a band pass filter as the notes play, using a selection of different synths including a noise source.
In general many parameters for a synth (or sample) can be altered while it is playing using the control mechanism. See section 7 of the tutorial in the help file.
live_loop :test do
tick
tick_set :slow,look/8 #tick(:slow) at 1/8th rate
s= (ring :cnoise, :dsaw,:tb303,:prophet,:zawa,:tri).look(:slow) #change every 8 notes
puts s #current synth
use_synth s
with_fx :bpf,centre: 80 do |c| #start controllable band pass filter
#start note with controllable cutoff
b=play scale(:e2,:harmonic_minor, num_octaves: 2).choose,cutoff: 100,attack: 0.1, sustain: 1.2,release: 0.2
control b, cutoff: 50,cutoff_slide: (ring 0.1,0.2,0.4).look # slide cutoff at different rates
4.times do #sweep bpf 4 times
control c,centre: rrand(10,100),centre_slide: 0.2
sleep 0.2
end
sleep 0.6
end
end
You may also wish to create risers with “line” to affect a parameter you want to rise.
riser0 = (line 10, 0, inclusive: true, steps: 16)
live_loop :attackBeat do
puts tick
#Load in your own sample to hear it in action or use a synth
sample hat, 33, attack: riser0.look
sleep 2
end
Alternatively use “.mirror” to create an oscillator sort of like an LFO. This is probably one of the most useful techniques I’ve found for synthwave because you can have multiple LFO’s running different parameters simultaneously. You can use this to drive any parameter even if it’s not an FX parameter. You can also do complex things like have one LFO affect another with math to create a resultant LFO of a weird shape (or slowly morphing shape.
lfo0 = (line 80, 100, inclusive: true, steps: 120).mirror
live_loop :oscSynth do
puts tick
#Load in your own sample to hear it in action or use a synth
with_fx :hpf, cutoff: lfo0.look do
sample outrun, 38
end
sleep 0.125
end
Thanks so much @bagofdragonite. So if I’m understanding correctly, in the first example the parameter moves from the first value to the second value in a straight line then remains at the second value. And in the second example it does the same thing but repeatedly moves between the first and second value. Is this correct?
Are “line” and “mirror” sp things or ruby things? I haven’t come across any doco on these as yet.
Line is documented in the Lang section, bottom left of screen… or you can type it in, put the cursor
in it and press F1…
Mirror is somewhere between the two… people use it, but maybe it isn’t formally acknowleged.
The help for line states:
line start (number), finish (number)
Create a ring buffer representing a straight line between start and finish of num_slices elements. Num slices defaults to 8. Indexes wrap around positively and negatively. Similar to range.
Introduced in v2.5
Consider it a ring from A to B, with X number of steps, triggered by Tick?
Regarding line, it will move through the values in a straight line (rising or falling) then repeat in a cycle. If you want the value to remain at the high point use “.ramp” to achieve this. I’m sure once you read through LANG you will understand how to use these better than I’m explaining here.
Son of a… I feel like an idiot! That explains why this was the only approach that worked for me lol. So here’s what it should look like (thanks for pointing that out @robin.newman)
use_bpm 180
melody = (ring :C2, :E2, :G2, :B2, :C3, :B2, :G2, :E2)
live_loop :strange do
use_synth :saw
use_synth_defaults sustain: 0.5, release: 0.5
m = play melody.tick, cutoff: 100
control m, cutoff: 80, cutoff_slide: 0.25
sleep 0.5
end
@aen1gma, thanks for that code snippet, that’s literally one of the major reasons I wanted to get into music programming (and sonic-pi in particular) was to recreate this sound!
I did run into a problem running that code sample though, saying that :saw doesn’t have a :cutoff parameter (only when calling control for some reason, though). I’m running Sonic Pi v2.9 so maybe in v3.0.1 (or later) this issue is fixed.
Using :dsaw fixed it for me:
use_bpm 180
melody = (ring :C2, :E2, :G2, :B2, :C3, :B2, :G2, :E2)
dt = 0.125/2
slidetime_a = Array.new(8) { |t| t = dt*(t+1) }
slidetime = (ring *(slidetime_a.concat slidetime_a.reverse()[1,6]))
live_loop :strange do
idx = tick
co = slidetime[idx]
use_synth :dsaw
use_synth_defaults sustain: 0.5, release: 0.5
sn = play melody[idx], cutoff: 120
control sn, cutoff: 80, cutoff_slide: co
sleep 0.5
end
with a little variability in the cutoff sprinkled in for some added effect.