# EuclidianSequencer vs Sequencer8 vs TuringMachine: Understanding the Difference Between These Nallely MIDI Sequencers

> Compare Nallely MIDI sequencers: EuclidianSequencer for Euclidean rhythms, Sequencer8 for traditional steps, and TuringMachine for evolving algorithmic sequences. Discover the best for your music.

- Repository: [dr-schlange/nallely-midi](https://github.com/dr-schlange/nallely-midi)
- Tags: deep-dive
- Published: 2026-02-28

---

**EuclidianSequencer generates Euclidean rhythm patterns using a computed deque of 0/1 values based on length and density parameters, Sequencer8 operates as a traditional 8-step step-sequencer with individually activatable steps, and TuringMachine implements a probabilistic 8-bit rotating tape for evolving algorithmic sequences.**

The **dr-schlange/nallely-midi** library provides three distinct virtual sequencer devices for modular MIDI and CV generation. Understanding the **difference between EuclidianSequencer, Sequencer8, and TuringMachine** is essential for selecting the right rhythmic control strategy, whether you need mathematical rhythm distribution, traditional step programming, or generative evolution.

## Core Architecture and Design Philosophy

### EuclidianSequencer – Euclidean Rhythm Generation

**EuclidianSequencer**, defined in [`nallely/sequencer.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/sequencer.py) (lines 93–184), implements the Bjorklund algorithm to distribute a specified number of hits evenly across a configurable length. The pattern is computed once—or whenever the **length**, **hits**, or **shift** parameters change—and stored in a `deque` of binary values. This produces mathematically even rhythmic distributions ideal for drum patterns.

### Sequencer8 – Fixed Step Sequencing

**Sequencer8**, located in the same file (lines 130–214), functions as a traditional analog-style step-sequencer with exactly 8 steps. Step values are stored as direct attributes (`step0` through `step7`), and each step includes an `activeN` boolean flag for per-step muting. Unlike the algorithmic generation of the other two devices, this sequencer relies on manual value entry and activation control.

### TuringMachine – Probabilistic Tape Rotation

**TuringMachine**, found at lines 15–189 in [`nallely/sequencer.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/sequencer.py), models a finite state machine with an 8-bit memory tape implemented as a `deque`. On each clock trigger, the tape rotates and optionally mutates based on a probability parameter, creating evolving binary patterns without explicit step programming.

## Clock Input and Trigger Behavior

**EuclidianSequencer** responds to the **clock_cv** input, advancing an internal step counter on rising edges. The `on_clock_rising()` method outputs gate and trigger signals whenever the current step value equals 1.

**Sequencer8** uses two distinct inputs: **play_cv** to start or stop the sequence and **trigger_cv** to advance to the next step. The `next_step()` method checks `current_step_active()` (lines 62–64) to determine whether to emit outputs for the current position.

**TuringMachine** treats **trigger_cv** as the master clock. Every rising edge executes `on_trigger_rising()`, which rotates the `self.memory` deque and potentially flips the newest bit based on the **mutation** probability setting.

## Data Structures and Pattern Storage

- **EuclidianSequencer**: Stores the computed pattern in a `deque` of 0/1 values. The `compute_sequence()` method (lines 38–47) recalculates the pattern using a floor-based algorithm when parameters change.
- **Sequencer8**: Maintains step values as individual float attributes alongside boolean activation flags. The pattern is not computed but directly stored in object attributes.
- **TuringMachine**: Uses a `deque` representing an 8-bit tape. The memory rotates rather than advancing a playhead, creating a circular shift register effect where bits circulate through the output positions.

## Length Configuration and Step Activation

**EuclidianSequencer** supports **length** parameters from 1–128 steps and **hits** from 1–128, allowing sparse or dense rhythmic patterns. No per-step muting exists; the pattern is deterministic based on the Euclidean algorithm.

**Sequencer8** is constrained to 8 steps maximum, though the **length_cv** input (1–8) can shorten the active playback range. Individual steps can be disabled via `activeN_cv` inputs (lines 55–62), causing the sequencer to skip gates for those positions while maintaining the step values in memory.

**TuringMachine** has a fixed 8-bit tape length. Instead of step activation, it offers a **mutation** probability (0.0–1.0) to randomly invert the newest bit when the tape rotates, creating generative variations of the initial pattern.

## Output Parameters and Signal Types

**EuclidianSequencer** provides three primary outputs:
- `step_out_cv`: Current step index
- `gate_out_cv`: High when step value is 1
- `trigger_out_cv`: Pulse when step value is 1

**Sequencer8** provides extensive I/O for step control:
- `current_step_cv`: Playback position index
- `edit_step_cv`: Editing position index
- `output_cv`: CV value of the current step
- `trig_out_cv`: Trigger pulse output
- `active0_cv` through `active7_cv`: Per-step activation states

**TuringMachine** provides binary and integer outputs:
- `out_main_cv`: Current bit value (0 or 1)
- `gate_out_cv`: Gate signal for the current bit
- `tape_out_cv`: 8-bit integer representing the entire tape state
- `out0_cv` through `out7_cv`: Individual bit outputs for each memory cell

## Practical Implementation Examples

```python

# EuclidianSequencer – 16-step pattern with 5 hits, shifted by 2 steps

euclid = EuclidianSequencer(length=16, hits=5, shift=2)
for _ in range(20):
    for out in euclid.on_clock_rising(1, None):
        print(out)  # Yields step index, gate, and trigger pulse

```

```python

# Sequencer8 – 8-step melodic sequence with step 3 muted

seq8 = Sequencer8()
seq8.step0 = 60   # C4

seq8.step1 = 62   # D4

seq8.step2 = 64   # E4

seq8.step3 = 65   # F4 (muted)

seq8.step4 = 67   # G4

seq8.active3 = 0  # Disable step 3

for _ in range(10):
    for out in seq8.on_trigger_rising(1, None):
        print(out)  # Yields step index, CV value, and trigger

```

```python

# TuringMachine – 8-bit tape with 30% mutation probability

tm = TuringMachine(mutation=0.3)
tm.on_random_rising(1, None)  # Seed with random byte

for _ in range(16):
    for out in tm.on_trigger_rising(1, None):
        print(out)  # Yields tape integer, current bit, and individual outputs

```

## Summary

- **EuclidianSequencer** computes mathematical rhythm patterns using the Euclidean algorithm, ideal for drum sequencing with configurable density and length up to 128 steps.
- **Sequencer8** provides traditional step-sequencing with 8 discrete steps and per-step muting, suitable for melodic lines and CV automation where manual control is preferred.
- **TuringMachine** generates evolving binary patterns through rotating memory and probabilistic mutation, perfect for generative music and algorithmic composition that changes over time.

## Frequently Asked Questions

### Can I change the sequence length dynamically in all three sequencers?

Only **EuclidianSequencer** supports runtime length changes up to 128 steps via the **length** parameter. **Sequencer8** allows shortening the active range to 1–8 steps using **length_cv** but maintains 8 underlying storage slots. **TuringMachine** has a fixed 8-bit tape that cannot be resized.

### Which sequencer supports per-step muting or disabling?

**Sequencer8** uniquely provides individual `activeN` boolean flags for each of its 8 steps, allowing you to mute specific positions without deleting their values. **EuclidianSequencer** outputs the full computed pattern without per-step gating, while **TuringMachine** always outputs the complete tape state as a rotating shift register.

### How does the TuringMachine create variations without traditional step parameters?

The **TuringMachine** uses a **mutation** probability parameter (0.0–1.0) in its `on_trigger_rising()` method. When triggered, it rotates the 8-bit memory `deque` and randomly flips the newest bit based on this probability, creating evolving sequences through probabilistic bit manipulation rather than manual step editing.

### Where are these sequencers defined in the nallely-midi source code?

All three classes reside in [`nallely/sequencer.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/sequencer.py): **TuringMachine** is defined at lines 15–189, **EuclidianSequencer** at lines 93–184, and **Sequencer8** at lines 130–214. They inherit from `VirtualDevice` defined in [`nallely/core.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/core.py) and utilize helper functions from [`nallely/utils.py`](https://github.com/dr-schlange/nallely-midi/blob/main/nallely/utils.py).