I’m trying to understand the code of Grids (especially the drum-pattern-generator).
line 94 in pattern_generator.cc:
return U8Mix(U8Mix(a, b, x << 2), U8Mix(c, d, x << 2), y << 2);

First up: U8Mix
As I understand it U8Mix returns a weighted sum:
the input numbers are all 8bit unsigned
the computation inside U8Mix is b*x + a*(255-x)
this sum is (to my understanding) 16bit
but the return of U8Mix is only 8bit unsigned
could someone explain? or point out where my reasoning is false?
preferrably with an example of meaningfull / relevant numbers

Second: the bitshift in ReadDrumMap: U8Mix(a, b, x << 2)
Why the bitshift?

U8Mix returns x * b + (255 - x) * a >> 8 (it ‘crossfades’ between a and b where x sets the position of the crossfader, with a slight loss of 255/256.0). It internally calculates the 16-bit result as you’ve noticed but drops the lowest byte.

The drum map is 5 x 5 - which means that that each axis is divided into 4 zones. If a coordinate (say x) has a range of 8-bit, x >> 6 will give you the zone index ; and x << 2 will give you the relative position within the zone.

I’ve need trying to prototype a variation of Grids using JavaScript (I know; not ideal, but it’s the language I know best).

Your explanation above has been really useful, pichenettes. I’ve not really used bit-shift operators before (no formal background in computer science here, but been writing code for years), so I’ve learnt a lot.

@pichenettes Am I right in thinking that your U8Mix function never quite reaches ‘b’ value? I did a simple JS test, using the function to crossfade between values of 0 and 255, and the output only reached 254, with x at 255. Is this expected behaviour?

I was hoping to use the same mix function to fade between values in the 0-11 range, but again, the output of the mix function only gets to 10.

Is there some variation of the mix function that will return exactly the target value at x=255?

I’d normally do this using floating-point numbers, but I’m hoping eventually to have this code running on an ATmega328, so I thought it might be best to use an integer-only version.

Happy New Year, incidentally! May 2016 bring you health, happiness, prosperity (and many brilliant ideas which we all look forward to seeing transformed into Euro goodness).

> Am I right in thinking that your U8Mix function never quite reaches ‘b’ value?

Yes. That’s the expected behaviour because reaching b would require the crossfade parameter to be at 256 (that is to say 1.0 using an 8-bit fractional part).

If you want 255 to mean “100% b, 0% a”, you need to divide by 255 instead of shifting by 8, and what took 1 CPU cycle will suddenly take 40+

Thanks for getting back to me. Thinking about it, it’s not necessarily a problem, since when we’re inside the next cell, and x=0, b will become a, and we’ll get the original value.

I may make a lookup table, to create little plateaus in x around each node.