Update new loop range on sample load.

I am trying to figure out the best way to do this. I want the loopable range to be updated when I load a new sample to the new sample length. I want the previous loop point to remain but the range in which it can loop to be the length of the new sample. If I have a sample that is shorter than the previous sample then the loop range doesn’t work at all. This results in the loop parameters over shooting the length of the loaded sample. I am thinking I have to scale the loop start and end parameter to fit inside the new sample length on load?I haven’t been able to find a solution. Is this something that can be achieved?

Are you using Path Browser or Drop control on your macro page?

Try this script in program tree. Connect the Path Browser or Drop to script parameter Filename.
It should set the sample length, loop points if present and also change the zone name. Be aware of that when setting scope for waveform or Sample Display template.

function filenameChanged()
  local zone = this.parent:findZones(true)[1]
  local sample = AudioFile.open(Filename)
  if sample.valid then
    local name = string.sub(string.match(sample.fileName,"[^\\/]+$"),1,-5)
    zone:setName(name)
    zone:setParameter("SampleOsc.Filename", sample.fileName)
    zone:setParameter("SampleOsc.SampleEnd", sample.length)
    local rootKey = sample.rootKey
    if rootKey then
      zone:setParameter("SampleOsc.Rootkey", rootKey)
    else
      zone:setParameter("SampleOsc.Rootkey", 60)
    end
    local loops = sample.loops
    if loops[1] then
      zone:setParameter("SampleOsc.SustainLoopModeA", 1)
      zone:setParameter("SampleOsc.SustainLoopStartA", loops[1].loopStart)
      zone:setParameter("SampleOsc.SustainLoopEndA", loops[1].loopEnd)
    else
      zone:setParameter("SampleOsc.SustainLoopModeA", 0)
      zone:setParameter("SampleOsc.SustainLoopStartA", 0)
      zone:setParameter("SampleOsc.SustainLoopEndA", 0)
    end
  end
end

defineParameter("Filename", nil, "", filenameChanged)

Thank you very much Misohoza!

I will give this go. I’m using the path browser. The main problem I have is constraining or limiting the SustainLoopEnd/Start range of the new sample length. The new range for the loop end doesn’t stop when it reaches the end of the sample and just keeps increasing. I’ve tried defining the parameter range but I can’t get it to work with knobs or sliders. So I’m needing the loop controls to stop at the end of the loaded sample and not just keep increasing.

The code works well Misohoza. I still have the problem where the loop range doesn’t stop at the length of the file when adjusted. How can I restrict a knob,slider, range slider for SustainLoopEndA to the length of the loaded sample? I have tried defining the parameters which works for every other parameter except the loop range.

Try this:

function sampleStartChanged()
  local zone = this.parent:findZones(true)[1]
  if zone then
    zone:setParameter("SampleOsc.SampleStart", SampleStart)
  end
end

function sampleEndChanged()
  local zone = this.parent:findZones(true)[1]
  if zone then
    zone:setParameter("SampleOsc.SampleEnd", SampleEnd)
  end
end

function loopStartChanged()
  local zone = this.parent:findZones(true)[1]
  if zone then
    zone:setParameter("SampleOsc.SustainLoopStartA", LoopStart)
  end
end

function loopEndChanged()
  local zone = this.parent:findZones(true)[1]
  if zone then
    zone:setParameter("SampleOsc.SustainLoopEndA", LoopEnd)
  end
end

defineParameter("SampleStart", nil, 0, 0, 0x7fffffff, sampleStartChanged)
defineParameter("SampleEnd", nil, 0, 0, 0x7fffffff, sampleEndChanged)
defineParameter("LoopStart", nil, 0, 0, 0x7fffffff, loopStartChanged)
defineParameter("LoopEnd", nil, 0, 0, 0x7fffffff, loopEndChanged)

defineParameter("zoneScope", nil, "")

function onUndo()
  if undoInfo.updateDisplay then
    adjustRange()
  end
end

defineParameter{name = "undoInfo", default = {}, onChanged = onUndo, automatable = false}

