here’s the only one i’m aware of

these is a large rewrite underway that replaces all position logic and provides “hard sync.”

if you found another, i could use a more minimal repro case than “wrms.”

@andrew now i’m looking in wrms i see you are using rec flag a lot (maybe? assuming supercut module passes it through to softcut module via metatable but didn’t follow the whole trail.)

if so, best to avoid this in realtime. it’s a hard process flag. use it when you’re not planning for a voice to record to conserve CPU. for this use case, just set rec_level=0 and pre_level=1. (it will affect overdub fidelity maybe a little if you run it for months or years or something.)

this should avoid the linked issue.

i’m like 90% sure that’s it - seems like it has to do with record toggling. i’ll try and run some tests and see if i can contribute some helpful info

edit: gotcha i can try that out. that record flag is mapped to a norns key so definitely used at runtime

(lol, this is the same exact thing further up in this thread)

1 Like

Not sure if this could be related, but @zebra gave some advice upthread you may want to take a look at.

https://llllllll.co/t/norns-2-0-softcut/20550/150?u=nosollution

Edit: I think you already saw it @andrew ; leaving for ref.

this is definitely my fault for not clarifying the purpose of rec in the API docs and for giving it the most conveniently typable name.

is it expected behavior that if I mute softcut in the mixer (turn the level all the way down) that the softcut return level in the reverb is unaffected? I’m still getting the wet trails from my muted softcut sounds.

I don’t recall this being the case previously, but maybe I’m missing something…

softcut send to reverb is pre-fader. this param is in the reverb group.

would it ever be possible to configure it to be post-fader?

use-case is using some app that uses both an engine and softcut (like less concepts and refrain) and wanting to be able to fade in the softcut portion within a performance using the mixer, rather than having to adjust levels in both places.

edit - this would also be helpful if you want to just hear the monitor input to start, then fade in the softcut output in one gesture.

I also noticed that the engine send is post-fader? Is there a good reason for the difference?

actually i would call this a mistake; it doesn’t match the intended routing and doesn’t seem particularly useful… thanks for pointing it out.

simple change, here it is

3 Likes

i’m trying to setup automatic looping of multiple samples loaded into the same buffer with the following code (using bundled samples in the example below):

local samples = {
  first = {
    path = _path.audio .. "/tehn/drumilk.wav",
    duration = nil,
    start = nil,
  },
  second = {
    path = _path.audio .. "/tehn/drumilk.wav",
    duration = nil,
    start = nil,
  },
  
}

local voices = {
  second = 1,
  first = 2,
}

local function load_samples()
  local start = 0

  for key, sample in pairs(samples) do
    local channels, frames, samplerate = audio.file_info(sample.path)
    softcut.buffer_read_mono(sample.path, 0, start, -1, 1, 1)
    
    sample.duration = frames / samplerate
    sample.start = start
    
    print('loaded', key, 'at', start, 'duration', sample.duration)

    start = start + util.round_up(sample.duration)
  end
end

local function setup_voices()
  for key in pairs(voices) do
    local voice = voices[key]
    local sample = samples[key]

    softcut.enable(voice, 1)
    softcut.buffer(voice, 1)
    softcut.level(voice, 1)
    softcut.play(voice, 1)
    
    softcut.loop(voice, 1)
    softcut.loop_start(voice, sample.start)
    softcut.loop_end(voice, sample.start + sample.duration)
    
    print('setting voice', key, 'loop', 'to', sample.start, sample.start + sample.duration)
    
    softcut.position(voice, sample.start)
    softcut.level_slew_time(voice, 0)
    softcut.rate_slew_time(voice, 0)
    softcut.level(voice, 0.25)
  end
  
  softcut.level(voices.first, 0)
end

local function phase(voice, phase)
  if voice == voices.first then
    -- print('phase', voice, phase)
  end
end

function init()
  load_samples()
  setup_voices()

  softcut.event_phase(phase)
  softcut.phase_quant(voices.first, 1/10)
  softcut.poll_start_phase()
end

function redraw()
  screen.clear()
  screen.update()
end

the following output is produced in maiden, which seems correct (with the exception that util.round_up rounds 4.8 up to 6 for some reason).

loaded	first	at	0	duration	4.8
loaded	second	at	6	duration	4.8
setting voice	first	loop	to	0	4.8
setting voice	second	loop	to	6	10.8

but i hear audible pause just before the sample is looped. am i doing something the wrong way here?

UPD: nvm, figured it out. I’ve been using 44.1kHz samples in my tests and after trying to resample them to 48kHz i got nice seamless playback. this doesn’t seem to be a documented point, though.

1 Like

you beat me to it. you’re right, 48khz requirement needs to be more prominently displayed. (or of course we could just resample on import.)

2 Likes

perhaps it’d be best under the API docs? currently, it’s under all the usability docs (tape, fileshare > audio, and the general faq).

2 Likes

You just made me realize that my code would be much simpler if I was resampling my drum loops (which can be a mix of sample rates depending on the file) on import for Softcut playback, rather than modifying the rate on a per-loop basis.

Is there a simple way to do this right now? I can only think of loading a file into a temporary spot on a buffer, then playing back at a modified rate to record onto the destination buffer.

that would work. but you could also just process your files directly with ffmpeg or sox ?

Oh right, that would be simpler. Can I rely on either or both of those being preinstalled on Norns so that I can run them dynamically from my app? I’d like to be able to support arbitrary WAV files for users of Beets without requiring them to do the transcoding themselves.

I think you could just include them in your script’s folder and call them from lua.

Dumb question(?) - for softcut.position (voice, value) what are the units for value?

Seconds?

ye 'ol seconds is correct

Dreaming of a softcut function to get audio sample data as an array/table. (That could then be drawn on display)

I hacked the following together In python tonight, but it’s pretty slow to load and barfs on some samples.

5 Likes

Have you seen Reaper’s ReaPeaks? It’s a pretty simple format for storing peak information. It zooms easily, can be saved alongside a sample, and if you use Reaper, it can generate those for you.
http://reaper.fm/sdk/reapeaks.txt