# Uh oh! Off-by one error in snd-inverse!

This makes me unhappy. I expect to see 0, 10, 10, and a count from 0 to 9. Instead I see 0, 10, 9, and a count from 0 to 8, and then 0.

Snd-inverse seems to neglect the last sample of the input! And I’m told integrate has the same problem.

``````(let*(
(arr (vector 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9))
(snd (snd-from-array 0 1 arr))
(inv (snd-inverse snd 0 10))
)

(print (snd-t0 inv))
(print (snd-srate inv))
(print (snd-length inv ny:all))
(terpri)
(dotimes (ii 10) (print
(snd-sref inv (* 0.1 ii))
))
nil
)
``````

Your Loop goes not high enough.
it stops at ii < 10 = 9.
That’s convenient for cases where you get the length of an Array, list or Sound because the indexing commences always with 0 and should therefore not Count up to the actual number of values contented.

I do no think you have explained why, even stopping at 9, I see a count from 0 to 8, and then, a 0 instead of 9.

I wonder what you try to achieve with it in the end.
Anyway, if you increase the Initial values by 0.1 (the first 0.0 included) you’ll get the proper amount of numbers (if the stop value of dotimes is also increased).
The purpose of snd-inverse is to create a map which can be used to warp sound-objects (i.e. in behaviours).
snd-compose is used to reassemble the sound.
An example that removes all pauses from speech or Music:

``````(setf *sr* *sound-srate*)
(snd-compose s
(snd-inverse
(integrate
(snd-oneshot
(s-abs s) 0.01 (/ 20 *sr*)))
0 *sr*))
``````

Why do you think my loop iterated the wrong number of times? I don’t get that either.

I made a strictly increasing sound with ten samples. I invert it. I write a loop that iterates over the ten unique values of the original sound, I give each to snd-sref, I expect to get back the ten indices of the samples for those values.

Here is changed code, and changed answers, and I don’t know why these make sense either. I think snd-length should give me ten for either set of ten numbers. The last sample was surely lost in the first example. That cannot be correct behavior. Change the first value, and it’s not lost. I do not understand the inconsistency.

``````    (let*(
(arr (vector 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0))
(snd (snd-from-array 0 1 arr))
(inv (snd-inverse snd 0 10))
)

(print (snd-t0 inv))
(print (snd-srate inv))
(print (snd-length inv ny:all))
(terpri)
(dotimes (ii 11) (print
(snd-sref inv (* 0.1 ii))
))
nil
)
``````

0
10
11

-1
-1.49012e-008
1
2
3
4
5
6
7
8
9

Ok, the Loop Counter is correct. But you should always use it with the actual length of the result of the inverse procedure.
I do not see a wrong behaviour. The function does what it is supposed to do when applied in the intended Fashion.
I am rather concerned about the Floating Point Errors, when dealing with Long sounds and big indexes.

Why is the loss of the sample valued 0.9, in my first example, correct behavior?

what do you think is the result from snd-inverse in general?
The length of the Sound returned can vary, according to the Sound it is fed with.
The Sound is a Kind of frequency Modulation. in combination with snd-compose, it will tell which value will be the next. The map (from-snd-inverse) should be made up from equal distanced values (0 1 2 3 …). Fractions will cause an fractional advance (i.e. Interpolation).
Your example with a ramp is rather unlucky.
It is a “pseudo” meaningful result.
Maybe there are others who can convey to you the properties of snd-inverse better.

Look: documentation says,

(snd-inverse signal start srate)
Compute the function inverse of signal, that is, compute g(t) such that signal(g(t)) = t.

For which values of t should that hold? Let’s test the identity:

``````    (let*(
(arr (vector 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9))
(signal (snd-from-array 0 1 arr))
(g (snd-inverse signal 0 10))
)

(dotimes (ii 10) (print
(snd-sref signal
(snd-sref g (* 0.1 ii))
)
))
nil
)
``````

Result is:

0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0

I’d say that is a bug! The function is not behaving as documented. Unless you can explain why 0.9 is one of the values of t that should be excluded from that identity. But I don’t see why, because 0.9 is indeed among the values that signal can return.

The documentation also says:
“This function is intended for internal system use in implementing time warps.”
The measure for if it is a bug or not is whether or not it fulfils its intended purpose.

I’ve not looked in detail at the problem, but perhaps try using snd-fetch to look at the actual sample values.

“Compute the function inverse of signal, that is, compute g(t) such that signal(g(t)) = t.”
Can that be done from a single point or does it require a pair of values?

Nyquist does expose a number of things for manipulating mathematical functions as “sounds,” in ways not meant for playing, like slope, integral, recip, … and snd-inverse is advertised as satisfying a certain identity.

It seems that you have to expand the Signal by one sample (as with integrate)
The same is the case with the wave-shaping function shape.
Roger himself was surprised that such was the case. I believe it’s written in the Soft Distortion tutorial.
Another example is pwl, where the last time index always must be given, although it is not included in the actual sample. Thus, your Sound would be:

``````(snd-pwl 0 10 '(0 0.0 9 0.9 10))
``````

I normally do not run in the missing sample Problem because I am using integrate before (which I Extend by one smp for precise measurements).
Over milions of samples, the lost of one is barely obvious but surely annoying for your Zero crossing detection.
But dangers you know are those you can avoid.