ok, good to know. i’ll check the wrap logic for negative rates. [ed: yeah it’s a little stupid.] it should not really require a workaround - though i think it is still good common sense to allow some pre- and post-roll, at least equal to the crossfade time. that way you dont have to worry about the ramifications of accessing a completely different part of the buffer during the crossfade.

@tehn looks like this is a potential issue in mlr.lua too.

in case it’s not clear, here’s what happens:

  • softcut performs sample-accurate looping with a crossfade. when a voice hits a loop endpoint, it keeps going for the duration of the xfade time, and another copy of the voice starts at the loop startpoint.

  • with negative rates, reverse “start” and “end” in the above and you see the issue. the phase should correctly wrap to the end of the buffer when you scrub backwards past zero.
    (gritty details:)

the description of the BOOM sound, and the occasional supernova crash reports, led me to fear that i had fumbled this in the worst way and was writing/reading to unitialized memory. but i don’t think this is the case:

  • buffer size is always a power of two. ugen stores a bitmask: mask = (buffer size) - 1.
  • any time an integer phase (sample index) is used (read or write) it is cast to unsigned int and has the mask applied, immediately before use.
    i therefore don’t think there’s any chance that the sample index could ever fall outside the buffer (though indeed, with negative input it could fall on some random place within the buffer - this will be cleaned up!), but please correct me if i’m missing something.
  • but, given that all voices share a buffer, if you expect to be using the start of the buffer, but you wrap to the end during xfade, you could be hearing stuff you didn’t expect to hear, esp. if another voice is using the end of the buf. i’d guess this is the cause of some MLR bug reports.
6 Likes

Been playing with SoftCut, and it’s been really great and straightforward so far. A couple of questions:

  • Is there a way to pan voices in SoftCut? I was attempting to use play_dac, but it wasn’t working quite as I expected.
  • I haven’t gotten clear_range to actually clear a buffer yet, but feel like I must be doing something wrong. It takes frames, and not time right?

works for me, can you be more specific?

[ed] i’ll be more specific.
to pan voice 1 hard left, this works for me:

engine.play_dac(1, 1, 1.0)
engine.play_dac(1, 2, 0.0)

hard right:

engine.play_dac(1, 2, 1.0)
engine.play_dac(1, 1, 0.0)

75/25 left/right:

engine.play_dac(1, 1, 0.75)
engine.play_dac(1, 2, 0.25)

of course you could make a lua func for equal-power panning. the patch levels have some smoothing built in. so here’s equal power:

(untested)

-- position in [-1, 1]
function xpan_voice(num, pos) 
  local theta = (pos + 1) * math.pi / 4
  local l = math.cos(theta)
  local r = math.sin(theta)
  engine.play_dac(num, 1, l)
  engine.play_dac(num, 2, r)
end

there’s other pan laws; for -4.5db law you would take the square root of the product of the equal-power and the linear.

clear_range

ah yeah sorry this is broken in supernova. it is bug. i made an upstream PR
[ https://github.com/supercollider/supercollider/pull/4137 ]

but we may ditch supernova anyway:
(issues with supernova load distribution)
[https://github.com/monome/norns/issues/626]

(consideration of multple scsynth processes instead:)
[ https://github.com/monome/norns/issues/630 ]

2 Likes

Ah, this is awesome-- thanks @zebra for that panning code. I was trying something a bit more naive, but that is what I was looking for.

I’m still seeing odd behavior when controlling these values using the encoders. If panned hard left or right: no issue. But when adjusting values using the encoders there is some jerkiness, and occasionally when dialing the level of a channel to 0 it doesn’t come back to full volume (even though I see logging from sc in maiden that seems accurate):

[ PatchMatrix: level_ , 0, 1, 1.0 ]

Now, it could very well be a fundamental misunderstanding some other setup in SoftCut/norns on my part, or I’m passing the wrong value ranges. I’m a new to SuperCollider, so apologies if I’m missing something obvious. Here’s a quick test as a sanity check. It’s a short looping buffer, recording from the inputs. The buttons set hard pan left and right, and then the encoders set the individual channel values directly (I used the code you posted above as well, but this script allowed me to dial in specific levels). Adjusting the encoders doesn’t work as I expect, until hitting zero. And then I notice a drop in volume as I bring them up again. This is usually fixed by using the buttons to hard pan left and right a couple of times.

cool, thanks for the feedback; i’ll take a look

@rryy

ahh you’re absolutely right; that is a bug; here is a fix

(patch matrix was applying level as levelScale envelope generator parameter. this is, non-obviously, only applied on a new envelope segment. so you could only get the level change by first setting it to 0. which i did, when testing, stupidly.)

thanks again for catching it, and sorry about that.


ehh, in fact duh, there’s no slew now. there used to be. it is steppy. we can ditch the envelope and add a slew. i think the motivation was just to shave a few CPU cycles when patch levels aren’t changing (most of the time) and pause the patch synth entirely when level is zeroed.

19 posts were merged into an existing topic: Norns 2.0: softcut

this thread is purely historical and was created to discuss the softcut engine on norns 1.0 – since then, many new improvements have been made. as syntax has been overhauled, here is a new thread for softcut discussion on norns 2.0: Norns 2.0: softcut

1 Like