Skip to content

Reverb

The Reverb component adds spatial depth and ambience to audio signals using convolution-based reverb. It simulates the sound of different acoustic spaces.

Props

PropTypeDefaultDescription
inputModStreamRefRequiredAudio signal to process
outputModStreamRefRequiredReverb output
labelstring'reverb'Label for the component in metadata
wetnumber0.3Wet/dry mix 0-1 (controlled or initial value)
onWetChange(wet: number) => void-Callback when wet/dry mix changes
durationnumber2.0Reverb duration in seconds (controlled or initial value)
onDurationChange(duration: number) => void-Callback when duration changes
decaynumber2.0Decay rate (controlled or initial value)
onDecayChange(decay: number) => void-Callback when decay changes
childrenfunction-Render prop function receiving control props
wetnumber0.3Wet/dry mix 0-1 (controlled or initial value)
onWetChange(wet: number) => void-Callback when wet/dry mix changes
durationnumber2.0Reverb duration in seconds (controlled or initial value)
onDurationChange(duration: number) => void-Callback when duration changes
decaynumber2.0Decay rate (controlled or initial value)
onDecayChange(decay: number) => void-Callback when decay changes

Render Props

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

PropertyTypeDescription
wetnumberWet/dry mix (0-1)
setWet(value: number) => voidUpdate the wet/dry mix
durationnumberReverb duration in seconds
setDuration(value: number) => voidUpdate the duration
decaynumberDecay rate (1-10)
setDecay(value: number) => voidUpdate the decay rate
isActivebooleanWhether the reverb is active

Usage

Basic Usage

tsx
import { ToneGenerator, Reverb, Monitor } from '@mode-7/mod';
import { useRef } from 'react';

function App() {
  const toneOut = useRef(null);
  const reverbOut = useRef(null);

  return (
    <>
      <ToneGenerator output={toneOut} />
      <Reverb input={toneOut} output={reverbOut} />
      <Monitor input={reverbOut} />
    </>
  );
}

With UI Controls

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

function App() {
  const inputRef = useRef(null);
  const reverbOut = useRef(null);

  return (
    <Reverb input={inputRef} output={reverbOut}>
      {({ wet, setWet, duration, setDuration, decay, setDecay }) => (
        <div>
          <div>
            <label>Mix: {(wet * 100).toFixed(0)}%</label>
            <input
              type="range"
              min="0"
              max="1"
              step="0.01"
              value={wet}
              onChange={(e) => setWet(Number(e.target.value))}
            />
          </div>

          <div>
            <label>Duration: {duration.toFixed(1)}s</label>
            <input
              type="range"
              min="0.1"
              max="5"
              step="0.1"
              value={duration}
              onChange={(e) => setDuration(Number(e.target.value))}
            />
          </div>

          <div>
            <label>Decay: {decay.toFixed(1)}</label>
            <input
              type="range"
              min="1"
              max="10"
              step="0.1"
              value={decay}
              onChange={(e) => setDecay(Number(e.target.value))}
            />
          </div>
        </div>
      )}
    </Reverb>
  );
}

Reverb Presets

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

function App() {
  const inputRef = useRef(null);
  const reverbOut = useRef(null);

  const presets = {
    smallRoom: { duration: 0.5, decay: 2, wet: 0.2 },
    mediumRoom: { duration: 1.0, decay: 2.5, wet: 0.3 },
    largeHall: { duration: 2.5, decay: 3, wet: 0.4 },
    cathedral: { duration: 4.0, decay: 4, wet: 0.5 },
    plate: { duration: 1.5, decay: 1.5, wet: 0.3 },
  };

  return (
    <Reverb input={inputRef} output={reverbOut}>
      {({ setWet, setDuration, setDecay }) => (
        <div>
          <h3>Presets:</h3>
          {Object.entries(presets).map(([name, settings]) => (
            <button
              key={name}
              onClick={() => {
                setDuration(settings.duration);
                setDecay(settings.decay);
                setWet(settings.wet);
              }}
            >
              {name.charAt(0).toUpperCase() + name.slice(1)}
            </button>
          ))}
        </div>
      )}
    </Reverb>
  );
}

Vocal Reverb Chain

tsx
import { Microphone, Filter, Compressor, Reverb, Monitor } from '@mode-7/mod';
import { useRef } from 'react';

