Control multi-volume from samples?

Hi Sonic Pis

I want to control 4 volumes from 4 samples as a single value. Is it possible ?

I have :
Drums1 = "User/Me/Desktop/SetSonicPi/Drums1.wav
Drums2 = "User/Me/Desktop/SetSonicPi/Drums2.wav
Drums3 = "User/Me/Desktop/SetSonicPi/Drums3.wav
Drums4 = "User/Me/Desktop/SetSonicPi/Drums4.wav

Is it possible to code something like that ?
DRUMASTER = Drums1 amp: $, Drums2 amp: $, Drums3 amp: $, Drums4 amp: $

in ruby is $ = variable ?

I hope my questions are clear.
Thx for your help

You could define a function that plays the 4 samples at a given volume:

Drums1 = "User/Me/Desktop/SetSonicPi/Drums1.wav"
Drums2 = "User/Me/Desktop/SetSonicPi/Drums2.wav"
Drums3 = "User/Me/Desktop/SetSonicPi/Drums3.wav"
Drums4 = "User/Me/Desktop/SetSonicPi/Drums4.wav"

define :playdrums do |amp|
  sample Drums1, amp: amp
  sample Drums2, amp: amp
  sample Drums3, amp: amp
  sample Drums4, amp: amp
end

playdrums 0.2
sleep 1
playdrums 2

Does that do what you want?

Thanks @emlyn

Did you if it’s possible to have an fx for each drums in the following code :

Drums1 = “User/Me/Desktop/SetSonicPi/Drums1.wav”
Drums2 = “User/Me/Desktop/SetSonicPi/Drums2.wav”
Drums3 = “User/Me/Desktop/SetSonicPi/Drums3.wav”
Drums4 = “User/Me/Desktop/SetSonicPi/Drums4.wav”

live_loop :Drums do
sample [Drums1, Drums2, Drums3, Drums4].choose
sleep sample_duration Drums1
end

Thx for your help

You mean so that the same fx always goes with the same drum? One way would be to pair the drums with an effect and choose them together, something like this:

Drums1 = "User/Me/Desktop/SetSonicPi/Drums1.wav"
Drums2 = "User/Me/Desktop/SetSonicPi/Drums2.wav"
Drums3 = "User/Me/Desktop/SetSonicPi/Drums3.wav"
Drums4 = "User/Me/Desktop/SetSonicPi/Drums4.wav"

live_loop :Drums do
  drum, fx = [[Drums1, :krush],
              [Drums2, :slicer],
              [Drums3, :echo],
              [Drums4, :flanger]].choose
  with_fx fx do
    sample drum
  end
  sleep sample_duration Drums1
end

Although if you then want to add different parameters to the fx it gets a bit more complicated:

Drums1 = "User/Me/Desktop/SetSonicPi/Drums1.wav"
Drums2 = "User/Me/Desktop/SetSonicPi/Drums2.wav"
Drums3 = "User/Me/Desktop/SetSonicPi/Drums3.wav"
Drums4 = "User/Me/Desktop/SetSonicPi/Drums4.wav"

live_loop :Drums do
  drum, fx, par = [[Drums1, :krush,   {amp: 2}],
                   [Drums2, :slicer,  {phase: 0.5, decay: 1.5}],
                   [Drums3, :echo,    {phase: 0.25}],
                   [Drums4, :flanger, {phase: 1}]].choose
  with_fx fx, **par do
    sample drum
  end
  sleep sample_duration Drums1
end

At that point it might be simpler and more flexible to just have a case statement with the different options:

Drums1 = "User/Me/Desktop/SetSonicPi/Drums1.wav"
Drums2 = "User/Me/Desktop/SetSonicPi/Drums2.wav"
Drums3 = "User/Me/Desktop/SetSonicPi/Drums3.wav"
Drums4 = "User/Me/Desktop/SetSonicPi/Drums4.wav"

live_loop :Drums do
  case rand_i(4)
  when 0
    with_fx :krush, amp: 2 do
      sample Drums1
    end
  when 1
    with_fx :slicer, phase: 0.5, decay: 1.5 do
      sample Drums2
    end
  when 2
    with_fx :echo, phase: 0.25 do
      sample Drums3
    end
  when 3
    with_fx :flanger, phase: 1 do
      sample Drums4
    end
  end
  sleep sample_duration Drums1
end

Hopefully one of these works for you. Note that some of the things here (e.g. case) are from Ruby and not strictly supported by Sonic Pi, so they might not continue working in later versions.

Thx @emlyn, your answers are very clear and open my eyes and my mind !

1 Like

I have an other question :
How can I control a parameter from my harwear ? I’ve read a lot of things about that, but I don’t find the answer.
I have a nanoKontrol2 (Korg) and I want to control the amp: of an fx with a knob. How can I do that ?
I’ve seen the example in Sonic Pi :

live_loop :midi_piano do
use_real_time
note, velocity = sync "midi/nanokey2_keyboard/0/1/note_on"
synth :piano, note: note, amp: velocity / 127.0
end

I’ve anderstood how to play note on with a keyboard, but the midi CC ??..

Thanks for your answers and your patience.
fLogx

The midi CC will work very similar to the note_on, just with a different OSC address. If you look at the ‘Cues’ log window in Sonic Pi as you twiddle the knob, you should see what address it uses.

Also, the sync command will wait for the next OSC message before continuing, which is not what you want to do here. Instead you should replace it with get which will just return the last value, without waiting.

Hopefully that’s enough to get you started, but do post back if anything is unclear or you run into problems.

1 Like

Hi @emlyn and others,
Is it possible to specify the MIDI number of my controller in the OSC adress, something like that ?

/midi/nanokontrol2/0/1/control_change/16
or
/midi/nanokontrol2/16/1/control_change

To “kill” the number of the knob and just to have the value of my controller ? Because I have 8 knobs

If I understand correctly, the midi CC messages are all coming through on the same OSC address, with the knob number and the value both as return values. I don’t think there’s a way to address just one of the knobs directly, but you could use another live_loop to split out just the knob(s) that you want into separate keys (obviously adjusting the OSC address for midi CC messages and the knob numbers to match what your nanoKontrol2 sends):

live_loop :midicc do
  use_real_time
  knob, value = sync "/midi/nanokontrol2/something/control_change"
  if knob == 1
    set :knob1, value
  elsif knob == 2
    set :knob2, value
  end
end

live_loop :midi_piano do
  synth :piano, note: :e3, amp: get(:knob1) / 127.0
  sleep 1
end
2 Likes

thanks A LOOOOOT !!!
just a correction in your code for next people it’s :

amp : get[:knob1] / 127.0

1 Like

What if you try this with the sleep. How can you make sure it doesn’t glitch? I tried it an when reaching 0 state it starts to fail and gives me following error.

±-> :live_loop_midi_piano
loop did not sleep or sync!

I think you just need to limit the sleep to stop it getting too small: when it gets very small, Sonic Pi will try to run many iterations of the live_loop in a short time, and won’t be able to keep up.
You could try adding a small number, so that the sleep doesn’t get too small, something like:

sleep get[:sleep1] / 127.0 + 0.1