API Reference

Synthesizer

class dexed.DexedSynth(sample_rate=44100.0)

Bases: object

DX7 synthesizer.

Example:

synth = DexedSynth(sample_rate=44100)

# From a Patch (DX7 sysex interface)
patch = Patch.load_bank("rom1a.syx")[0]
synth.load_patch(patch)
audio = synth.render(midi_note=60, velocity=100)

# From a Preset (ML interface)
from dexed import Preset
preset = Preset(algorithm=15, feedback=0.5)
synth.load_preset(preset)
audio = synth.render(midi_note=60)
Parameters:

sample_rate (float)

load_patch(patch)

Load a Patch into the synthesizer.

Return type:

None

Parameters:

patch (Patch)

load_preset(preset)

Load a Preset into the synthesizer.

Return type:

None

render(midi_note=60, velocity=100, note_duration=3.0, render_duration=4.0)

Render audio with current parameters.

Parameters:
  • midi_note (int) – MIDI note number 0-127 (default 60 = C4)

  • velocity (int) – Note velocity 0-127 (default 100)

  • note_duration (float) – How long the note is held in seconds (default 3.0)

  • render_duration (float) – Total audio duration in seconds (default 4.0)

Return type:

ndarray

Returns:

numpy array of shape [T] with audio samples (float32)

render_all_ops(midi_note=60, velocity=100, note_duration=3.0, render_duration=4.0)

Render individual operator outputs.

Returns:

channels 0-5 are operators 0-5, channel 6 is the final output.

Return type:

ndarray

Parameters:
property sample_rate: float

Get the sample rate in Hz.

property algorithm: int

Get the currently loaded DX7 algorithm (0-31).

property normalize_feedback: bool

When True, use consistent feedback scaling across all algorithms.

When False (default), algorithms 3, 5, and 31 have reduced feedback, matching original Dexed behavior.

Preset

class dexed.Preset(feedback=0.0, transpose=0.5, pitch_mod_sensitivity=0.0, lfo_speed=0.35353535353535354, lfo_delay=0.0, lfo_pitch_mod_depth=0.0, lfo_amp_mod_depth=0.0, osc_key_sync=1, lfo_sync=0, pitch_env_rates=<factory>, pitch_env_levels=<factory>, op_env_rates=<factory>, op_env_levels=<factory>, op_output_level=<factory>, op_frequency_coarse=<factory>, op_frequency_fine=<factory>, op_detune=<factory>, op_velocity_sensitivity=<factory>, op_amp_mod_sensitivity=<factory>, op_rate_scaling=<factory>, op_breakpoint=<factory>, op_left_depth=<factory>, op_right_depth=<factory>, algorithm=0, lfo_wave=4, op_frequency_mode=<factory>, op_left_curve=<factory>, op_right_curve=<factory>)

Bases: object

PyTree-compatible DX7 preset with all synth state.

All fields are JAX PyTree data leaves – changing any value never triggers JIT recompilation. This makes Preset ideal for use as the argument to jax.pure_callback.

algorithm is 0-indexed (0–31), matching the DX7 sysex byte.

Because there are no meta fields, all Presets share the same treedef:

_, treedef = jax.tree.flatten(Preset())  # works for any Preset

Flat vector to Preset inside JIT:

_, treedef = jax.tree.flatten(Preset())

@jax.jit
def make_preset(flat_params):  # flat_params is (145,)
    leaves = Preset.array_to_leaves(flat_params)
    return jax.tree.unflatten(treedef, leaves)

Bulk serialization:

