Would a sample playback module be a possible addition?

And/Or would it possible to get the audio from TAPE as an input?

A sample playback module is in the works (SPVoice here https://github.com/antonhornquist/r/blob/master/lib/r.scd#L3912-L4128) . This module does not stream samples from disk, they need to be loaded to memory. A few additional engine commands have to be added for this to work (ie. at least readsample - in the works here https://github.com/antonhornquist/r/blob/master/lib/r.scd#L498).

EDIT: With SPVoice it is possible to read files recorded using TAPE and play them back. Right now there’s no possibility to feed TAPE output into engines, though, so as with any other engine R cannot use live TAPE output for processing. TAPE is a separate process (implemented in C++). With a bit of jackd plumbing it sounds feasible to route TAPE output to engines. @zebra or @tehn I don’t recall, has this feature been discussed?

/Anton

4 Likes

I’m wondering about new Clock coroutine options and how those might work to sync an LFO to global clock.

Would this be doable with the existing LFO modules?
(It’s late for me so I’m not quite piecing that together yet).

Hi,

I’ve not tried to sync LFOs with the Lua scripting layer in any way yet. Also, I unfortunately haven’t had the time to use the Clock coroutine functionality.

That said, regardless of the clock (this could be a metro too I guess) - if you know a “current tempo” and would like to sync on a certain beat/subdivision you might get something going by

  • continously updating the Frequency parameter of an LFO module to what is the “current tempo” (a BPM to LFO rate conversion would have to be made and Frequency would have to be updated when BPM changes)
  • resetting the LFO using the Reset parameter on certain beats/subdivisions.

Let me know if you need clarifications. Again - this is not something I’ve tested in practice but seems like the only reasonable way to get it to work since the LFOs - as all things R - run in audio rate as opposed to control rate on the SC side.

2 Likes

is there a way to tell if if a modules connection is a inlet or an outlet?

for example this code:

 function getModules()
  local loc = 1
  for k,v in pairs(R.specs) 
    do
    list_content[loc] = k
    loc = loc + 1
    print(k)
    for i,j in pairs(R.specs[k])
      do
       print('---' .. i)
    end
  end
end

outputs:


Amp

—Level

FShift

—Frequency

—FM

Decimate

—DepthModulation

—Rate

—SmoothModulation

—RateModulation

—Depth

—Smooth

is there a way to list if those are inputs or outputs? Maybe using “generateLuaSpecs”? Sorry I might be running before I can walk.

Thanks!
Eric

Hi Eric!

Your code lists module parameters, not inputs/outputs. This
is simply because that’s what has been generated as Lua specs to R.specs (using the generateLuaSpecs SC method).

You’re right in the need for other metadata Lua side though. It’s something I’ve been working on for some time. There’s a new way of defining modules with more metadata possible to specify SC side. So I now made a new update of r.lua covering inputs and outputs too. R.specs will remain as is describing parameter specs, for backwards compatibility. R.metadata, which I just added, contains more extensive metadata. Let me know if that helps (you’d have to pull the latest from the repo) for your use case.

BTW, thanks for referring to generateLuaSpecs - I just re-read and noticed a typo in the readme which I also fixed earlier today.

1 Like

Thank you for the information, and sharing the project, its very nice!

Question 1:
How would one go about adding a “Feedback” control for a Delay?

EDIT: Found Rymd and I’m trying to use that as an example of how to do feedback amount, but it seems a bit touchy so far and some gain values make it get louder each repeat (?)

Question 2:
What do you think about a LongDelay module with something like:

'DelayTime' -> (
    Spec: ControlSpec(1, 120, 'lin', 0, 4, "sec"),

I’m trying to add a LongDelay module by copying Delay in R.sc, but I can’t seem to get it to work. (even just copying Delay and changing just it’s name)

I get an error unable to create "Delay". invalid module type "LongDelay" in maiden when starting my test script. I’ve ;restarted SC after making changes to R.sc and setup an appropriate listing in r.lua. What else am I missing?

Is your code posted anywhere? Here’s a commit where I added a pink noise module. It’s a super simple example, but maybe it will be useful to see what was involved.

1 Like

@okyeron @Justmat

Hi! Very sorry, I’ve refactored R engine considerably but old left-overs are not removed yet and docs are not updated. Modules are now defined in the main r.scd file (yeah, it’s in one big file :slight_smile: ) :

See the stdModules array here:

3 Likes

Specifically, re your questions.

Question 1:
In Rymd I just loop back the audio with a gain stage in between. It is, of course, possible to add internal feedback in the Delay module (I guess using a local buffer would do). With an external path it’s possible to pass the signal that is fed back through additional modules - in Rymd there’s a filter in the feedback path, and IIRC the signals are being cross-fed left / right.

Question 2:
A module with longer delay makes sense. See above link for how modules now are created. The code alone likely will make sense (I’ll try to update the docs soon). Just make sure 120 secs do not allocate too much memory for the PI to handle.


By the way - to get a faster feedback loop I spent some time to create a “norns engine tester” kind of capability for prototyping scripts in SuperCollider on a regular computer. This only covers the subset of norns features I actually use in my scripts and is currently undocumented + unsupported.

Anyhow - with this you should be able to run a bunch of my scripts (ie. bleeding edge versions moln, rymd, bob and skev) on the computer. Just open the files and evaluate the content.

3 Likes

Thnx!

I’ll look at r.scd tonight.

What would be a quick/easy way to determine this on the pi?

I know top will show me cpu use…

(120 was just a arbitrary number - 60 may be plenty?)

Welp… looks like anything over 20 seconds barfs with this:
JackDriver: exception in real time: alloc failed, increase server's memory allocation (e.g. via ServerOptions) (on Pi4 2GB). Have not attempted to change via ServerOptions.

increasing server memory can be done by uncommenting here:

[ https://github.com/monome/norns/blob/master/sc/core/Crone.sc#L70 ]

and in fact should probably be done in main branch since we aren’t using supernova.


but also another way is to replace DelayC with BufDelayC, and supply a buffer for max delay size. buffers are allocated from the heap and limited only by physical memory. (should have some hundred MB, so minutes not seconds.)

this option could be noticeably less performant if you are making a large number of delays. but on balance i think most SC folks would agree it is better to use the heap than to make server mem allocation very large.

4 Likes

OK so… trying to do this and failing so far. The following doesn’t get me any sound. (numFrames below for 60 seconds)

snipped from r.scd

		ugenGraphFunc: {
			|
				in_In,
				in_DelayTimeModulation,
				out_Out,
				param_DelayTime,
				param_DelayTimeModulation,
				visual_DelayTime
			|
			var buffer = Buffer.alloc(numFrames: 48000*60, numChannels: 1);
			
			var sig_In = In.ar(in_In);
			var sig_DelayTimeModulation = In.ar(in_DelayTimeModulation);

			var delayTimeSpec = ControlSpec(0.5, 120, 'lin', 0, 4, "sec");

			var delayTimeSec = delayTimeSpec.map(
				delayTimeSpec.unmap(param_DelayTime) + (sig_DelayTimeModulation * param_DelayTimeModulation)
			);

			var delayed = BufDelayC.ar(buf: buffer.bufnum, in: sig_In, delaytime: delayTimeSec); 

			Out.ar(out_Out, delayed);
			Out.kr(visual_DelayTime, delayTimeSec);
			buffer.free;
		}

examples show a server as a variable for Buffer.alloc, do I need to do that here or is the default server assumed? If I need it what do I use? (context.server? Server.default? )

b = Buffer.alloc(s,44100,1);

In SuperCollider buffers need to be allocated and freed outside of the ugenGraphFunc. Here you’ve stumlbed on a limitation with the current r framework - which abstracts away a lot of things and does not deal with buffers custom to modules yet. So the BufDelayC route is not really feasible right now. I can look into whether it can be supported in some way (by providing a way to create buffers for modules), but right now it’s not as easy as with writing an engine from scratch in SuperCollider.

1 Like

I’m new to SuperCollider so I may be missing something, but: I’ve definitely made buffers inside my SynthDefs before and had them work just fine… Is there something I’m doing wrong, or misunderstanding how my plain ol SynthDefs may be different from how R is constructed?

(For example, here’s the Delay pedal for Pedalboard and an Amp simulator that uses a buffer for an efficient transfer function/wavetable)

I think it’s due to how R is constructed?
see here for where the modules get setup: https://github.com/antonhornquist/r/blob/5395bab6158f94107a1d3e1a898f85e689da320f/r.scd#L1822

As far as I can tell that func is just sent to synthdef.new https://github.com/antonhornquist/r/blob/5395bab6158f94107a1d3e1a898f85e689da320f/r.scd#L1333

Back to your original question: have you tried sending context.server to Buffer.alloc's server argument?

var buffer = Buffer.alloc(server: context.server, numFrames: 48000*60, numChannels: 1);

like @jah, i am surprised that this is possible, but it seems like limitations are always changing in SC-land.

it doesn’t seem like SynthDef.wrap is supplying any special magic.

however, @okyeron you definitely don’t want to call buffer.free until you’re done with the synth.

and @21echoes i can’t immediately see where those buffers are being freed. (are buffers allocated in a ugen graph func, freed automatically when the synth is freed? seems worth checking for leaks.)

1 Like