First time here? Check out the FAQ!
x

Why doesn't the bit crusher crush to 1-bit?

0 votes
539 views

In the Kata we've been playing with bit crushing recently using the technique of dividing the audio signal way down then multiplying it back up again to lose resolution, relying on the paca(rana) using 32-bit values for the audio signal. 

Using a Level to divide down with this expression:

And another Level (with Gain enabled) to mulitply back up again:

This works but it won't reduce to 1 bit, the lowest it can go is 2 bits. At 1-bit it just goes silent. And at two-bits it's asymetric with more signal below zero. 

Why is that? How would you make this sound work at 1-bit?

 

 

 

asked Jun 17, 2019 in Using Kyma by alan-jackson (Virtuoso) (15,840 points)
I was approaching it this way;

norm16bitMax:   ( 15 twoExp - 1 ) / ( 31 twoExp -1)
norm16bitMin: ( ( 15 twoExp  ) / ( 31 twoExp ) ) negated

would that be correct?

1 Answer

+2 votes
 
Best answer

If you change the first set of scales to

(2 ** (31 - !Bits)) inverse * 0.5

and the second set of scales to

(2 ** (31 - !Bits)) * 2

your example will work. (You need to do it in two steps to avoid underflow to zero when taking the inverse of 2**31.)

The asymmetry in the bit crushed 2-bit output comes in because the two's complement numbers used in computers are asymmetric: there is one more negative number than positive numbers. (You can see this in the chart of 3-bit signed integers on Wikipedia, there is a -4, but not a +4. Also, see the discussion about "Most negative number" in that same article.) When you crush down to 2-bits and then scale back up to full value, there are 4 possible results: 0.5, 0.0, -0.5, -1.0

answered Jun 18, 2019 by ssc (Savant) (128,200 points)
selected Jun 28, 2019 by alan-jackson
That's great thanks!

As you point out there's 1 more negative number in two's complement (three's a crowd) so the signal is negatively biased after bit reduction. For 1 bit the signal only has values of -1 and 0.

To re-centre the signal around zero I added a ScaleAndOffset on the end with:

    (2 ** !Bits) inverse

in the offset fields.
...