Norns 2.0: softcut

finding some trouble with softcut.buffer_clear() being effective on 190303 – the command doesn’t seem to work as expected (an immediate clear of all buffers). if anyone is able to confirm operator error or otherwise, please lmk!

oh, thank you for reminding me. i think i saw similar behavior last week and forgot to report it. i’ll test again.


@tehn , @dan_derks
yes sorry, looks like arguments to the various clear commands got scrambled. sorry. easy fix

meantime, clear_region looks correct - see if it works for you

pushed softcut-buffer-fixes branch with quick fix for clear command.
will add buffer/write commands while i’m in here (i completely forgot about these), then PR
currently giving a more thorough once-over to the various load commands as well


softcut.buffer_clear_region worked(!, thank you!) but in case it helps, softcut.buffer_clear_region_channel doesn’t seem to have any effect, though it’s accepted as OK


PR with fixes to those issues

also added commands to save softcut buffer to disk. not yet glued to lua but will get round to that next time i sit down with norns HW


I’m trying to expose some softcut parameters (based on halfsecond engine).

When I add:
local p = softcut.params()
Everything works as expected and I can see/map these 2 parameters within a script with the engine initialised.

Then if I go further and add a few more, it seems to lock up the parameters screen and I cant access it, for example:

`local p = softcut.params()`

Any thoughts why this might not work? This is pretty much my first attempt at customising stuff, so consider me a total novice :smiley:

I was having the same issue earlier when creating a script based on halfsecond. I was able to scroll to the second cut param but when I changed it the number value wasn’t changing and the audio was unpleasant. Is there more glue needed than what’s in halfsecond that we’re missing?

EDIT - not in front of norns right now but it just occurred to me that maybe it should be

`local p = softcut.params()`

I’m on a phone r/n but will look when possible

Meantime, check for warnings about missing voice method

@Molotov, @speakerdamage

i looked. travelling with severely limited internet atm.

the params generated by softcut.params() method (which is a quick hack really) are kinda wonky. step size is not so useful, and the labels are goofy (i added some underscores, will make a minor PR) - but it basically works, i was able to add params for filter fc/rq/mode levels, rec/pre levels, loop/fade times, &c for multiple voices, from the maiden REPL

couple weird ones:

  • position is one that makes no real sense as a parameter.

  • loop points are basically useless because of the gigantic step size - better off making customized params appropriate to whatever the script is doing, and wrapping the lower-level setter methods exposed by softcut.lua module.

  • when i tried to set a param for rec flag some total crazy thing happened, some metro throwing errors, (@tehn is there a global called rec or something?? sorry i lost the error but i’m sure its reproducable)

but there is some weirdness where i can’t actually scroll to the end of the params list if the list is long enough - it neither moves the selection line, nor allows space at the bottom of the screen - which i take to be a bug in menu.lua. :biohazard:

btw @speakerdamage, sorry but the supposition in incorrect, p[1] is all the params for voice 1, p[2] for voice 2, &c.

hope that helps / makes sense


yep, all useful info, thanks! :slight_smile:

How many voices are available?

currently there are 6.

i’m considering a change that might bump it back down (to 4 or 5), in exchange for 1) the ability for record / play heads to cross each other in the same buffer/region without glitching, and 2) more solid per-sample sync between voices for stereo or whatever.


Non-norns owner here…
Just want to confirm that softcut is totally independent from supercollider/crone? and as such could theoretically be compiled outside of the norns ecosystem?

Possibly using lua/c to make a pd external? or even just a little app/daemon to be routed with jack? (Im sure its a non-trivial task to actually do this… but certainly interesting to consider!)

1 Like

yes ! this is possible. when I have some time I’m planning on giving a max external a shot. hosting in jack as-is is also doable.

1 Like

In 2.0 it’s already a standalone application/JACK client :slight_smile:

1 Like

oh such lovely news all around! definitely interested to explore this some more.

I’ve begun a new engine that exposes many of the wonderful filters in SuperCollider. I would like these filters to effect whatever is connected to the device inputs. Is this managed by SoftCut? My intuition led me to use the SoundIn UGen simply like so.

		SynthDef(\parametric, { arg out = 0, gain=0.5
			freq1 = 200, rq1 = 1, db1 = 6,
			freq2 = 800, rq2 = 2, db2 = -6,
			freq3 = 2000, rq3 = 3, db3 = 3,
			freq4 = 6000, rq4 = 4, db4 = -3;

			var eq1, eq2, eq3, eq4, in;

			in =, gain);
			eq1 =,freq1,rq1,db1,1);
			eq2 =,freq2,rq2,db2,1);
			eq3 =,freq3,rq3,db3,1);
			eq4 =,freq4,rq4,db4,1);,;
1 Like

Having few troubles with porting “reels” to 2.0,
@zebra could you please explain propper usage of _src & _dst arguments in
softcut.buffer_read_mono(file, start_src, start_dst, dur, ch_src, ch_dst) softcut.buffer_read_stereo(file, start_src, start_dst, dur)?


start params are time values in seconds. so you probably want 0,0 most of the time?

src and dst are source and destination

ch is channel, 1-2.

you can use -1 for dur to specify entire file length

1 Like

i was gonna add this to the luadocs instead of just answering here, so far got this:

--- read file to one channel
-- @tparam string file : path to source file
-- @tparam number start_src : start point in source file, in seconds
-- @tparam number start_dst : start point in destination buffer, in seconds
-- @tparam number dur : duration in seconds. -1 reads entire file / entire buffer, whichever is smaller
-- @tparam ch_src : source channel in source file (1 to <num channels>)
-- @tparam ch_dst : source channel in destination buffer (1 or 2)
SC.buffer_read_mono = function(file, start_src, start_dst, dur, ch_src, ch_dst)
  _norns.cut_buffer_read_mono(file, start_src, start_dst, dur, ch_src, ch_dst)

--- read file, stereo
-- @tparam string file : path to source file
-- @tparam number start_src : start point in source file, in seconds
-- @tparam number start_dst : start point in destination buffer, in seconds
-- @tparam number dur : duration in seconds. -1 reads entire file / entire buffer, whichever is smaller
SC.buffer_read_stereo = function(file, start_src, start_dst, dur)
  _norns.cut_buffer_read_stereo(file, start_src, start_dst, dur)

so, minor correction:

it will use the entire file length, or the entire buffer length, whichever is smaller

also should say that these haven’t really gone through a large amount of testing yet; your help there is appreciated but don’t be surprised if there are bugs


i need to finish making a block diagram of the whole system.

softcut (a jack client) has a stereo input bus

crone (the mixer client) has separate stereo input busses for 1) hardware input (‘ADC’), 2) softcut input (‘CUT’), 3) supercollider (‘EXT’), and three corresponding output stereo busses (DAC/CUT/EXT.)

crone creates a special pre-FX stereo mix for softcut which can include ADC and EXT (and maybe TAPE in a future update.)

crone is also responsible for forwarding ADC to EXT, and EXT to FX/DAC . supercollider jack client doesn’t have its I/O connected to hardware, only to crone.

so, TL/DR: make an engine that houses your filters, turn the EXT->CUT level up, and the ADC->CUT level down, and all input to softcut will be processed by your filters.