Attached is a file with the three different formulas I gave last time for two-bit quantization, just for illustration -- any of these could work as a general bit-crusher with a little extra effort. Number one has a variant you can toggle on or off. Also notice how positive max-amp is an exception in numbers one and three -- it can be clipped out though.
Matt On Thu, Apr 29, 2010 at 9:56 PM, Matt Barber <[email protected]> wrote: >>> Reduced bit depth (which is what I think 'bit-crushing' means) can be >>> achieved by dividing the signal by x, pass it through something like >>> [int~], multiply it by x again. An [int~] can be implemented by using >>> [wrap~] and [-~], which are both vanilla. >> >> It is also worth considering adding a DC offset. Your [wrap~] solution >> implements a floor-function, that is, rounding downwards. You can make it >> round to closest, by adding x/2 before rounding downwards. >> >> [expr int($v1)] is rounding zerowards (thus output zero corresponds to a >> twice bigger input range as any other input). Thus it will behave in a >> weird unequal way. >> >> When the volume gets low, the _effective_ bits-per-sample gets very low, >> because the relative precision of integers is proportional to amplitude >> (which is not the case with floats). Therefore, even with 16-bit audio, if >> your amplitude is 0.0001 times the max, it will feel as if it were 3-bit >> audio. In such circumstances, the differences between the possible >> roundings will become quite audible. > > > Bit-depth transitions are really complicated things, especially when > going from normalized float to int (and among different utitlities > which do this, e.g. libsndfile or ecasound, I've found several > different standards). The biggest problem is what to do with the > asymmetry about zero with int representations -- there are more > negative numbers than positive in a two's complement int system. > > Here are three formulas I've used for noise-shaping dither in csound > (the first one is more compatible with the bit-depth transitions that > occur when csound writes a file). > > let X = the input signal and N = target bits: > > 1) Y=(floor([2^(N-1)]*X)+0.5)/[2^(N-1)] > 2) Y=floor([2^(N-1)]*X+0.5)/[2^(N-1)] > 3) Y=floor([2^(N-1)]*X)/[2^(N-1)] > > The only difference is whether the 0.5 is added, and whether it's > added before or after the floor function. > > So let's say you're moving from floats (-1 to +1) to 8-bits: > > In the first, one multiplies the signal by 2^7, getting a signal which > varies from -128 to +128 (floats). Flooring that will result in ints > in the same range (+128 after the floor will be a relative rarity in > real signals, though, so the effective range is -128 to 127). Adding > 0.5 to all of that gives a range of -127.5 to 127.5 (with the very > rarely encountered 128.5). Then division by 128 gives a signal which > varies between two values equally spaced from 0, but a constant 0 in > will result in a DC-offset out (it's a mid-rise function with 256 > possible values). > > In the second, one multiplies the signal by 2^7, getting a signal > which varies from -128 to +128 (floats). Adding 0.5 to this will > result in a signal that varies between -127.5 to +128.5, and flooring > this gives -128 to +128 (ints). This time, +128 will not be as rare. > This also is really just a rounding function, with x.5 values rounded > up. It's a mid-tread function, so zeros in will result in zeros out. > At first glance it may seem as though this has one more than 2^8 > values (128 negative values, 128 positive values, and 0 = 257 total > possible values). However, if one were to graph the rounding > function, one would find that anything that started out between -127.5 > and +127.5 will be rounded to -127 to +127 (255 values), while > anything lower than -127.5 will round to -128, and anything higher > than 127.5 will round to +128 -- the extremes of the staircase > function have half-quantization-step mappings, so the total effect is > still 8-bit. This one has the advantage that both zero in and maxamp > (positive or negative) give "correct" output values as well, but the > disadvantage that one of the quantized steps is divided between the > top and the bottom of the total range. Also, its graph is a > reflection of that of the first function about a diagonal. > > In the third, one starts with the same math as the first, up to the > floor function, which gives an effective range of -128 to 127. Then > one simply divides by the original scalar, which just gives the > mid-tread version of the function from the first formula (the first > formula minus half the quantization step), with zeros-in-zeros out but > one extra negative value than positive. > > > Maybe sometime later I could post some pictures for two-bit audio. > I'm sure there are plenty on the web. There's also the question of > whether, even for a bit-crushing effect, one would add dither. > > > Matt >
bitcrushers.pd
Description: Binary data
_______________________________________________ [email protected] mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
