Hi.
I started trying Sonic Pi about a week ago. I have some programming experience, but very little. So I am the living proof it really is a great tool for learning. And learning can deliver results in no time.
My setup:
- Raspberry Pi 3, upgraded to Stretch
- Sonic Pi 3.0.1
- Akai Lpd8 midi controller (the cheapest I could find).
Goal: what I wanted to achieve was a basic beat machine (no sequencing, for now, just boring techno style 1-1-1-1) and ambience sounds controlled by the midi controller.
You could probably run this code with another midi device, if you do a little mapping. Anything with 8 turning knobs and some pads will probably work.
Problems with code below:
- high (actually low, it should be inverted) tempo will result in high latency and can crash the midi_in thread
- high tempo combined with large reverb room will crash very soon with pretty much any sample.
- there could still be occasions the value for an opt: can be out of range. This will make the thread stop.
- Fast paced knob turning on many knobs at once will make the midi_in thread fall behind time and crash
Anyhow, I’m pretty new to it. And would love to hear your feedback. I probably wrote pretty amateur-hour code, but if you have suggestions on how to make things better: I’ld love to hear about them. Especially suggestions for latency reduction and reduction of crash probability
Other thing I would very much like to do is “remember” variable value of already running threads on restart. Now, if I restart already running code the amp, tempo, etc. sometimes gets set back to default values (first line) again. Which is annoying for usage.
----------
tempo = 0.5; sampleIdx = 0; voices = 1; amp = 0.5; randomiser = 1; ambiSelectie = 0; reverbRoom = 0; panner = 0
load_samples [:ambi_choir, :ambi_dark_woosh, :ambi_drone,:ambi_glass_hum, :ambi_glass_rub, :ambi_haunted_hum, :ambi_lunar_land, :ambi_piano, :ambi_soft_buzz, :ambi_swoosh, :bass_dnb_f, :bass_drop_c, :bass_hard_c, :bass_hit_c, :bass_thick_c, :bass_trance_c, :bass_voxy_c, :bass_voxy_hit_c, :bass_woodsy_c, :bd_808, :bd_ada, :bd_boom, :bd_fat, :bd_gas, :bd_haus, :bd_klub, :bd_pure, :bd_sone, :bd_tek, :bd_zome, :bd_zum, :drum_bass_hard, :drum_bass_soft, :drum_cowbell, :drum_cymbal_closed, :drum_cymbal_hard, :drum_cymbal_open, :drum_cymbal_pedal, :drum_cymbal_soft, :drum_heavy_kick, :drum_roll, :drum_snare_hard, :drum_snare_soft, :drum_splash_hard, :drum_splash_soft, :drum_tom_hi_hard, :drum_tom_hi_soft, :drum_tom_lo_hard, :drum_tom_lo_soft, :drum_tom_mid_hard, :drum_tom_mid_soft, :elec_beep, :elec_bell, :elec_blip, :elec_blip2, :elec_blup, :elec_bong, :elec_chime, :elec_cymbal, :elec_filt_snare, :elec_flip, :elec_fuzz_tom, :elec_hi_snare, :elec_hollow_kick, :elec_lo_snare, :elec_mid_snare, :elec_ping, :elec_plip]
varSamples = [:ambi_choir, :ambi_dark_woosh, :ambi_drone,:ambi_glass_hum, :ambi_glass_rub, :ambi_haunted_hum, :ambi_lunar_land, :ambi_piano, :ambi_soft_buzz, :ambi_swoosh, :bass_dnb_f, :bass_drop_c, :bass_hard_c, :bass_hit_c, :bass_thick_c, :bass_trance_c, :bass_voxy_c, :bass_voxy_hit_c, :bass_woodsy_c, :bd_808, :bd_ada, :bd_boom, :bd_fat, :bd_gas, :bd_haus, :bd_klub, :bd_pure, :bd_sone, :bd_tek, :bd_zome, :bd_zum, :drum_bass_hard, :drum_bass_soft, :drum_cowbell, :drum_cymbal_closed, :drum_cymbal_hard, :drum_cymbal_open, :drum_cymbal_pedal, :drum_cymbal_soft, :drum_heavy_kick, :drum_roll, :drum_snare_hard, :drum_snare_soft, :drum_splash_hard, :drum_splash_soft, :drum_tom_hi_hard, :drum_tom_hi_soft, :drum_tom_lo_hard, :drum_tom_lo_soft, :drum_tom_mid_hard, :drum_tom_mid_soft, :elec_beep, :elec_bell, :elec_blip, :elec_blip2, :elec_blup, :elec_bong, :elec_chime, :elec_cymbal, :elec_filt_snare, :elec_flip, :elec_fuzz_tom, :elec_hi_snare, :elec_hollow_kick, :elec_lo_snare, :elec_mid_snare, :elec_ping, :elec_plip]
varAmbiSamples = [:ambi_choir, :ambi_dark_woosh, :ambi_drone,:ambi_glass_hum, :ambi_glass_rub, :ambi_haunted_hum, :ambi_lunar_land, :ambi_piano, :ambi_soft_buzz, :ambi_swoosh]
sleep 3
in_thread(name: :midiIn) do
live_loop :midiIn do
use_real_time
ch, val = get "/midi/lpd8_midi_1/1/1/control_change"
if ch == 1 then
sampleIdx = val
puts "sample:"
puts varSamples[sampleIdx]
end
if ch == 2 then
tempo = quantise ((val / 127.0) * 4) + 0.2, 0.2
puts "tempo:"
puts tempo
end
if ch == 3 then
voices = quantise val / 25, 1
puts "voices:"
puts voices
end
if ch == 4 then
amp = val / 127.0 + 0.1
puts "amp:"
puts amp
end
if ch == 5 then
randomiser = val / 3.0
puts "randomiser:"
puts randomiser
end
if ch == 6 then
ambiSelectie = val
puts "ambiSelectie:"
puts varAmbiSamples[ambiSelectie]
end
if ch == 7 then
panner = quantise (val / 64.0) - 1, 0.1
puts "panner:"
puts panner
end
if ch == 8 then
reverbRoom = val / 127.0
puts "reverbRoom:"
puts reverbRoom
end
sleep 0.1
end
end
in_thread(name: :piano) do
live_loop :piano do
use_real_time
note, velocity = sync "/midi/lpd8_midi_1/1/1/note_on"
sync :noiseBringer
rrand_i(1, 4).times do
sleep tempo / 8
sample :drum_cymbal_open, amp: amp / 4, rate: (velocity / 127) + 0.4
sample varAmbiSamples[ambiSelectie], amp: amp /2, rate: note / randomiser, pan: panner
puts "note / randomiser:"
puts note / randomiser
sleep tempo / 8
sample :drum_cymbal_pedal, amp: amp / 4, rate: (velocity / 127) + 0.4
sleep tempo / 8
sample varAmbiSamples[ambiSelectie], rate: note / (randomiser - rrand(0, 10)), pan: panner
sleep tempo / 8
sample :elec_blup, amp: amp / 4, rate: (velocity / 127) + 0.4
sleep tempo / 8
sample :elec_filt_snare, amp: amp / 3, rate: (velocity / 127) + 0.4
sleep tempo / 8
sleep tempo / 8
sleep tempo / 8
end
end
end
in_thread(name: :noiseBringer) do
live_loop :noiseBringer do
with_fx :reverb, room: reverbRoom do
voices.times do
sample varSamples[sampleIdx], amp: amp
if voices > 1 then
if amp > 0.25 then
sample varSamples[sampleIdx], amp: amp
sample varSamples[sampleIdx], amp: amp - 0.2, rate: 0.9
end
else
sample varSamples[sampleIdx], amp: amp + 0.2
end
end
sleep tempo
cue :noiseBringer
end
end
end