Real bit crushing of samples?

Looking for a bit crush effect but not just something slapped on, but an actual realtime manipulation of the bit rate. Not rate as in pitch, but real bit rate. The sample hold trick can be nice. But Im looking for something really raw
Thanks

1 Like

Sample-and-hold is sample rate decimation, which is not the same as bit depth reduction. (You can have 24 bit audio at a low sample rate.)

To reduce the apparent bit depth .round the signal – .round(2 ^ bits.neg) I think.

You can’t physically change the sample format for part of the scsynth node tree. You can only simulate a lower bit depth.

hjh

1 Like

See also Decimator.ar

https://doc.sccode.org/Classes/Decimator.html

1 Like

I see, The Assimil8or sampler does actually change the bit rate, But it costs a thousand dollars… Oh well. No problem. I loaded up the old Player Pro tracker in sheepshaver and that has a nice crunchy sound to the samples as you lower the freq rate. Don’t know what’s happening there. That got me to make this thread. I guess I’ll just sample things.

What do you mean by “change the bit rate”?

Digital audio properties are sampling rate, and bit depth (aka sample width). “Bit rate” isn’t a standard property of PCM audio.

Bit rate could refer to bits per second = bits per sample, times samples per second. But bit crushers generally don’t work in terms of bits per second – usually they have a sample rate reduction control, and a bit depth reduction control.

In the integer sample domain, a 16 bit sample quantizes the true value to 32767 steps above 0, and 32768 steps below 0. An 8 bit sample quantizes to 127 steps above and 128 below 0. If you .round the signal to match 127 steps, e.g. sig.round(1/128) then the signal numerically matches 8-bit quantization – so it is bit-crushed. There is no meaningful distinction between an 8-bit signal and a 32-bit float signal that has been quantized (rounded) to 8 bits’ worth of resolution. Similarly, if a signal has been sampled-held to 3000 samples per second, then it is numerically identical to a 3000 samples/sec signal even if it’s calculating at 48000 kHz. It will still alias above 1500 Hz. Any other crunchiness in other devices must be coming from some additional DSP being done.

hjh

2 Likes

Here’s an example of my synthesis course. I love it because it shows how the popular bitcrush / resample combo can basically be written in 2 lines of SC code !
For the exponent you probably want (1 - bits) as the positive + negative range has to be regarded (e.g.: 3 bits, grid of 8 points for the level, round to 0.25 = 2 ** (1 - 3))

(
a = Bus.audio(s, 2);

SynthDef(\bitCrusher, { |out = 0, in, wet = 1, amp = 0.1, bits = 32,
	resampleRate = 22050, lag = 0, gate = 1|
	var sig, inSig = In.ar(in, 2);
	sig = inSig.round(2 ** (1 - bits)); // bit crushing
	sig = Latch.ar(sig, Impulse.ar(resampleRate)); // resampling
	// lagging smoothes
	sig = sig.lag(lag * 0.001);
	Out.ar(out, ((1 - wet) * inSig + (sig * wet)) * amp * EnvGate(gate: gate));
}).add;
)

// start before
y = Synth(\bitCrusher, [in: a, resampleRate: 24000]); // start with half nyquist on your system

// start src second, added to head 
x = { Out.ar(a, SinOsc.ar(200 * [1, 1.01])) }.play;


// audible bit crushing
y.set(\bits, 3)

// resampling
y.set(\resampleRate, 2001)

y.set(\resampleRate, 399)

// lagging, more analogue sound
y.set(\lag, 0.5)

y.set(\wet, 0.3)

y.release(3)

x.free;

This is only a starting point for endless distortion variations. E.g., a student reminded me of softround which you can also do server-side:


(
a = Bus.audio(s, 2);

SynthDef(\bitCrusher_2, { |out = 0, bits = 3, margin = 0.05, strength = 1.0,
	resampleRate = 22050, lag = 0, mix = 1, amp = 0.1|

	var sig, inSig = In.ar(a, 2), round, diff, resolution;
	resolution = 2 ** (1 - bits);
	round = inSig.round(resolution); // bit crushing
	// compare lang method 'softround'
	diff = round - inSig;
	sig = Select.ar(abs(diff) > margin, [inSig, inSig + (strength * diff) ]);

	sig = Latch.ar(sig, Impulse.ar(resampleRate)); 
	sig = sig.lag(lag * 0.001);

	ReplaceOut.ar(out, ((1 - mix) * inSig + (sig * mix)) * amp);
}, metadata: (
	specs: (
		mix: [0, 1, \lin, 0, 1],
		amp: [0, 0.3, \lin, 0, 0.3],
		bits: [1, 8, \lin, 1, 3],
		margin: [0, 1, 3, 0, 0.05],
		strength: [0, 1, \lin, 0, 1],
		resampleRate: [20, 22050, \exp, 0, 22050],
		lag: [0, 50, 3, 0, 0]
	)
)
).add;
)

// start GUI

SynthDescLib.global[\bitCrusher_2].makeGui

// start src

x = { Out.ar(a, SinOsc.ar(200 * [1, 1.01])) }.play

x.free;

Another nice distortion effect (also interesting in combo with above) is simply multiplying with one or more Gate UGens, a rough kind of granulation so to speak.

6 Likes

There has been a lot of incorrect terminology with the Asimil8or over the years. People have been posting on forums all sorts of things. But officially it is Bit Depth control. I had to do some googling cause I know Ive read the terms mixed up . Also, Real time CV control of aliasing.

But I should clarify. It is Bit Depth.

1 Like

So nice. Thank you very much

Before dropping the topic completely, it’s worth reposting this video about digital audio: Xiph.Org Video Presentations: Digital Show & Tell – it neatly deals with a number of misconceptions about sample rate and bit depth.

I did say one thing that was not correct. Sample-and-hold at, say, 3000 Hz, if the server’s sample rate is 48000, will make a stair-stepped signal (“zero-order hold”) and, when this is converted to analog with a Nyquist frequency of 24 kHz, this is not the same as a signal sampled at 3000 Hz, converted to analog with a Nyquist frequency of 1500 Hz. The latter will alias but the result will be band-limited to 0-1500 Hz (i.e. low-pass filtered), where the former will include high frequency artifacts from the stairsteps up to 24 kHz. But these high frequency artifacts are part of the familiar sound of bit crushing plugins! This is what you want – so physically changing the sample rate isn’t what’s needed for this effect.

Brilliant example: Tabla Beat Science, “Audiomaze”

hjh

4 Likes

Ok, Tabla Beat Science, that’s amazing. Is that supercollider? really , really good

Isn’t the band limiting a filter , that can be removed? I own an akai s612, and it can do very low sample rates. I had the hideaway mod done which switches off the aliasing filter (if I want) Or is the Nyquist frequency of 1500 Hz acting as a filter by default of its state? It’s all so confusing. , Im not a numbers guy

No. If the sample rate is 3000 Hz, then the Nyquist frequency is 1500 Hz and the sampled signal itself contains information only up to 1500 Hz. It isn’t that the signal contains stuff that a filter removes – literally, there is no information above Nyquist. If the original analog signal had information above Nyquist when being low-rate sampled, then higher frequencies will alias down back into the range 0 Hz - 1500 Hz. There’s a filter before the sampling process to prevent this. But this is recording, not playback.

It may be a bit confusing because one technique for digital to analog conversion is to raise the sample rate (often by the aforementioned zero-order hold) and then filter away the artifacts (digitally, then in analog). But here, the oversampling operation introduces distortion that wasn’t part of the original sampled signal, and the filter smooths that away. (Technically the resulting analog signal is a very near approximation, good enough for hearing.)

Seriously though, watch the xiph video. It’s made for “not numbers people” – at the end of it, you’ll understand some things that are now mysterious.

hjh

2 Likes

I think I watched that video 6 times over the past 3 years:) Such a great video.