Skip to content

BitCrusher

Lo-fi effect that reduces bit depth and sample rate to create digital distortion and vintage digital audio artifacts.

Props

PropTypeDefaultDescription
inputModStreamRefRequiredReference to input audio signal
outputModStreamRefRequiredReference to output audio signal
labelstring'bitcrusher'Label for metadata
bitDepthnumber8Bit depth reduction (1-16) (controlled or initial value)
onBitDepthChange(value: number) => void-Callback when bitDepth changes
sampleReductionnumber1Sample rate reduction factor (controlled or initial value)
onSampleReductionChange(value: number) => void-Callback when sampleReduction changes
childrenfunction-Render prop function

Render Props

When using the children render prop, the following controls are provided:

PropertyTypeDescription
bitDepthnumberCurrent bit depth
setBitDepth(value: number) => voidUpdate the bit depth
sampleReductionnumberCurrent sample reduction factor
setSampleReduction(value: number) => voidUpdate the sample reduction
isActivebooleanWhether the processor is active

Usage

Basic Usage

tsx
import { BitCrusher } from '@mode-7/mod';

function MyComponent() {
  const inputRef = useRef<ModStreamRef>(null);
  const outputRef = useRef<ModStreamRef>(null);

  return (
    <BitCrusher
      input={inputRef}
      output={outputRef}
      bitDepth={8}
      sampleReduction={1}
    />
  );
}

With Render Props

tsx
import { BitCrusher } from '@mode-7/mod';

function MyComponent() {
  const inputRef = useRef<ModStreamRef>(null);
  const outputRef = useRef<ModStreamRef>(null);

  return (
    <BitCrusher input={inputRef} output={outputRef}>
      {({ bitDepth, setBitDepth, sampleReduction, setSampleReduction }) => (
        <div>
          <label>
            Bit Depth: {bitDepth}
            <input
              type="range"
              min="1"
              max="16"
              step="1"
              value={bitDepth}
              onChange={(e) => setBitDepth(parseInt(e.target.value))}
            />
          </label>
          <label>
            Sample Reduction: {sampleReduction}x
            <input
              type="range"
              min="1"
              max="50"
              step="1"
              value={sampleReduction}
              onChange={(e) => setSampleReduction(parseInt(e.target.value))}
            />
          </label>
        </div>
      )}
    </BitCrusher>
  );
}

Controlled Props

tsx
import { BitCrusher } from '@mode-7/mod';
import { useState } from 'react';

function MyComponent() {
  const inputRef = useRef<ModStreamRef>(null);
  const outputRef = useRef<ModStreamRef>(null);
  const [bitDepth, setBitDepth] = useState(8);
  const [sampleReduction, setSampleReduction] = useState(1);

  return (
    <div>
      <BitCrusher
        input={inputRef}
        output={outputRef}
        bitDepth={bitDepth}
        onBitDepthChange={setBitDepth}
        sampleReduction={sampleReduction}
        onSampleReductionChange={setSampleReduction}
      />
      <button onClick={() => setBitDepth(4)}>4-bit (Very Lo-Fi)</button>
      <button onClick={() => setBitDepth(8)}>8-bit (Classic)</button>
      <button onClick={() => setBitDepth(12)}>12-bit (Subtle)</button>
      <button onClick={() => setSampleReduction(10)}>Heavy Aliasing</button>
    </div>
  );
}

Imperative Refs

tsx
import { BitCrusher } from '@mode-7/mod';
import { useRef } from 'react';

function MyComponent() {
  const inputRef = useRef<ModStreamRef>(null);
  const outputRef = useRef<ModStreamRef>(null);
  const bitCrusherRef = useRef(null);

  const logState = () => {
    if (bitCrusherRef.current) {
      const state = bitCrusherRef.current.getState();
      console.log('BitCrusher state:', state);
    }
  };

  return (
    <div>
      <BitCrusher
        ref={bitCrusherRef}
        input={inputRef}
        output={outputRef}
      />
      <button onClick={logState}>Log State</button>
    </div>
  );
}

Note: The imperative handle provides read-only access via getState(). To control the component programmatically, use the controlled props pattern shown above.

Important Notes

  • Lower bit depths create more distortion and quantization noise
  • Bit depth of 1 produces extreme digital distortion
  • Bit depth of 8 resembles vintage samplers and video game audio
  • Sample reduction creates aliasing artifacts
  • Higher sample reduction values create more dramatic downsampling effects
  • Combine low bit depth and high sample reduction for extreme lo-fi effects
  • Use subtle settings (12-16 bit, low sample reduction) for vintage warmth

Released under the MIT License.