arr = np.stack([p.to_array() for p in presets])  # (N, 145) float32
np.save('presets.npy', arr)
presets = [Preset.from_array(row) for row in np.load('presets.npy')]
Parameters:
feedback: float = 0.0
transpose: float = 0.5
pitch_mod_sensitivity: float = 0.0
lfo_speed: float = 0.35353535353535354
lfo_delay: float = 0.0
lfo_pitch_mod_depth: float = 0.0
lfo_amp_mod_depth: float = 0.0
osc_key_sync: int = 1
lfo_sync: int = 0
pitch_env_rates: ndarray
pitch_env_levels: ndarray
op_env_rates: ndarray
op_env_levels: ndarray
op_output_level: ndarray
op_frequency_coarse: ndarray
op_frequency_fine: ndarray
op_detune: ndarray
op_velocity_sensitivity: ndarray
op_amp_mod_sensitivity: ndarray
op_rate_scaling: ndarray
op_breakpoint: ndarray
op_left_depth: ndarray
op_right_depth: ndarray
algorithm: int = 0
lfo_wave: int = 4
op_frequency_mode: ndarray
op_left_curve: ndarray
op_right_curve: ndarray
SCALES: ClassVar[Dict[str, int]] = {'feedback': 7, 'lfo_amp_mod_depth': 99, 'lfo_delay': 99, 'lfo_pitch_mod_depth': 99, 'lfo_speed': 99, 'op_amp_mod_sensitivity': 3, 'op_breakpoint': 99, 'op_detune': 14, 'op_env_levels': 99, 'op_env_rates': 99, 'op_frequency_coarse': 31, 'op_frequency_fine': 99, 'op_left_depth': 99, 'op_output_level': 99, 'op_rate_scaling': 7, 'op_right_depth': 99, 'op_velocity_sensitivity': 7, 'pitch_env_levels': 99, 'pitch_env_rates': 99, 'pitch_mod_sensitivity': 7, 'transpose': 48}
DATA_FIELDS: ClassVar[List[str]] = ['feedback', 'transpose', 'pitch_mod_sensitivity', 'lfo_speed', 'lfo_delay', 'lfo_pitch_mod_depth', 'lfo_amp_mod_depth', 'pitch_env_rates', 'pitch_env_levels', 'op_env_rates', 'op_env_levels', 'op_output_level', 'op_frequency_coarse', 'op_frequency_fine', 'op_detune', 'op_velocity_sensitivity', 'op_amp_mod_sensitivity', 'op_rate_scaling', 'op_breakpoint', 'op_left_depth', 'op_right_depth', 'osc_key_sync', 'lfo_sync', 'algorithm', 'lfo_wave', 'op_frequency_mode', 'op_left_curve', 'op_right_curve']
META_FIELDS: ClassVar[List[str]] = []
GLOBAL_CONTINUOUS_SIZE: ClassVar[int] = 15
GLOBAL_INT_MAXES: ClassVar[List[int]] = [1, 1, 31, 5]
OP_CONTINUOUS_SIZE: ClassVar[int] = 18
OP_INT_MAXES: ClassVar[List[int]] = [1, 3, 3]
to_array()

Pack all parameters into a (145,) float32 array.

Order matches DATA_FIELDS. Integer fields are cast to float32.

Return type:

ndarray

classmethod from_array(arr)

Unpack a (145,) float32 array into a Preset.

Integer fields are recovered by rounding.

Parameters:

arr (ndarray) – (145,) float32 array as produced by to_array().

Return type:

Preset

global_continuous()

Global continuous params as a (15,) float32 array.

Order: feedback, transpose, pitch_mod_sensitivity, lfo_speed, lfo_delay, lfo_pitch_mod_depth, lfo_amp_mod_depth, pitch_env_rates[0..3], pitch_env_levels[0..3].

Return type:

ndarray

global_ints()

Global integer params as a (4,) int32 array.

Order matches GLOBAL_INT_MAXES: osc_key_sync, lfo_sync, algorithm, lfo_wave.

Return type:

ndarray

op_continuous()

Per-operator continuous params as a (6, 18) float32 array.

Row i holds operator i’s 18 continuous params. Order matches OP_CONTINUOUS_SIZE: env_rates[4], env_levels[4], output_level, frequency_coarse, frequency_fine, detune, velocity_sensitivity, amp_mod_sensitivity, rate_scaling, breakpoint, left_depth, right_depth.

Return type:

ndarray

op_ints()

Per-operator integer params as a (6, 3) int32 array.

Row i holds operator i’s 3 ints. Order matches OP_INT_MAXES: frequency_mode, left_curve, right_curve.

Return type:

ndarray

classmethod from_operator_bundles(global_cont, global_int, op_cont, op_int)

Construct a Preset from operator-bundle arrays.

Parameters:
  • global_cont (ndarray) – (15,) float32 — global continuous params.

  • global_int (ndarray) – (4,) int — [osc_key_sync, lfo_sync, algorithm, lfo_wave].

  • op_cont (ndarray) – (6, 18) float32 — per-operator continuous params.

  • op_int (ndarray) – (6, 3) int — per-operator ints [freq_mode, left_curve, right_curve].

Return type:

Preset

This is the inverse of calling global_continuous(), global_ints(), op_continuous(), op_ints().

static array_to_leaves(arr)

Split a (145,) flat array into a list of PyTree leaves.

