Sample Start/End in Macro Page?

Yes thanks, I see, no problem I just added the two lines I added in the previous script and it works great! Thanks a lot for your help!

1 Like

I have clicks and pops when I loop a grain zone, I tried all possible solutions, crossfading the loop and adding a fade in and fade out to the sample but I continue to have those clicks and pops.
Any idea how I can avoid them? My instrument is completely useless with those clicks and pops!
This is the modified script that I’m using, as you can see when I change the sample start and end points the loop start and end point change accordingly.

But The problem is NOT the script, I tried also building a simple instrument with a grain zone, setting the same values for the sample start/end points and the loop start/end points and I have the same problem. This problem is not happening in padshop.

local zones = this.parent:findZones()

zoneNames = {}
for i = 1, #zones do
    zoneNames[i] = zones[i].name
end

function zoneSelectChanged()
    getSampleLength()
    scope = "@0:"..zones[ZoneSelect].name.."/"
end

defineParameter("ZoneSelect", nil, 1, zoneNames, zoneSelectChanged)
defineParameter("scope", nil, "")
defineParameter("SampleStart", nil, 0, 0, 0x7fffffff, 1)
defineParameter("SampleEnd", nil, 0, 0, 0x7fffffff, 1)
defineParameter("Filename", nil, "", function() onFilenameChanged() end)
defineParameter("PitchDetectionProgress", nil, 0, 0, 100)
defineParameter("PitchDetection", nil, false)

function sampleStartChanged()
    local zone = zones[ZoneSelect]
    zone:setParameter("SampleOsc.SampleStart", SampleStart)
zone:setParameter("SampleOsc.SustainLoopStartA", SampleStart) 
   if SampleEnd < SampleStart then
        SampleEnd = SampleStart
        zone:setParameter("SampleOsc.SampleEnd", SampleEnd)
    end
end

function sampleEndChanged()
    local zone = zones[ZoneSelect]
    zone:setParameter("SampleOsc.SampleEnd", SampleEnd)
zone:setParameter("SampleOsc.SustainLoopEndA", SampleEnd) 
   if SampleStart > SampleEnd then
        SampleStart = SampleEnd
        zone:setParameter("SampleOsc.SampleStart", SampleStart)
    end
end

function setRootkey(sample)
    local zone = zones[ZoneSelect]
    local pitch, voiced = sample:getPitch(0, -1)
    if voiced and voiced then
        local rootkey, detune = math.modf(pitch)
        if detune >= 0.5 then
            rootkey = rootkey + 1
            detune = detune - 1
        end
        detune = math.floor((detune * 100) + 0.5)
        print(pitch, voiced, rootkey, detune)
        zone:setParameter("SampleOsc.Rootkey", rootkey)
        zone:setParameter("SampleOsc.Tune", detune)
    end
end

function keyTextFromSampleName(st)
    local notes = {c = 0, d = 2, e = 4, f = 5, g = 7, a = 9, b = 11}
    local mn = {}
    st = string.match(st, "([^\\/]+)%.%a+$")
    print(st)
    for k, s, n in string.gmatch(st, "[_%-%s]([A-Ga-g])(%#?)(%-?%d)") do
        if k and n then
            local midinn = notes[string.lower(k)] + (s == "#" and 1 or 0) + (n + 2) * 12
            table.insert(mn, midinn)
            print(k, s, n, midinn)
        end
    end
    return mn[#mn]
end

function onFilenameChanged()
    local zone = zones[ZoneSelect]
    local sample = AudioFile.open(Filename)
    if sample.valid then
        zone:setParameter("SampleOsc.Filename", sample.fileName)
        zone:setParameter("SampleOsc.SampleStart", 0)
        zone:setParameter("SampleOsc.SampleEnd", sample.length)
        -- sample start and end parameters
        defineParameter("SampleStart", nil, 0, 0, sample.length, 1, sampleStartChanged)
        defineParameter("SampleEnd", nil, 0, 0, sample.length, 1, sampleEndChanged)
        SampleStart = 0
        SampleEnd = sample.length
        -- rootkey and detune
        local rootKey = keyTextFromSampleName(sample.fileName)
        zone:setParameter("SampleOsc.Rootkey", rootKey or 60)
        zone:setParameter("SampleOsc.Tune", sample.detune or 0)
        if not rootKey and PitchDetection then
            sample:analyzePitch(setRootkey)
            while sample:getPitchAnalysisProgress() < 1 do
                PitchDetectionProgress = sample:getPitchAnalysisProgress() * 100
                wait(250)
            end
            PitchDetectionProgress = 0        
        end
    end
end

function getSampleLength()
    local zone = zones[ZoneSelect]
    local fn = zone:getParameter("SampleOsc.Filename")
    local sample = AudioFile.open(fn)
    if sample.valid then
        defineParameter("SampleStart", nil, 0, 0, sample.length, 1, sampleStartChanged)
        defineParameter("SampleEnd", nil, 0, 0, sample.length, 1, sampleEndChanged)
        SampleStart = zone:getParameter("SampleOsc.SampleStart")
        SampleEnd = zone:getParameter("SampleOsc.SampleEnd")    
    end
end

function onLoad()
    zoneSelectChanged()
end

function onNote(e)
    playNote(e.note, e.velocity, -1, zones[ZoneSelect])
end

It’s probably because the loop points are not at zero crossing. If the fades and crossfades don’t help this could be a problem.

I’m still experimenting but it looks like disabling “Snap” and enabling “Snap to zero crossing” improve a lot the clicks and pops problem