maximecb / noisecraft

Browser-based visual programming language and platform for sound synthesis.
https://noisecraft.app
GNU General Public License v2.0
1.05k stars 61 forks source link

`BitCrush` distortion node #81

Closed maximecb closed 1 year ago

maximecb commented 2 years ago

It seems like it could be fairly easy to implement a basic bit crush style distortion node, and that would give us a new type of distortion effect to play with. This is a node that downsamples the input audio, e.g. 8 bits per sample at an 11KHz sample rate. Internally, NoiseCraft operates with 32-bit samples at a 44100Hz sample rate.

The BitCrush node could have two drop-down menus, one for the bit depth and one for the sample rate. We could select between bit depths like 32 (no-op), 16, 12, 10, 8, 6, 4, 2.

For the sample rate, we could have different fractions of the full 44100 sample rate, or go with a scheme where we produce one output sample for every N input samples, which would give us more sample rates. I want to keep the implementation simple so I'd probably go for hard sampling, no averaging between samples or smoothing.

1:1 => 44100Hz (no-op) 2:1 downsampling => 22050Hz 3:1 => 14700Hz 4:1 => 11050Hz 5:1 => 8820Hz 6:1 => 7350Hz ... 12:1 => 3675Hz

Reducing the sample rate like this should be pretty trivial, we can just keep a modulo counter that goes from 1 to N, and sample the input every time the counter is at 0.

To reduce the bit depth, I'm thinking an easy solution would be to assume that the input is within the [-1, 1] range, and map that onto [0, 65535], that is, between 9 and INT16_MAX, and then take the Math.floor() of that value. That gives us a 16-bit integer. Then we can simply drop the lower bits to get any bit depth that we want between 0 and 16 bits. Technically we should be able to downsample to odd numbers like 3-bits or 5-bits if we want to, which I guess we might as well allow.

maximecb commented 2 years ago

Added some notes as to how I think this can be implemented.

greg7gkb commented 2 years ago

So the 'bit crush' style effect totally makes sense... that would basically be a simulation of lower quantization levels for the outputs, using the kind of math you suggested above.

However the reduction in sampling rate doesn't make as much sense to me. Wouldn't this be the same effect as just band-limiting the signal down to the new 'sample rate'? In fact, the references I found on reducing sample rate suggest that you want to low-pass filter the input signal before downsampling anyway to reduce aliasing artifacts: https://ccrma.stanford.edu/~jos/sasp/Filtering_Downsampling.html

In short, I'm not sure that changing the sample rate, internally, would produce a useful effect beyond what we already have via filters.

(I believe the typical use of reducing sample rate is to also reduce the amount of bandwidth required to transmit the signal, for example in low-bandwidth VoIP apps or other streaming-based media services.)

maximecb commented 2 years ago

Hi Greg!

I'm just going based on the existing BitCrush plugins I've seen. They typically have options for both bit depth and sample rate. I think it could produce a useful effect to reduce the sample rate because it's very unlikely IMO to sound exactly the same as the existing filter. Low pass filters all have unique roll-off slopes and resonance characteristics.

BitCrush is meant to be a low-fi effect, a kind of distortion, so maybe we could get away without filtering first, we could just try it and see what it sounds like? For downsampling I'd probably go for either "hard" downsampling where we just take one input sample every N, or maybe a "softer" version where we take the average of the N previous samples. Could also have a checkbox to switch between modes.

https://steinberg.help/cubase_plugin_reference/v9/en/_shared_picts/picts/plug_ref/bitcrusher.png

https://thehomerecordings.com/wp-content/uploads/2020/01/tb_timemachine.jpg

http://kilohearts.com/img/products/bitcrush_twitter.jpg