Rangl

rangl

Arc based granular four track sampler with live recording and friction.

Adapted from ash/angl after being heavily inspired by @dan_derks to have a poke around scripts (thanks!) and from @infinitedigits and his work on granchild. rangl is a small arc controlled granular player with four tracks. It is based on angl but adds support for

  • adjusting the level of each track,
  • live recording of tracks, and
  • adding friction to tracks (think spinning prayer wheels).

Requirements

norns, arc, and the Glut engine (comes with ash).

Documentation

Press K3 to switch modes. The modes are

speed: adjust the speed on the four tracks. Hold K2 and touch arc
to set speed to zero.

pitch: adjust pitch on the four tracks. Hold K2 for fine control.

record: touch arc to select track. Hold K2 and press K3 to start
recording. Touch another track to end recording or hold K2 and press
K3.

level: adjust level of the individual tracks.

friction: adjust friction for the individual tracks.

Download

or install from maiden:

;install https://github.com/tgk/rangl
39 Likes

haven’t had a chance to try it yet but as soon as i saw “friction” and “prayer wheels” i had to know how you did it

fr.time = FRICTION_RATE
fr.event = function()
  for v=1,VOICES do
    local friction = params:get(v.."friction")
    if friction > 0 then
      params:set(v.."speed", ((100 - friction)/100)*params:get(v.."speed"))
    end
  end
end

person, if you only knew how many hours i spent googling and deciphering prior bits of arc code to try and understand a way to do this…the only way i can communicate that is that i last posted about this in may of 2019 and i am still thinking about it

wildly, i actually have an extremely similar bit of code in a WIP script of mine and still somehow never made the connection that i didn’t actually need to understand physics in real life to make the wheels slow down. bah

thanks and congrats! definitely will try to check it out

8 Likes

Thanks! I did consider getting out some more serious stuff that more closely modelled friction in the real world but in the end I think worked out better since this solution is so much easier to read for humans :blush:

3 Likes

wowowow! super nice layering + manipulation in your demo + yesss you opened the flood gates with those spinning wheels!!! super glad to have a clean Lua example to point to!!! :revolving_hearts: :ferris_wheel:

5 Likes

what a sweet setup, a beautiful demo and really neat concise code! don’t have an arc to play with this, but I loved seeing all of this

4 Likes

timestamp 01:05 tho

3 Likes

Thanks @infinitedigits - the code is very heavily inspired by your live recording work and wouldn’t have been possible (or at least not as clean) had it not been for your work. Much appreciated!

2 Likes

in LaTeX, you type \langle angle brackets \rangle with “\langle” and “\rangle”, so I guess if I (or anyone else) does their own spin on this very cool!! script, we know what to name it

1 Like

This is so very fun, thank you for creating and sharing it!

1 Like

I am having a lot of fun with this script. Thanks so much. Now I need a usb footswitch. Unless there is a way to hack in the threshold recording like in cheat codes2. :black_heart:

2 Likes

Uh sorry I’m not familiar how cheat code works. I have yet to acquire a128 grid :blush:

oh, it just uses the built-in system polls to track amplitude and calls a specific function when a threshold is crossed (exemplified in oooooo as well + was the inspiration!)

basic setup:

function init()
  params:add_control("record_threshold","rec threshold",controlspec.new(1,1000,'exp',1,85,'amp/10k'))
end

amp_in = {}
local amp_src = {"amp_in_l","amp_in_r"}
for i = 1,2 do
  amp_in[i] = poll.set(amp_src[i])
  amp_in[i].time = 0.01
  amp_in[i].callback = function(val)
    if val > params:get("record_threshold")/10000 then
      -- your recording function goes here!
      amp_in[i]:stop() -- once threshold is crossed, we don't need to listen for it anymore
    end
  end
end

function arm_threshold_recording()
  amp_in[1]:start()
  amp_in[2]:start()
end
4 Likes

Very helpful piece of code, thank you!

While implementing this in a script I noticed that if I don’t place the poll setup inside the init() function I can’t start the poll. So placing this

within the init() function makes it work. Is this meant to be like that or am I missing something?