Page 1 of 1

attempt to index out of range sample

Posted: Sat Sep 25, 2021 2:50 am
by Ethan_Pixelate
I am trying to make a function that slows down/speeds up a sound through SoundData, i cant just use Source:setPitch() because i will ultimately be overlaying this SoundData with others and have it exported to wav (Don't ask why, it's a really stupid project, or ask anyways cuz its also really funny).

The problem I'm having is that I keep getting an out of range error (note that im using the setSample and getSample with an extra number that respects what channel im operating on)

Code: Select all

local M = {}

M.Name = "Pitch Control"
M.Description = "Slows down, or speeds up a cut."

function M:Operate(Sound)
    local Speed = math.random(0.5,2)

    local SampleRate = Sound:getSampleRate()
    local Duration = Sound:getSampleCount()
    local Channels = Sound:getChannelCount()

    local NewDuration = math.floor(Duration*Speed)-1
    local NewSound = love.sound.newSoundData(
        NewDuration,
        SampleRate,
        Sound:getBitDepth(),
        Channels
    )
    for C=1,Channels,1 do
        for I=1,NewDuration,1 do
            local NormalizedI = I/NewDuration
            local SampleIndex = math.floor(NormalizedI*Duration)
            NewSound:setSample(I,C,Sound:getSample(SampleIndex,C))
        end
    end

    return NewSound
end

return M
this is the line causing the error in specific:

Code: Select all

NewSound:setSample(I,C,Sound:getSample(SampleIndex,C))
any help would be appreciated, thanks. :D

Re: attempt to index out of range sample

Posted: Sat Sep 25, 2021 3:35 am
by MrFariator
Going off a limb here, but as per wiki the sample positions start from 0 when using getSample/setSample. As such I think that erroring line should be along the lines of:

Code: Select all

NewSound:setSample(I-1,C,Sound:getSample(SampleIndex-1,C))
With the caveat that you'll have to be careful that the "SampleIndex-1" remains within [0,Duration-1], inclusive.

Because hyphotetically lets say the sample count of the original sound is 200, and the new sound will get 100 samples allotted to it. With your code you're eventually going to try touching either position 200 or 100, when the last valid position is at 199 or 99 respectively.

Re: attempt to index out of range sample

Posted: Sat Sep 25, 2021 3:59 am
by Ethan_Pixelate
I tried that, but I'm still getting the error, I'm also making sure that I cant go over the limit by having NewDuration be set to whatever *minus* 1, not sure if SampleIndex follows, but as evident by the fix not working, that doesn't seem to be the case either, was worth a shot though.

Re: attempt to index out of range sample

Posted: Sat Sep 25, 2021 10:39 am
by pgimeno
I think the problem is with NewDuration. First of all, due to the implementation of math.random in LuaJIT, this line will either give a value of 0.5 or 1.5 (which one of both is random):

Code: Select all

local Speed = math.random(0.5,2)
I think you want this instead:

Code: Select all

local Speed = math.random()*1.5 + 0.5
Then there's this:

Code: Select all

local NewDuration = math.floor(Duration*Speed)-1
The -1 makes it one sample short. If you have N=3 samples, the sample indices will be 0, 1, 2, i.e. from 0 to N-1; but if you have N-1=2 samples, trying to access index 2 will fail. Remove the -1 and do as MrFariator said.

Edit: Hmm, thinking about it, this is also suspect:

Code: Select all

 local NormalizedI = I/NewDuration
You get a fractional number there, and you don't know how the function is going to round it. I suggest you change it to this:

Code: Select all

local NormalizedI = math.floor((I-1)/NewDuration)
then use the value raw:

Code: Select all

NewSound:setSample(I-1,C,Sound:getSample(SampleIndex,C))
Although at this point, it's easier to loop from 0 to NewDuration-1 than to subtract 1 from each usage of I.

Re: attempt to index out of range sample

Posted: Sat Sep 25, 2021 11:43 pm
by Ethan_Pixelate
Alright, so I have applied the fixes up to the "local NewDuration = math.floor(Duration*Speed)-1", and the effect actually was successfully applied a couple of times, but then another error on the 3rd time it was used. The reason I didn't fix the rest is because I think I didn't make it clear enough why I was making NormalizedI a fractional number. The reason NormalizedI is a fractional number is because I'm trying to represent I as a percentage instead of an absolute integer position so that I can get a transformed position on Sound so that I can copy it to NewSound. In other words, nearest neighbor scaling for sound instead of textures, so rounding NormalizedI wouldn't really be a good thing because that would mean making it 0 or 1. Will try it anyways to see if it works though.

Re: attempt to index out of range sample

Posted: Sun Sep 26, 2021 2:13 am
by pgimeno
Yeah I was pretty off with that comment, sorry. If you can provide a runnable example maybe we can help better.

Re: attempt to index out of range sample

Posted: Sun Sep 26, 2021 3:31 am
by Ethan_Pixelate
Yeah, I probably should have done that in the original post, here it is:

Re: attempt to index out of range sample

Posted: Sun Sep 26, 2021 11:06 am
by pgimeno
Okay, the problem was using a 1-based index to access the samples. This works:

Code: Select all

local NormalizedI = (I-1)/NewDuration
But as I said, it's easier at this point to loop with a zero-based index instead of subtracting 1 twice:

Code: Select all

for I=0,NewDuration-1 do
The same problem is in RandomChopping. Looping from 0 to Duration-1 makes it start working in principle, but for me it crashes later because I-Start is negative when Start is > 0. I think you want I+Start there. Note that you don't use End, and even if you did, you have to watch out for End < Start. If you want to chop at random, you probably need to first pick a random length, then choose a start point between 0 and Duration - length, then copy `length` samples from there (not `Duration` samples, because in that case you'd go out of range again).

Re: attempt to index out of range sample

Posted: Sun Sep 26, 2021 5:21 pm
by Ethan_Pixelate
So I tried what you said and it works!!

Thank you so much :D