function App() {
  const micOut = useRef(null);
  const filterOut = useRef(null);
  const compOut = useRef(null);
  const reverbOut = useRef(null);

  return (
    <>
      <Microphone output={micOut} />

      {/* High-pass filter to remove rumble */}
      <Filter
        input={micOut}
        output={filterOut}
        type="highpass"
        frequency={80}
      />

      {/* Compression for consistent levels */}
      <Compressor input={filterOut} output={compOut} />

      {/* Reverb for space */}
      <Reverb input={compOut} output={reverbOut}>
        {({ setWet, setDuration, setDecay }) => {
          React.useEffect(() => {
            setWet(0.3);
            setDuration(1.5);
            setDecay(2.5);
          }, []);
          return null;
        }}
      </Reverb>

      <Monitor input={reverbOut} />
    </>
  );
}

Controlled Props

You can control the Reverb from external state using controlled props:

tsx
import { ToneGenerator, Reverb, Monitor } from '@mode-7/mod';
import { useState, useRef } from 'react';

function App() {
  const toneOut = useRef(null);
  const reverbOut = useRef(null);
  const [wet, setWet] = useState(0.3);
  const [duration, setDuration] = useState(1.5);
  const [decay, setDecay] = useState(2.5);

  return (
    <>
      <ToneGenerator output={toneOut} />
      <Reverb
        input={toneOut}
        output={reverbOut}
        wet={wet}
        onWetChange={setWet}
        duration={duration}
        onDurationChange={setDuration}
        decay={decay}
        onDecayChange={setDecay}
      />

      <div>
        <label>Mix: {(wet * 100).toFixed(0)}%</label>
        <input
          type="range"
          min="0"
          max="1"
          step="0.01"
          value={wet}
          onChange={(e) => setWet(Number(e.target.value))}
        />
      </div>

      <div>
        <label>Duration: {duration.toFixed(1)}s</label>
        <input
          type="range"
          min="0.1"
          max="5"
          step="0.1"
          value={duration}
          onChange={(e) => setDuration(Number(e.target.value))}
        />
      </div>

      <Monitor input={reverbOut} />
    </>
  );
}

Imperative Refs

For programmatic access to state, you can use refs:

tsx
import { Reverb, ReverbHandle, Monitor } from '@mode-7/mod';
import { useRef, useEffect } from 'react';

function App() {
  const reverbRef = useRef<ReverbHandle>(null);
  const inputRef = useRef(null);
  const outputRef = useRef(null);

  useEffect(() => {
    // Access current state
    if (reverbRef.current) {
      const state = reverbRef.current.getState();
      console.log('wet:', state.wet);
      console.log('duration:', state.duration);
      console.log('decay:', state.decay);
    }
  }, []);

  return (
    <>
      <SomeSource output={inputRef} />
      <Reverb
        ref={reverbRef}
        input={inputRef}
        output={outputRef}
      />
      <Monitor input={outputRef} />
    </>
  );
}

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

Important Notes

Duration

  • Controls the length of the reverb tail
  • Short (0.1-0.5s): Small rooms, tight spaces
  • Medium (0.5-2s): Normal rooms, studios
  • Long (2-5s): Large halls, cathedrals
  • Very long durations increase CPU usage

Decay

  • Controls how quickly the reverb fades out
  • Lower values (1-2): Natural, realistic decay
  • Medium values (2-4): Enhanced, musical decay
  • High values (4-10): Slow, ethereal decay
  • Higher decay values create denser reverb

Wet/Dry Mix

  • 0 = 100% dry (no reverb)
  • 0.2-0.3 = Subtle ambience
  • 0.4-0.6 = Noticeable space
  • 0.7-1.0 = Heavy, atmospheric reverb

Impulse Response

  • The reverb uses algorithmically generated impulse responses
  • Changes to duration or decay regenerate the impulse response
  • This may cause a brief audio glitch when changing parameters

Performance Considerations

  • Reverb is CPU-intensive due to convolution
  • Longer durations require more processing
  • Consider using a single reverb for multiple sources via a mixer

Creative Uses

Try extreme settings for creative effects:

  • Very short duration + high decay = metallic plate sound
  • Very long duration + low decay = infinite ambience
  • Adjust in real-time for special effects

Released under the MIT License.