function adjustRange()
  local zone = this.parent:findZones(true)[1]
  if zone then
    zoneScope = "@0:"..zone.name.."/"
  end
  --print(zoneScope)
  local sample = AudioFile.open(zone:getParameter("SampleOsc.Filename"))
  if zone and sample.valid then
    defineParameter("SampleStart", nil, 0, 0, sample.length, sampleStartChanged)
    defineParameter("SampleEnd", nil, sample.length, 0, sample.length, sampleEndChanged)
    defineParameter("LoopStart", nil, 0, 0, sample.length, loopStartChanged)
    defineParameter("LoopEnd", nil, 0, 0, sample.length, loopEndChanged)

    SampleStart = zone:getParameter("SampleOsc.SampleStart")
    SampleEnd = zone:getParameter("SampleOsc.SampleEnd")
    LoopStart = zone:getParameter("SampleOsc.SustainLoopStartA")
    LoopEnd = zone:getParameter("SampleOsc.SustainLoopEndA")
  end
end

function filenameChanged()  
  local zone = this.parent:findZones(true)[1]
  local sample = AudioFile.open(Filename)
  if sample.valid then
    local name = string.sub(string.match(sample.fileName,"[^\\/]+$"),1,-5)
    startUndoBlock("Load User Sample "..name)
    undoInfo = { redo = true, updateDisplay = true }
    this:setParameter("undoInfo", { redo = false }, true)
    
    local newzone = clone(zone)

    newzone:setName(name)
    newzone:setParameter("SampleOsc.Filename", sample.fileName)
    newzone:setParameter("SampleOsc.SampleEnd", sample.length)
    local rootKey = sample.rootKey
    if rootKey then
      newzone:setParameter("SampleOsc.Rootkey", rootKey)
    else
      newzone:setParameter("SampleOsc.Rootkey", 60)
    end
    local loops = sample.loops
    if loops[1] then
      newzone:setParameter("SampleOsc.SustainLoopModeA", 1)
      newzone:setParameter("SampleOsc.SustainLoopStartA", loops[1].loopStart)
      newzone:setParameter("SampleOsc.SustainLoopEndA", loops[1].loopEnd)
    else
      newzone:setParameter("SampleOsc.SustainLoopModeA", 0)
      newzone:setParameter("SampleOsc.SustainLoopStartA", 0)
      newzone:setParameter("SampleOsc.SustainLoopEndA", 0)
    end
    zone:removeFromParent()
    this.parent:appendZone(newzone)
    undoInfo = { redo = true }
    this:setParameter("undoInfo", { redo = false, updateDisplay = true }, true)
    endUndoBlock()
  end
end

defineParameter{name = "Filename", default = "", onChanged = filenameChanged, persistent = false, automatable = false}

function onLoad()
  adjustRange()
end

Load Sample.zip (7.61 KB)

Wow! Thank you very much Misohoza,

That works great. I was starting to think that it couldn’t be done. I will start to build this into my instrument (once I understand what’s happening in it). I notice the parameters are reset for controls each time the sample is loaded. How is that working?

So I have been trying to incorporate this code into my instrument by going through it bit by bit with my limited knowledge. How do I modify it to not update filename, rootkey and resetting the loop parameters everytime a new file is loaded? Is there a basic function to just stop the loop range from exceeding the sample file length?

Try this one. It’s using a ui script and is more simple. Maybe it will work better for you. Either way you can still adapt/change the script.
Load Sample UI.zip (6.39 KB)

Perfect!

Thank you again Misohoza. I really appreciate your help. I just read a previous forum request you had assisted another user with a similar request and thought “This is kind of what I am after”. So I am a little red faced as I had scoured the forum and reference material and somehow overlooked that post. Steinberg Forums. But the solution you just gave me is exactly what I am after. I have been building an instrument and this was the last piece of the puzzle.
I originally started building in Kontakt but found the process very archaic and limiting, The granular engine is very old unless you code a new granular engine in it like Straylight (That’s not going to happen). Falcon is incredibly basic in building instruments and from what I could see was only macro controls. I had built maybe 40% of my instrument in Reaktor and couldn’t decide what direction to take it, So it has become another project. So Halion I found is the best sampler for building a custom instrument. The support on this forum has been very good with your support and also AposMus.

Thanks Again!