Works with both NumPy and JAX arrays. JIT-traceable.

All Presets share the same treedef (no meta fields), so one treedef works universally:

_, treedef = jax.tree.flatten(Preset())

@jax.jit
def make_preset(flat_params):
    return jax.tree.unflatten(treedef, Preset.array_to_leaves(flat_params))
Parameters:

arr – flat array with len(arr) == 145.

Returns:

List of 28 arrays/scalars matching the PyTree leaf order.

classmethod from_patch(patch)

Create a Preset from a Patch.

Delegates to to_preset().

Return type:

Preset

to_patch(name='PRESET')

Convert to a Patch.

Denormalizes continuous parameters, rounds to integers, and clamps to native DX7 ranges.

Parameters:

name (str)

Patch

class dexed.Patch(name='INIT VOICE')

Bases: object

Complete DX7 patch with all parameters.

Provides named access to all DX7 parameters and conversion methods for various formats (sysex, packed, normalized arrays).

Operators are 0-indexed (op[0] through op[5]). Algorithm is 0-indexed (0-31).

Parameters:

name (str)

property op: _OperatorAccessor

patch.op[0] through patch.op[5].

Type:

Access operators by 0-based index

classmethod from_sysex(data)

Create Patch from 156-byte unpacked DX7 voice data.

This is the “VCED” format used in single-voice dumps.

Return type:

Patch

Parameters:

data (bytes)

to_sysex()

Export to 156-byte unpacked DX7 voice data.

Return type:

bytes

classmethod from_packed(data)

Create Patch from 128-byte packed format (used in bulk dumps).

Return type:

Patch

Parameters:

data (bytes)

to_packed()

Export to 128-byte packed format.

Return type:

bytes

classmethod load_bank(filename)

Load a DX7 bank file (32 voices).

Supports both raw 4096-byte dumps and standard sysex format.

Return type:

List[Patch]

Parameters:

filename (str)

save_to_bank(filename, patches=None)

Save patches to a bank file. If patches is None, saves just this patch as slot 0.

Parameters:
to_raw()

Export to 155-element array of raw DX7 parameter values.

Values are in their native DX7 ranges (0-99, 0-31, etc.).

Return type:

ndarray

classmethod from_raw(params)

Create Patch from 155-element raw parameter array.

Return type:

Patch

Parameters:

params (ndarray)

to_preset()

Convert to a Preset (flat, normalized ML representation).

Custom Operator Graphs

class dexed.OperatorGraph(num_ops=6)

Bases: object

Custom FM synthesis graph with arbitrary operator routing.

Provides DX7-accurate synthesis with the flexibility to create custom topologies beyond the 32 standard algorithms.

Parameters:

num_ops (int)

connect(source, target, amount=1.0)

Connect source operator to modulate target operator.

Parameters:
  • source (int) – Source operator index (0-indexed)

  • target (int) – Target operator index (0-indexed)

  • amount (float) – Modulation amount (default 1.0)

Return type:

OperatorGraph

Returns:

self for method chaining

disconnect(source, target)

Remove modulation connection between operators.

Return type:

OperatorGraph

Parameters:
set_carriers(carriers)

Set which operators output to audio.

Parameters:

carriers (List[int]) – List of operator indices (0-indexed)

Return type:

OperatorGraph

Returns:

self for method chaining

set_feedback(op, level=7)

Set self-feedback level for an operator (DX7 style).

Parameters:
  • op (int) – Operator index (0-indexed)

  • level (int) – Feedback level 0-7 (0 disables, 7 is maximum)

Return type:

OperatorGraph

Returns:

self for method chaining

property mod_matrix: ndarray

Get the modulation matrix (read-only copy).

property carriers: List[int]

Get carrier operator indices (0-indexed).

property modulators: List[int]

Get modulator operator indices (0-indexed).

get_connections()

Get all connections as (source, target, amount) tuples.

Return type:

List[tuple]

Returns:

List of (source_op, target_op, amount) tuples, all 0-indexed.

get_sources(target)

Get all operators that modulate a given target.

Parameters:

target (int) – Target operator index (0-indexed)

Return type:

List[tuple]

Returns:

List of (source_op, amount) tuples.

get_targets(source)

Get all operators that a given source modulates.

Parameters:

source (int) – Source operator index (0-indexed)

Return type:

List[tuple]

Returns:

List of (target_op, amount) tuples.

is_connected(source, target)

Check if source modulates target.

Return type:

bool

Parameters:
connection_amount(source, target)

