Tileable Noise Function with dynamic period

I’m working with a NeoPixel LED strip that supports 0-255 RGB values. I’m programming some animations for it with an Arduino Yun. I wanted a noise function, which unfortunately does not come natively with Arduino. So I decided I’d find one.

I found the following noise function, which seems optimized for Arduinos specifically. Unfortunately, I don’t fully understand it, as it has no comments and is doing some fancy bit-shifting for most of its math. It’s also programmed in a very unreadable way, but I suppose that’s to be expected with optimized code…

Relevant code here:

// returns a value between 0 - 255 for lights
int renderNoise(unsigned long x, unsigned long y, unsigned long z)
{ //return constrain(137 + inoise(x, y, z)>>9, 0, 255); // 127 + 10 zie Processing
  return 137 + (inoise(x, y, z)>>9);
  //return 137 + (inoise(x, y, z)/512);
}
 
long inoise(unsigned long x, unsigned long y, unsigned long z) 
{
      long X = x>>16 & 255, Y = y>>16 & 255, Z = z>>16 & 255, N = 1L<<16;
      x &= N-1; y &= N-1; z &= N-1;
     
      long u=fade(x),v=fade(y),w=fade(z), A=P(X)+Y, AA=P(A)+Z, AB=P(A+1)+Z, B=P(X+1)+Y, BA=P(B)+Z, BB=P(B+1)+Z;
      
      return lerp(w, lerp(v, lerp(u, grad(P(AA), x   , y   , z   ),  
                                     grad(P(BA), x-N , y   , z   )), 
                             lerp(u, grad(P(AB), x   , y-N , z   ),  
                                     grad(P(BB), x-N , y-N , z   ))),
                     lerp(v, lerp(u, grad(P(AA+1), x   , y   , z-N ),  
                                     grad(P(BA+1), x-N , y   , z-N )), 
                             lerp(u, grad(P(AB+1), x   , y-N , z-N ),
                                     grad(P(BB+1), x-N , y-N , z-N ))));
}
   
long lerp(long t, long a, long b) { return a + (t * (b - a) >> 12); }
 
long grad(long hash, long x, long y, long z) 
{ long h = hash&15, u = h<8?x:y, v = h<4?y:h==12||h==14?x:z;
  return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}
 
long fade(long t) 
{
  long m = (t >> 8) + 1;
  m = m > 255 ? 255 : m;
  long t0 = F(t >> 8), t1 = F(m);
  return t0 + ( (t & 255) * (t1 - t0) >> 8 );
}

My problem is, I need the LED strip values to match on either end, as I’m going to be making a circular configuration. Thus, I need to know the period of my noise function, or be able to define it, so the first pixel value blends right into the last pixel value.

I tried modifying the “p” table to be unshuffled (0-255, in order) in the hopes that that would show the noise period, but it still showed up noisy, so I obviously don’t quite understand how this is working…

Is there another noise implementation out there that might be of more use? Or can someone tell me where in this code I can define the period?

I would like to avoid a computationally heavy solution. I would also love it if I could input the period as an argument to the function. I also only need 1D noise (just an led strip).

Thanks!

My problem is, I need the LED strip values to match on either end, as I'm going to be making a circular configuration.

I don't understand why.
Why do you want the same pixel value at the physical join and yet you are happy to have large discontinuities between any other pair of pixels.

I do want the ends to line up, but there is no large disparities between other pixels. Noise provides smooth interpolations between random values, so the values throughout the strip change smoothly. Except the endpoints, which don't line up, thus the issue. Does that explain it better?

Interesting, I will have to have a play with that! I am planning a cylindrical display.

As for the endpoints, I suggests generating n-1 points then interpolating point [n] as the average of [1] and [n-1].

Noise provides smooth interpolations

That is not what the rest of the world calls noise.

Yes put them in an array first, then apply the smoothing, you can make the array wrap round and apply the smoothing to the one before and the one after.
You will need two arrays one for the random numbers and the other for the smoothed value.

Please do not call it noise, at this stage it isn't.

Sorry for the confusion... I come from computer graphics and there we most assuredly do call it noise. I suppose Perlin Noise or Simplex Noise or something would've been more explicit. Many shader languages have a noise function built in called "noise".

Yes put them in an array first, then apply the smoothing, you can make the array wrap round and apply the smoothing to the one before and the one after.

I thought the first array was just random numbers, so how does it wrap around? The period would be defined by this array length, correct? So if I wanted a dynamic period, I could use less of the array, or loop it successively.

You will need two arrays one for the random numbers and the other for the smoothed value.

Assuming I'm correct above, I understand the first array, which is just a scrambled array of points within my range and length equal to period. The second smoothed value array I don't quite understand... Is it for interpolation? Mind showing some code or pseudocode so I can understand?

My main goal is to either change the above linked example to have a period of my choosing, or write it again from scratch after understanding how period fits in, preferably with a dynamic period.

Thanks for the help!

Yeah, “Noise” in graphics is a very confusing use of the term! It’s really randomized textures, but I guess noise is quicker to say. It produces some impressive results though.

I thought the first array was just random numbers, so how does it wrap around?

An array is a list of numbers, each number has a index that points to it for example index 0 points to the first number in the array and index n points to nth number.

If you are going through the array one number at a time with a pointer say called ‘p’ then you can wrap round by saying

number = myArray[p]; // get a number
// do stuff with number
p++; // move to next number
if(p>= arrayLength) p=0; // this wraps round the array

The second smoothed value array I don’t quite understand.

It is to place the results of your smoothing operation into. You can’t use the original array because you need those numbers intact for the next smoothing operation. Something like this:-

mySmoothArray[p] = ( myArray[p-1] + myArray[p] + myArray[p+1] ) / 3;

You can but weighting factors on any of those three parameters as well by simply multiplying them by a number.
Note you will have to watch the value of p to make sure p-1 and p+1 do not go outside the array bounds. So you need a bit of code to test this, something like:-

if(p>0) {
mySmoothArray[p] = ( myArray[p-1] + myArray[p] + myArray[p+1] ) / 3;
}
else {
mySmoothArray[p] = ( myArray[arrayLength-1] + myArray[p] + myArray[p+1] ) / 3;
}