Skip to content

ToneGenerator

The ToneGenerator component creates an oscillator that generates tones at a specific frequency. It supports multiple waveforms and can be modulated by CV signals.

Props

PropTypeDefaultDescription
outputModStreamRefRequiredReference to output the generated audio signal
labelstring'tone-generator'Label for the component in metadata
frequencynumber440Frequency in Hz (controlled or initial value)
onFrequencyChange(frequency: number) => void-Callback when frequency changes
gainnumber0.3Gain level 0-1 (controlled or initial value)
onGainChange(gain: number) => void-Callback when gain changes
waveformOscillatorType'square'Waveform type (controlled or initial value): 'sine', 'square', 'sawtooth', or 'triangle'
onWaveformChange(waveform: OscillatorType) => void-Callback when waveform changes
cvModStreamRef-Optional CV input for frequency modulation
cvAmountnumber100Amount of CV modulation to apply to frequency
childrenfunction-Render prop function receiving control props

Render Props

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

PropertyTypeDescription
frequencynumberCurrent frequency in Hz
setFrequency(value: number) => voidUpdate the frequency
gainnumberCurrent gain level (0-1)
setGain(value: number) => voidUpdate the gain level
waveformOscillatorTypeCurrent waveform type
setWaveform(type: OscillatorType) => voidUpdate the waveform type
isActivebooleanWhether the oscillator is running

Usage

Basic Usage

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

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

  return (
    <ToneGenerator
      output={toneOut}
      frequency={440}
      waveform="sine"
      gain={0.5}
    />
  );
}

With Render Props (UI Controls)

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

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

  return (
    <ToneGenerator output={toneOut}>
      {({ frequency, setFrequency, waveform, setWaveform, gain, setGain }) => (
        <div>
          <div>
            <label>Frequency: {frequency}Hz</label>
            <input
              type="range"
              min="20"
              max="2000"
              value={frequency}
              onChange={(e) => setFrequency(Number(e.target.value))}
            />
          </div>
          <div>
            <label>Waveform:</label>
            <select value={waveform} onChange={(e) => setWaveform(e.target.value as any)}>
              <option value="sine">Sine</option>
              <option value="square">Square</option>
              <option value="sawtooth">Sawtooth</option>
              <option value="triangle">Triangle</option>
            </select>
          </div>
          <div>
            <label>Gain: {gain.toFixed(2)}</label>
            <input
              type="range"
              min="0"
              max="1"
              step="0.01"
              value={gain}
              onChange={(e) => setGain(Number(e.target.value))}
            />
          </div>
        </div>
      )}
    </ToneGenerator>
  );
}

With LFO Modulation

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

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

  return (
    <>
      <LFO output={lfoOut} />
      <ToneGenerator
        output={toneOut}
        frequency={440}
        cv={lfoOut}
        cvAmount={200}  // Modulate frequency by ±200Hz
      />
    </>
  );
}

Controlled Props

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

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

function App() {
  const toneOut = useRef(null);
  const [frequency, setFrequency] = useState(440);
  const [gain, setGain] = useState(0.5);
  const [waveform, setWaveform] = useState<OscillatorType>('sine');

  return (
    <>
      <ToneGenerator
        output={toneOut}
        frequency={frequency}
        onFrequencyChange={setFrequency}
        gain={gain}
        onGainChange={setGain}
        waveform={waveform}
        onWaveformChange={setWaveform}
      />

      <div>
        <label>Frequency: {frequency}Hz</label>
        <input
          type="range"
          min="20"
          max="2000"
          value={frequency}
          onChange={(e) => setFrequency(Number(e.target.value))}
        />
      </div>

      <div>
        <label>Waveform:</label>
        <select value={waveform} onChange={(e) => setWaveform(e.target.value as OscillatorType)}>
          <option value="sine">Sine</option>
          <option value="square">Square</option>
          <option value="sawtooth">Sawtooth</option>
          <option value="triangle">Triangle</option>
        </select>
      </div>

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

Imperative Refs

For programmatic control, you can use refs to access the component's state:

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

function App() {
  const toneRef = useRef<ToneGeneratorHandle>(null);
  const toneOut = useRef(null);

  useEffect(() => {
    // Access current state
    if (toneRef.current) {
      const state = toneRef.current.getState();
      console.log('Current frequency:', state.frequency);
      console.log('Current gain:', state.gain);
      console.log('Current waveform:', state.waveform);
    }
  }, []);

  return (
    <>
      <ToneGenerator ref={toneRef} output={toneOut} />
      <Monitor input={toneOut} />
    </>
  );
}

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

Important Notes

  • The oscillator starts immediately when the component mounts
  • The oscillator is stopped and cleaned up when the component unmounts
  • CV modulation adds to the base frequency value
  • All waveform types are standard Web Audio oscillator waveforms
  • LFO - Low Frequency Oscillator for modulation
  • Filter - Process the tone with filtering
  • Monitor - Output the tone to speakers

Released under the MIT License.