How to replace a single value inside a ring, which is inside an array?

Hi.

I have an array with rings, which ticks various samples in live_loops.

This is considering a little project I mentioned earlier.

Array:

track = [(bools 1, 0, 0, 0, 0, 0, 0, 0),
         (bools 0, 1, 0, 0, 0, 0, 0, 0),
         (bools 0, 0, 1, 0, 0, 0, 0, 0),
         (bools 0, 0, 0, 1, 0, 0, 0, 0),
         (bools 0, 0, 0, 0, 1, 0, 0, 0),
         (bools 0, 0, 0, 0, 0, 1, 0, 0),
         (bools 0, 0, 0, 0, 0, 0, 1, 0),
         (bools 0, 0, 0, 0, 0, 0, 0, 1),
         (bools 1, 0, 0, 0, 0, 0, 0, 0),
         (bools 0, 1, 0, 0, 0, 0, 0, 0)]

Sound producing loops:

in_thread(name: :pattern) do
  live_loop :track0 do
    if track[0].tick
      sample sampl[0], rate: rate[0], amp: amp[0], pan: pan[0], attack: attack[0], sustain: sustain[0], release: release[0], pitch: pitch[0]
    end
    sleep spacing
  end
  live_loop :track1 do
    if track[1].tick
      sample sampl[1], rate: rate[1], amp: amp[1], pan: pan[1], attack: attack[1], sustain: sustain[1], release: release[1], pitch: pitch[1]
    end
    sleep spacing
  end
#etc
end

I would like to be able to replace just 1 bools value inside 1 track, changing the track to for example:

track = [(bools 1, 0, 0, 0, 1, 0, 0, 0), #there's 1 changed value here...
         (bools 0, 1, 0, 0, 0, 0, 0, 0),
         (bools 0, 0, 1, 0, 0, 0, 0, 0),
         (bools 0, 0, 0, 1, 0, 0, 0, 0),
         (bools 0, 0, 0, 0, 1, 0, 0, 0),
         (bools 0, 0, 0, 0, 0, 1, 0, 0),
         (bools 0, 0, 0, 0, 0, 0, 1, 0),
         (bools 0, 0, 0, 0, 0, 0, 0, 1),
         (bools 1, 0, 0, 0, 0, 0, 0, 0),
         (bools 0, 1, 0, 0, 0, 0, 0, 0)]

Closest I got so for, is to locate it, rebuild the ring as an array and then replace the selected track inside the array.

  i = 0
      mem = [0, 0, 0, 0, 0, 0, 0, 0]
      puts "mem:", mem
      8.times do
        if track[selTrack].tick(:klerezooi)
          puts "i", i, "YES" #this is for debugging, so I know where it's going
          if i == selVal then
            mem[i] = 0
          else
            mem[i] = 1
          end
        else
          puts "i", i, "no"
          if i == selVal then
            mem[i] = 1
          else
            mem[i] = 0
          end
        end
        i += 1
        sleep 0.1
      end
      puts "mem:", mem
      track[selTrack] = mem.ring

This works… right up until the last line.
The puts “mem”, mem line outputs the exact output I’m expecting, with one value changed.
When I replace the selected track with track[selTrack] = mem.ring, this produces (bools 1, 1, 1, 1, 1, 1, 1 , 1). Regardsless of the content of mem.

How do you turn arrays in to rings and rings into arrays?

I’ve noticed the (bools ) ring acts peculiar. It’s created as 1, 0, 1 - style, but puts like true, false, true - style?

This will output true, false, true -style:

    puts track[selTrack]

While (after some ruby googling), this will output 1, 0, 1 -style (though I would prefer it on 1 line):

mem = track[selTrack]
x = 0
    8.times do
      if selVal == x then
        puts ">", (mem[x] ? 1 : 0), "<"
      else
        puts (mem[x] ? 1 : 0)
      end
      x += 1
    end

I haven’t looked at the total problem but the conversions can be done as follows:

s=(ring 1,2,3,4)
puts "This is a ring",s
sa= s.to_a #using .to_a converts it to an array
puts "This is an array",sa
r=[1,2,3,4] #an initial array r
puts "This is an array",r
rr= SonicPi::Core::RingVector.new(r) #this uses internal Sonic Pi calls to produce a ring
puts "This is a ring",rr

Here’s some code which works, although I’ve changed the contents of the altered list manually.

track = [(bools 1, 0, 0, 0, 0, 0, 0, 0), #initial array
         (bools 0, 1, 0, 0, 0, 0, 0, 0),
         (bools 0, 0, 1, 0, 0, 0, 0, 0),
         (bools 0, 0, 0, 1, 0, 0, 0, 0),
         (bools 0, 0, 0, 0, 1, 0, 0, 0),
         (bools 0, 0, 0, 0, 0, 1, 0, 0),
         (bools 0, 0, 0, 0, 0, 0, 1, 0),
         (bools 0, 0, 0, 0, 0, 0, 0, 1),
         (bools 1, 0, 0, 0, 0, 0, 0, 0),
         (bools 0, 1, 0, 0, 0, 0, 0, 0)]

puts "initial array",track
tracka= track.map {|n| n.to_a} #changes entire array to lists
tracka[0]=[true,false,false,false,true,false,false,false] #changed track values
track =tracka.map {|n| SonicPi::Core::RingVector.new(n)} #changes back to rings
puts "final array",track
1 Like

Hi Robin.

I honestly don’t fully understand what’s happening in the code you sent, but it works.

Thank you very much!

OK glad that’s the case. Basically the code I sent uses the two conversions from the first reply .to_a to convert from ring to array and SonicPi::Core::RingVector.new( ) to convert from array to ring.
The addition is the use of the .map method which takes each element of an array and carries out the code inside the { } so converts in the first case all the rings in the array track to be simple arrays, and in the second changes them all back from arrays to rings again. In between you make the changes on the entry you want to alter.