Get modulation amount (0.0 if not connected).

Return type:

float

Parameters:
get_feedback(op)

Get feedback level for an operator (0 if none).

Return type:

int

Parameters:

op (int)

disconnect_all()

Remove all connections (reset to isolated operators).

Return type:

OperatorGraph

summary()

Get a human-readable summary of the graph configuration.

Return type:

str

Returns:

Multi-line summary string.

to_mermaid()

Generate Mermaid diagram syntax for visualization.

Return type:

str

Returns:

Mermaid flowchart syntax string.

to_ascii()

Generate ASCII art representation of the graph.

Return type:

str

Returns:

Multi-line string showing operators, connections, and carriers.

render(sample_rate=44100.0, midi_note=60, velocity=100, note_duration=1.0, render_duration=1.5)

Render audio from the operator graph with DX7-accurate synthesis.

Parameters:
  • sample_rate (float) – Audio sample rate in Hz

  • midi_note (int) – MIDI note number (0-127)

  • velocity (int) – Note velocity (0-127)

  • note_duration (float) – How long the note is held in seconds

  • render_duration (float) – Total audio duration in seconds

Return type:

ndarray

Returns:

Audio samples as float32 numpy array

render_all_ops(sample_rate=44100.0, midi_note=60, velocity=100, note_duration=1.0, render_duration=1.5)

Render individual operator outputs with DX7-accurate synthesis.

Returns:

  • Channels 0 to num_ops-1: Individual operator outputs

  • Last channel: Final output (sum of carriers)

Return type:

ndarray

Parameters:
classmethod from_matrix(mod_matrix, carriers, feedback=None)

Create an operator graph from a modulation matrix.

Parameters:
  • mod_matrix (ndarray) – NxN array where [i,j] = amount op j modulates op i

  • carriers (List[int]) – List of carrier operator indices (0-indexed)

  • feedback (Optional[Dict[int, int]]) – Optional dict of {op_index: level} for self-feedback (level 0-7)

Return type:

OperatorGraph

Returns:

OperatorGraph instance

classmethod from_algorithm(algorithm)

Create an operator graph matching a DX7 algorithm.

Parameters:

algorithm (int) – DX7 algorithm number (0-31)

Return type:

OperatorGraph

Returns:

OperatorGraph configured to match the algorithm

class dexed.GraphOperator(output_level=99, frequency_coarse=1, frequency_fine=0, frequency_mode=0, detune=7, velocity_sensitivity=0, rate_scaling=0, amp_mod_sensitivity=0, breakpoint=39, left_depth=0, right_depth=0, left_curve=0, right_curve=0, envelope=<factory>)

Bases: object

Operator in a custom FM synthesis graph.

Parameters match DX7 operators for familiarity and accuracy.

Parameters:
  • output_level (int)

  • frequency_coarse (int)

  • frequency_fine (int)

  • frequency_mode (int)

  • detune (int)

  • velocity_sensitivity (int)

  • rate_scaling (int)

  • amp_mod_sensitivity (int)

  • breakpoint (int)

  • left_depth (int)

  • right_depth (int)

  • left_curve (int)

  • right_curve (int)

  • envelope (GraphEnvelope)

output_level: int = 99
frequency_coarse: int = 1
frequency_fine: int = 0
frequency_mode: int = 0
detune: int = 7
velocity_sensitivity: int = 0
rate_scaling: int = 0
amp_mod_sensitivity: int = 0
breakpoint: int = 39
left_depth: int = 0
right_depth: int = 0
left_curve: int = 0
right_curve: int = 0
envelope: GraphEnvelope
property frequency_ratio: float

Compute frequency ratio from coarse/fine settings.

class dexed.GraphEnvelope(rates=<factory>, levels=<factory>)

Bases: object

4-stage envelope for graph operators.

Parameters:
rates: List[int]
levels: List[int]

Algorithm Utilities

dexed.get_carriers(algorithm)

Get list of carrier operator numbers for an algorithm.

Return type:

List[int]

Parameters:

algorithm (int)

dexed.get_modulators(algorithm)

Get list of modulator operator numbers for an algorithm.

Return type:

List[int]

Parameters:

algorithm (int)

dexed.get_mod_matrix(algorithm)

Get 6x6 modulation matrix for an algorithm.

Return type:

ndarray

Parameters:

algorithm (int)

dexed.algorithms = <dexed.algorithms._AlgorithmDict object>

Dictionary-like access to algorithms by number (0-31).