Skip to content

[DRAFT]: Add Sequencer Modes: Step & Pulse#4143

Open
solaris76 wants to merge 27 commits intoSynthstromAudible:communityfrom
solaris76:sequencer-modes-pr
Open

[DRAFT]: Add Sequencer Modes: Step & Pulse#4143
solaris76 wants to merge 27 commits intoSynthstromAudible:communityfrom
solaris76:sequencer-modes-pr

Conversation

@solaris76
Copy link
Copy Markdown
Contributor

@solaris76 solaris76 commented Oct 13, 2025

[DRAFT] Sequencer Modes: Alternative Pattern-Based Sequencing for Deluge

Overview

This PR adds alternative sequencer modes to the Deluge - new ways to create and perform patterns beyond the traditional piano roll. Think of them as different "views" of musical material that complement the existing linear clip system.

Status: Alpha 0.7 - Core functionality working, ready for testing and feedback


What This Adds

Two New Sequencer Modes

1. Step Sequencer 📊

  • Classic 16-step analog-style sequencer (inspired by analog sequencers)
  • Each column = one step with gate, octave, and note selection
  • Perfect for bass lines, arpeggios, and melodic patterns

2. Pulse Sequencer 🌀

  • 8-stage euclidean/polyrhythmic sequencer (inspired by Intellijel Metropolix)
  • Each stage can generate 1-8 pulses with different timings
  • Includes play order modes (Forward, Backward, Ping-Pong, Random, Pedal, etc.)
  • Perfect for complex rhythms and generative patterns

Performance Controls (Control Pads)

Configurable sidebar columns (x16-x17):

  • Clock Division - Change playback speed (1/4x to 32x)
  • Octave Shift - Transpose by octaves
  • Transpose - Semitone transposition
  • Direction - Forward/Backward/Ping-Pong/Random (Step Seq & Gen Seq)
  • Scenes - 8 snapshots per mode for live performance
  • Generative - Reset, Randomize, Evolve controls

Each pad is individually configurable with Toggle/Momentary modes.

Pattern Save/Load System

Patterns save to mode-specific folders:

  • Step Sequencer → PATTERNS/MELODIC/SEQUENCER/STEP/
  • Pulse Sequencer → PATTERNS/MELODIC/SEQUENCER/PULSE/
  • Piano Roll → PATTERNS/MELODIC/ (unchanged, backward compatible)

Compact HEX encoding following Deluge conventions (like noteDataWithSplitProb)

Song files preserve all sequencer mode states + piano roll data


How It Works

Mode Selection

Access via Select Encoder menu:

  1. Select encoder → "CLIP TYPE"
  2. Choose: PIANO ROLL, STEP SEQ, PULSE SEQ
  3. Pads instantly change to show the selected sequencer

Key Design Principles

  1. Piano roll remains master - Note data is still stored in NoteRows
  2. Non-destructive - Switch between modes without losing work
  3. Universal - Works with Synth, MIDI, and CV tracks
  4. Performance-focused - Control pads and scenes for live use
  5. Deluge conventions - Follows existing UI patterns and file formats
  6. Shift+Pad preserved - Shift key still edits synth parameters in all modes

Current Implementation Status

✅ Working Features

Core Sequencers:

  • Step Sequencer (16 steps, gate/octave/note per step)
  • Pulse Sequencer (8 stages, euclidean patterns)
  • Mode switching via Clip Type menu
  • Real-time playback with sync to tempo

Control System:

  • 16 configurable control pads (x16-x17)
  • Clock Division, Octave, Transpose, Direction controls
  • Toggle and Momentary pad modes
  • Scene capture/recall (8 scenes per mode)

Persistence:

  • Pattern save/load with compact HEX encoding
  • Song save/load preserves sequencer states
  • Automatic folder routing based on active mode
  • Playback continues during save/load operations

UI/UX:

  • Full pad rendering for each mode
  • Real-time visual feedback
  • Display popups for all actions
  • Sidebar rendering for control pads
  • Fader visualization with intensity gradients

🚧 Known Limitations

  • Kit/Audio clips not yet supported (instrument tracks only)
  • Recording sequencer output to piano roll not yet implemented
  • MIDI learn for control pads not yet implemented
  • Undo/redo for sequencer actions not yet implemented

Architecture

RAII Design

All sequencer modes use RAII (Resource Acquisition Is Initialization):

  • Smart pointers manage mode lifetime
  • Factory pattern for mode creation
  • Clean initialization/cleanup

File Structure

src/deluge/model/clip/sequencer/
├── sequencer_mode.h/.cpp           (base class)
├── sequencer_mode_manager.h/.cpp   (factory)
├── modes/
│   ├── step_sequencer_mode.h/.cpp
│   ├── pulse_sequencer_mode.h/.cpp
└── control_columns/
    ├── sequencer_control_state.h/.cpp
    ├── sequencer_control_group.h/.cpp
    └── control_types.h

Integration Points

Modified files (minimal changes to existing code):

  • instrument_clip.h/.cpp - Added sequencer mode management
  • instrument_clip_view.cpp - Mode rendering/input handling
  • save_pattern_ui.cpp - Folder routing for sequencer patterns
  • load_pattern_ui.cpp - Folder routing for loading

New files (isolated sequencer code):

  • All sequencer mode implementations
  • Control column system
  • Documentation

File Format

Pattern Files

Step Sequencer Pattern:

<pattern>
  <attributes
    patternVersion="0.0.1"
    sequencerMode="step_sequencer"
    scaleType="0" />
  <stepSequencer
    numSteps="16"
    currentStep="0"
    noteScrollOffset="0"
    stepData="0x000301010203..." />
  <controlColumns padData="0x001004000000060001...">
    <scenes>
      <scene index="0" size="128">0xABCD...</scene>
    </scenes>
  </controlColumns>
  <noteRows>...</noteRows>
</pattern>

Encoding:

  • stepData: 3 bytes per step (noteIndex, octave+3, gate)
  • stageData: 7 bytes per stage (gate, note, octave, pulseCount, velocity, probability, gateLength)
  • padData: 9-10 bytes per pad (y, x, type, valueIndex, mode, active, sceneValid)
  • Follows Deluge's noteDataWithSplitProb HEX encoding convention

Credits

Design & Implementation: Chris Griggs (@solaris76)

Built on: Deluge Community Firmware


Request for Feedback

This is an alpha release - please test and provide feedback on:

  1. Usability - Is the UI intuitive? Any confusing aspects?
  2. Stability - Any crashes, errors, or unexpected behavior?
  3. Performance - Does playback feel solid? Any timing issues?
  4. Features - What sequencer modes would you like to see next?
  5. Workflow - Does the pattern save/load workflow feel natural?
  6. Gen Sequencer - How does the generative behavior feel? Are the fader controls intuitive?

How to provide feedback:

  • Open issues on this PR

Thank You

Huge thanks to the Deluge Community Firmware team for creating such an extensible platform, and to everyone who tests and provides feedback on this feature!

🎹 Happy sequencing! 🎹

New Features:
- Step Sequencer: 16-step analog-style sequencer (SH-101/TB-303 inspired)
- Pulse Sequencer: 8-stage euclidean/polyrhythmic sequencer (Metropolix inspired)
- Control Pads: 16 configurable performance controls (Clock Div, Octave, Transpose, Direction, Scenes, Generative)
- Pattern Save/Load: Mode-specific folders with compact HEX encoding
- Song Persistence: All sequencer states preserved in song files

Architecture:
- RAII design with smart pointers
- Factory pattern for mode management
- Isolated in src/deluge/model/clip/sequencer/
- Minimal changes to existing Deluge code
- Follows Deluge conventions (keyboard layout system, file formats)

Status: Alpha 0.6 - Core functionality working, ready for community testing
- Scene XML wasn't properly closing tags
- Fixed closeTag() to closeTag("scene")
- Should resolve E365 parsing error when loading patterns
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 13, 2025

Test Results

175 tests  ±0   175 ✅ ±0   1s ⏱️ -1s
 21 suites ±0     0 💤 ±0 
 21 files   ±0     0 ❌ ±0 

Results for commit 4456d37. ± Comparison against base commit 7d0b687.

♻️ This comment has been updated with latest results.

- Fix duplicated sequencerMode_->readFromFile() calls in instrument_clip.cpp
- Simplify XML parsing structure to properly handle mode attribute and delegate child elements
- Remove redundant error handling blocks that were causing CI job failures
- Clean up unused sequencer mode folder logic in save_pattern_ui.cpp

Resolves CI job failure ID: 52646064856
- Fix StepSequencerMode::writeToFile() to specify 'stepSequencer' tag name in closeTag()
- Fix PulseSequencerMode::writeToFile() to specify 'pulseSequencer' tag name in closeTag()
- Ensures proper XML serialization when saving sequencer mode data
- Fix StepSequencerMode::writeToFile() to use writeAttributeHexBytes() instead of manual writer.write()
- Fix PulseSequencerMode::writeToFile() to use proper XML serialization methods
- Fix SequencerControlState::writeToFile() to use writeAttributeHexBytes() for padData
- Add proper writeOpeningTagEnd() and writeClosingTag() calls
- Add missing #include <vector> for dynamic byte arrays

These fixes resolve E365 XML corruption errors when saving/loading songs with sequencer mode data.
The XML output is now properly formatted with correct tag structure.
- Add sequencer mode processPlayback() call to InstrumentClip::processCurrentPos()
- Sequencer modes now replace normal note row processing when active
- This enables actual sound generation from step sequencer and pulse sequencer modes
- Fixes issue where sequencer modes were not playing any notes

The sequencer mode playback integration was missing, causing sequencer modes to render
but not generate any audio. Now when a sequencer mode is active, it completely replaces
the linear clip playback with pattern-based sequencing.
- Integrate sequencer mode processing into Session::doTickForward() alongside arpeggiator
- Add sequencer mode processing loop that calls processPlayback() for active sequencer clips
- Include proper timing integration with swungTicksTilNextEvent for efficient scheduling
- Add necessary include for SequencerMode class in session.cpp
- Skip normal note row processing when sequencer mode is active in InstrumentClip
- Remove duplicate sequencer processing from InstrumentClip (now handled at session level)

This completes the sequencer playback integration, enabling step sequencer and pulse
sequencer modes to generate notes during playback. The architecture follows Deluge
patterns by handling sequencer processing in the main session loop similar to how
the arpeggiator is processed.
- Add PATTERNS/SEQUENCER/STEP/ and PATTERNS/SEQUENCER/PULSE/ folder support
- Update SavePatternUI to detect sequencer modes and save to appropriate folders
- Update LoadPatternUI to load from sequencer-specific folders instead of PATTERNS/MELODIC/
- Create sequencer folders automatically when saving patterns
- Provide clear titles: 'Save Step Pattern' and 'Save Pulse Pattern'

This organizes sequencer patterns separately from regular melodic patterns,
making it easier to manage and find sequencer-specific content on the SD card.
- Correct indentation in sequencer mode reading code
- Fix misplaced closing brace that was causing format check failure
- Ensure proper tab indentation follows Deluge code style

This resolves the CI formatting check failure in job 52668798897.
- Fix method signatures and parameter alignment across all sequencer files
- Standardize if-statement formatting: if (condition) action; → if (condition) newline action;
- Fix switch statement formatting with proper case indentation
- Reorder includes alphabetically within groups
- Fix template formatting: template<T> → template <T>
- Standardize else formatting: } else { → } newline else {
- Fix namespace formatting and add closing comments
- Align method call parameters properly
- Fix enum and struct member alignment
- Standardize comment spacing and alignment
- Fix macro indentation in registration code
- Resolve all clang-format violations for CI compliance

These changes ensure the code passes automated formatting tests while
maintaining functionality and compilation compatibility.
…cer data

- Add stopAllNotes() method to SequencerMode base class and implementations
- Integrate sequencer note cleanup with InstrumentClip::expectNoFurtherTicks()
- Enhanced cleanup() methods to properly stop notes during mode switching
- Fix XML serialization issues causing E365 errors:
  - Use self-closing tags for sequencer elements (stepSequencer, pulseSequencer)
  - Convert scene data to attributes for consistent XML structure
  - Fix XML/JSON format mismatch in control columns parsing
  - Proper tag delegation following arpeggiator pattern
  - Add safety checks for empty padData and large scene data
- Preserve both linear note data AND sequencer data in song files
- Add robust error handling for hex data parsing
- Ensure backward compatibility with existing song files

This resolves hung notes when stopping playback and eliminates E365 XML
corruption errors when saving/loading songs with sequencer mode data.
Both linear clips and sequencer modes now coexist properly.
Normal clips notes no longer play over Sequencer modes.

Key fixes:
- Implemented proper sequencer mode caching to preserve data
- Fixed hasSequencerMode() logic to prevent interference with piano roll
- Sequencer instances now cached when switching modes instead of destroyed
- Step and pulse sequencer data preserved across mode switches
- Updated default patterns to all gates OFF for cleaner user experience
- Removed arp-influenced values from default pattern detection
- Fixed XML serialization issues and hung note problems
- Added comprehensive note cleanup for cached sequencer modes
…equencer data currently)

- Modified InstrumentClip::copyBasicsFrom() to preserve sequencer mode type during clip duplication
- Duplicated clips maintain their sequencer mode (step/pulse) but get default patterns
- Cached sequencer modes are also recreated with defaults
- This ensures consistent behavior: duplicated clips have the same mode but clean patterns
- Future enhancement: implement proper clone() methods for full pattern duplication
- Move sequencer mode registration from static initialization to lazy initialization
- Prevents interference with Deluge's custom memory allocator during startup
- Fixes memory corruption in emptySpaces tracking that caused M005 errors
- No changes to InstrumentClip core functionality
- Sequencer modes (step_sequencer, pulse_seq) now register safely on first access

Changes:
- sequencer_mode_manager.cpp: Added lazy registration in instance() method
- step_sequencer_mode.cpp: Removed static registration lambda
- pulse_sequencer_mode.cpp: Removed static registration lambda
@solaris76 solaris76 marked this pull request as ready for review October 20, 2025 12:10
@solaris76 solaris76 changed the title [DRAFT]: Add Sequencer Modes: Step Sequencer and Pulse Sequencer [DRAFT]: Add Sequencer Modes: Step, Pulse & Generative Sequencer Nov 28, 2025
@MrHaila
Copy link
Copy Markdown

MrHaila commented Dec 8, 2025

Really interesting stuff!

I spent a bit of time testing the step sequencer yesterday. I think I saw two technical issues:

  1. The pianoroll playhead gets stuck on top of all new sequencers if switching to them while play mode is on.
  2. I think the step sequencer playhead looks wrong in "skip" steps, where it seems to highlight the step that is getting skipped while already playing the correct note, then proceeds to jump over to the next correct note. Sounds right, but visuals look off.

I find the UX quite hard to approach in this current iteration since they are quite complicated sequencers. I would need to spend a lot more time with them to come up with actional UX feedback, tho. My most immediate dissonance in the step sequencer is that the steps always have a note "pitch" selected, even when they are "off". I would expect to be able to press a note pitch to turn it off and for that column (octave buttons, etc.) to be visually muted to tell them apart more easily.

It might also make more sense to have color coded "pages" of the step sequencer to have to columns represent velocity, gate, random of that step in addition to pitch? The <> encoder would be a pretty handy tool for that.

Would it make sense to split this PR into separate sequencers to not bundle all the UX work together, blocking each other?

@solaris76
Copy link
Copy Markdown
Contributor Author

I spent a bit of time testing the step sequencer yesterday. I think I saw two technical issues:
Would it make sense to split this PR into separate sequencers to not bundle all the UX work together, blocking each other?

Awesome, thanks for taking the time to review, much appreciated. You're right re the step seq, I should dim the step if inactive, will take a look. Like the idea of multiple pages too, will see what I can do. Tbh the step sequencer (and the generative one) were extra ones I added so could do with a bit more review/improvement.

Thanks again.

- Dim SKIP steps to 10% brightness (entire column)
- Dim OFF step note pads to 10% brightness
- Fix red indicator not showing on steps following SKIP steps
- Reset to first step when playback starts
- Clear white progress column when initializing sequencer modes (step, pulse)
- Make octave pads bright white only when step type is ON, dim for OFF/SKIP
@solaris76
Copy link
Copy Markdown
Contributor Author

Pushed an update that should fix those issues above (removed the generative seq for now), and dimmed the column when steps are skipped so should be a bit clearer. Thanks @MrHaila

- Add Shift key check in step sequencer handlePadPress to allow synth parameter editing
- Add Shift key check in pulse sequencer handlePadPress to allow synth parameter editing
- When Shift is pressed, pad presses return false so instrument clip view can handle them
- Move static lastRefreshTick to member variable in pulse sequencer
- Handle note slot exhaustion: stop oldest note when all slots full
- Complete cleanup: reset all state variables in both sequencers
- Clear scale notes array in step sequencer cleanup
- Reset all note tracking arrays in pulse sequencer cleanup
- Initialize lastRefreshTick in pulse sequencer initialize
- Add include for sequencer_mode.h
- Process sequencer modes in arrangement mode, similar to session mode
- Fixes sequencer mode clips not working in arrangement mode
@solaris76 solaris76 changed the title [DRAFT]: Add Sequencer Modes: Step, Pulse & Generative Sequencer [DRAFT]: Add Sequencer Modes: Step & Pulse Dec 8, 2025
@MrHaila
Copy link
Copy Markdown

MrHaila commented Dec 13, 2025

I pulled the latest and poked around some more with proper thought.

Bugs:

  • Entering step sequencer and backing out to piano roll while play mode is on causes the currently playing step sequencer note to get stuck. Stop/play fixes this.
  • Stopping the step sequencer causes the play head to get stuck (pause instead of stop?). Changing the clip type does not fix this.
  • Pressing play causes the step sequencer play head to start from step 2 while playing the audio of the first step twice. Only affects the first loop, after pressing start. Easy to repro by putting in a high note as the first one to hear it clearly.
  • The step sequencer play head is seemingly off by one, highlighting the next step to be played instead of the current one.
  • Skipped notes in the step sequencer seem to have an off by one bug as well, where the first skipped note is treated the same as "off" and subsequent skipped notes actually skip. I didn't see this bug a week ago. Repro by inputting "on, off, on, skip, on, off" for example.
  • Going to 40% brightness or lower causes the skipped/off track muted pads to have buggy colors/brightnesses and some pads start flickering when play mode is on. Only affects muted pads and when on lower than 40% brightness. "fix" by setting to 44% brightness.
  • shift + <> still resizes the piano roll that is not visible in step sequencer. Unexpected. <> tries to navigate the piano roll and that is also not visible.
  • Step sequencer has not got the same play direction options as the pulse sequencer. Feels like a bug since the two are so similar in UX.
  • Pulse sequencer play head seems to highlight first step twice on every loop.

Suggestions:

  • I would like to tap an active note pad to make it off. Similarly, tapping a note pad in an off step would ideally turn it on in addition to setting the note. Similar to velocity sequencer.
  • I would like the off steps to not have a note selected. This would make it feel more similar to piano roll and velocity sequencer.
  • I would like to hold a note pad an press another note pad to arp all the in-between steps. Like velocity sequencer. Now it does nothing.
  • I would like to press and turn the up/down encoder for octave shift and shift + same for semitones, like in piano roll. Now it does nothing.
  • I would like the step sequencer playhead look the same as the default Deluge playhead, so a white bar. The current red highlight indicates that it is somehow different and dangerous(?) but I don't think it is.
  • I would like to hold a step and use the select encoder to set step randomization and condition just like in piano roll. Now it changes the instrument as if a step was not pressed at the same time.
  • Random feels a bit too random for me. I would love to hold a note and press random to only random the notes instead of steps and hold a step gate to only random the gates.
  • I would prefer if all the steps were off by default instead of on to prevent nasty sounds while entering when play mode is on. Would also make this more similar to piano roll and pulse sequencer that are quiet by default.
  • I would like to be able to edit the gate length and velocity of the step sequencer steps. The most intuitive view I can think of would be similar to the velocity sequencer. Similar to the DROID motor fader sequencer, I think.
  • I would like to hold an individual note and use the gold encoders to edit the param of that one step.
  • I think I would prefer the skipped steps in step sequencer to mute out the whole column, including notes, using the exact same visual as when resizing clips in a piano roll and the muted area indicates what area is outside of the clip and "inactive". This feels like a veru similar visual concept.
  • I would like the the song view to display something on the row of the step sequencer. Maybe the on/off/skipped statuses like Metropolix seems to do on its screen?

Thinking about the step sequencer... I would suggest moving the octave buttons below the step gate buttons and make the up/down encoder scroll the whole view instead of just the note grid. That way, I could get all my notes of a default scale to be visible at once without scrolling. I think it is more important for me to be able to see where the notes are vs having the octave buttons always on top.

Again, thanks for working on this! I would be extremely happy to not have to buy more gear to be able to explore and practice with more sequencer types. So at least I can help alpha test this stuff.

I haven't really interrogated the pulse sequencer at all since the UX is so overwhelming. Poking the step sequencer first.

@MrHaila
Copy link
Copy Markdown

MrHaila commented Dec 13, 2025

I noticed that the step sequencer does not really play well together with the song view, and in fact has its own concept of scenes. To me, it would feel more intuitive to not have scenes at all and instead use the default Deluge clips feature for the same purpose. I would like to be able to duplicate a currently playing step sequencer in the song view and start editing it like I would a piano roll clip. Currently, it initializes an empty one instead of duplicating the contents.

Related bug: duplicating a step sequencer in the song view and hold+select encoder on the newly duplicated row (that is not playing) to change the instryment causes the instrument to go quiet. Same action works on the enabled row that is playing notes, so possibly this has something to do with editing a row that is disabled. Editing the instrument on the enabled row fixes the sounds or stop/play also fixes it.

@MrHaila
Copy link
Copy Markdown

MrHaila commented Dec 13, 2025

One more: entering the step sequencer from song view while playing causes the song view play head to get stuck on top of the step sequencer.

@solaris76
Copy link
Copy Markdown
Contributor Author

solaris76 commented Dec 14, 2025

Thanks again @MrHaila
Response to you suggestions below. Will have a look at those bugs too thanks. Thanks again for spending time on all this.

  • I would like to tap an active note pad to make it off. Similarly, tapping a note pad in an off step would ideally turn it on in addition to setting the note. Similar to velocity sequencer.
  • I would like the off steps to not have a note selected. This would make it feel more similar to piano roll and velocity sequencer.
  • I would like to hold a note pad an press another note pad to arp all the in-between steps. Like velocity sequencer. Now it does nothing.

This isn't really how an analogue sequencer works which is what this concept is based on (inspired by my Korg SQ1). I also need to see what note I have selected and or whether I have a note on/off. Given we can have up to 12 notes in a scale this would provide poor usability as i can't at a glance see whether a note is selected or not and or what note i have selected is then enabling a step. Eg I may re-enable a step and wonder why nothings playing if i've disabled a note.

  • I would like to press and turn the up/down encoder for octave shift and shift + same for semitones, like in piano roll. Now it does nothing.

I've added shift + vertical to shift octaves. You also have the octave/transpose control column option for this. this way you have much more control. Hold an empty pad on the two rightmost columns, choose Octave with <>, then choose amount +/- with vert encoder (press encoder to set toggle/momentary). You have much more usable control this way and this is mainly based on performance.

  • I would like the step sequencer playhead look the same as the default Deluge playhead, so a white bar. The current red highlight indicates that it is somehow different and dangerous(?) but I don't think it is.

Highlighting the step/note in our case makes the most sense to me as the white bar displays where the Deluge is in the clip. The sequencers have their own independent lengths so the white position bar and highlighted notes are not the same. Also, having the white bar jump around on a random order would be a bit odd in my view and also would take up too much of the UI.

  • I would like to hold a step and use the select encoder to set step randomisation and condition just like in piano roll. Now it changes the instrument as if a step was not pressed at the same time.
    Nice idea. Will look into that.
  • Random feels a bit too random for me. I would love to hold a note and press random to only random the notes instead of steps and hold a step gate to only random the gates.

Hold the random button and turn the Vertical encoder. You can set the random %. You might want to set one of the pads to Evolve which will only shift notes at lower %'s. As a note, all the right two column pads are configurable. e.g. hold an unlit pad, turn <> encoder to choose action, then vert encoder for value/percentage or press to toggle momentary/toggle. This way you can completely configure the right column to your needs.

  • I would prefer if all the steps were off by default instead of on to prevent nasty sounds while entering when play mode is on. Would also make this more similar to piano roll and pulse sequencer that are quiet by default.

Agree. Will Update.

  • I would like to be able to edit the gate length and velocity of the step sequencer steps. The most intuitive view I can think of would be similar to the velocity sequencer. Similar to the DROID motor fader sequencer, I think.
  • I would like to hold an individual note and use the gold encoders to edit the param of that one step.
    Maybe we could set velocity and gate length like this?

This could work. Maybe hold note pad + <> for Velocity, Vert for gate length and select for note probability?

  • I think I would prefer the skipped steps in step sequencer to mute out the whole column, including notes, using the exact same visual as when resizing clips in a piano roll and the muted area indicates what area is outside of the clip and "inactive". This feels like a veru similar visual concept.

Don't agree here. I personally think we need to ensure we still know what the step note settings are even if step is skipped. However I have added this functionality when you change the total length of the sequencer using Shift + <>.

  • I would like the the song view to display something on the row of the step sequencer. Maybe the on/off/skipped statuses like Metropolix seems to do on its screen?

I think would add too much complexity to song view personally. You dont see the note probably etc from clip view so think it would be odd to have this here.

@solaris76
Copy link
Copy Markdown
Contributor Author

solaris76 commented Dec 14, 2025

I noticed that the step sequencer does not really play well together with the song view, and in fact has its own concept of scenes. To me, it would feel more intuitive to not have scenes at all and instead use the default Deluge clips feature for the same purpose. I would like to be able to duplicate a currently playing step sequencer in the song view and start editing it like I would a piano roll clip. Currently, it initializes an empty one instead of duplicating the contents.

The scenes feature in my view is by far the most useful of the sequencers and really sets them apart from others. You can save a state with random/octave/transpose then go back to where you were, great for trying variations without losing your prior one. You can have up to 8 scenes per sequencer. That said, you dont need to use the scenes like this and can still do as you describe.

I do need to look more at song & arrange mode though and the implications of the sequencers there as agree might not be optimal currently.

- Fix timing issue: advance step at START of boundary, refresh UI before processing
- Optimize memory: use smaller integer types (uint8_t/int8_t/int16_t) for step sequencer state
- Remove old format fallback handling for numActiveSteps
- Simplify step advancement logic to ensure correct red highlight on step after skip
- Restructure step advancement to happen at START of boundary (not end)
- Fix UI refresh timing to occur after advancement, ensuring async render sees correct currentStep_
- Prevent double-play of first step by only advancing when position has moved forward
- Fix red pad highlight after skip steps by refreshing UI immediately after advancing past skip
- Ensure currentStep_ stays correct throughout step duration for proper UI highlighting
@solaris76
Copy link
Copy Markdown
Contributor Author

New commit should fix most of those bugs :)

Also added the ability to alter sequencer length holding shift + <> like clips.

- Add probability field to Step struct (0-100%, default 100%)
- Add select encoder control for probability adjustment when note pad held
- Improve display formatting: show 'Velocity: 100', 'Gate length: 75', 'Probability: 75%'
- Fix encoder handling: only adjust velocity/gate/probability when note pad is actually held
- Fix pad release tracking to properly clear held pad state
- Add helper functions: isNotePadHeld(), displayValue(), clampValue()
- Optimize memory: change heldPadX_/heldPadY_ from int32_t to int8_t
- Use probability in playback via shouldPlayBasedOnProbability()
- Update file persistence to include probability (6 bytes per step with backward compatibility)
- Restore vertical encoder note scrolling when no pad is held
- Vertical encoder now: adjusts velocity when pad held, scrolls notes when not held
@solaris76
Copy link
Copy Markdown
Contributor Author

solaris76 commented Dec 15, 2025

You can now hold a note pad and adjust note settings the three encoders. vertical: Velocity, <> Gate & Select: Iteration/Probability.
You can also change seq length with shift + <>. This functionality replicates same functions as per clip view (where relevant) for consistency.

I've removed all the performance controls form Pulse sequencer and now uses the control columns for all of its settings, so far less intimidating and aligns well with step sequencer.

- Replace snprintf with intToString for smaller code size
- Create specialized display functions (displayVelocity, displayGateLength, displayProbability)
- Make isNotePadHeld() and clampValue() inline for performance
- Reduce buffer sizes where possible
- Remove redundant cfunctions.h include (already via functions.h)
…l columns)

- Removed performance control UI (y0, y1, y2, y5, y6, y7) - now handled by control columns
- Kept only stage count (y4) and stage enable/disable (y3) controls
- Removed unused PlayOrder enum (using control column direction values 0-7)
- Removed unused functions: handleNoteSelection, cycleValue, renderRightSideControls, renderPlaybackIndicator
- Removed handler functions: handleClockDividerChange, handlePlayOrderChange, handleTransposeChange, handleOctaveChange, resetPerformanceControls, handleVelocitySpread, handleProbability, handleGateLength
- Updated code to use control columns for transpose, octave, clockDivider, direction
- Added calculateNoteCode() helper to reduce code duplication
- Enabled DIRECTION control type support for pulse sequencer
- Reduced binary size by ~2KB
- Remove redundant performance controls, use control columns exclusively (like step sequencer)
- Add hold note + encoder functionality: velocity (horizontal), gate (vertical), probability/iterance (select)
- Add Shift + horizontal encoder to adjust sequence length (1-8 stages)
- Standardize encoder behavior across both sequencers to match piano roll view interaction patterns
- Optimize PulseSequencerMode::StageData: use uint8_t/int8_t instead of int32_t (saves ~224 bytes per instance, ~512 bytes binary size)
- Standardize string formatting: replace sprintf/snprintf with intToString + memcpy for consistency
- Fix XML save/load: correct offset calculations and array sizes
- Add play order state to XML persistence for both sequencers
- Fix pulse sequencer rendering: inactive stages set to 0 brightness like step sequencer
- Add copyFrom method for proper sequencer data duplication when cloning clips
- Ensure duplicated clips can play immediately with initialized_ flag
@MrHaila
Copy link
Copy Markdown

MrHaila commented Dec 20, 2025

Thanks for all the replies and fixes! Another weekend, another round of testing. I'm trying to focus on digging up bugs and interesting edge cases.

Compliments:

  • The velocity and gate length shortcuts are a great addition! I immediately got a more interesting sequence going.
  • The skip/off mode visual changes have made the step sequencer markedly easier for me to understand at a glance! Some of the muted states are barely visible and actually buggy (odd colors and flickering) when on low brightness, but I assume that's a system bug.
  • Playing around with the different playhead directions is a lot of fun now!

Bugs:

  • In song view, clip row shows notes from piano roll and the piano roll playhead even when clip type is set to step sequencer. Repro by making a new clip, enter some notes, switch to the step sequencer, press "song", press "play". I would ideally see the one-liner clip representation to show step sequencer gates and the step sequencer playhead.
    • Note: I still intuitively feel it surprising that the sequencers would have visually different looking playheads, but it would help to have that difference be represented in all views.
  • Similarly, the arranger view shows piano roll notes even if the clip mode is step sequencer.
  • Not sure if related to this PR (would need to check after this), but in piano roll, pressing multiple empty notes at once will add all notes, but repeating the same input will only remove one of the pressed notes. Repro by trying to enter and remove a chord in piano roll.
  • When stopped, the step and pulse sequencer show the red playhead on step 1. Feels like a bug because the piano roll does not do the same thing. I would expect the play head not to show at all when stopped.
    • Note: the playhead does not show up at all if the first step is set to skipped in step sequencer. I think this is correct.
  • When entering step sequencer from song view, the song mode play head will get stuck on top of the step sequencer. Repro by using the song view to jump between a piano roll and step sequencer clip while playing.
  • After holding a note to edit the probability, the OLED notification never goes away. It's stuck on top. I would expect it to disappear when releasing the held note, like in piano roll.
  • The note iterance does not seem to work. It can be edited (hold a note and rotate "select" clockwise) but notes play as if the sequence is always "1". So "1/2" always plays and "2/2" never plays.
  • The default "+5 transpose" button seems to shift notes up and wrap them around in the current octave (Ab2 + 5 = F2 on Fm scale) instead of setting them to play on the next octave. All kinds of fun and funky possibilities with this kind of auto-inversion, but probably a bug? Does not affect the "+1 octave" button.
  • The note colors do not change depending on the octave of the note, like in piano roll and keyboard view. It would be handy to re-affirm visually that a note is of higher or lower octave when two are side-by-side without having to cross-reference the octave button state. Also, there is no way at the moment to tell apart +1 and +2 octaves, so color would help with that.

UX suggestions:

  • Shift + <> popup text on the OLED only says a number, like "8". Would be nicer if it said what the change is about, so for example "seq length: 8".
  • Press + turn <> is now a no-op. I would ideally like to use it to select the base resolution of the step sequencer, so whether the notes are 16th like default, or maybe 8th or 32nd, etc., so the speed performance controls can then be used on top of the base resolution.
  • The "speed" performance options seem a bit odd. I can select all the way to /64 slower but only *2 faster. Am I holding it wrong if I was looking to make a really fast arp by setting something like speed *8 without touching the tempo?
  • Both "off" and "skipped" gate columns now have a muted background color on all the pads. I would propose only having the muted color on skipped columns as that would look more similar to adjusted clip lengths in song and kit views, where the muted color always means "skip". Should the muted color also match the exact same color used in other views, where it's a brighter?
  • Similarly, setting the sequence length with Shift + <> turns all pads off instead of setting them to muted gray like in other views. Would be slightly more intuitive to use the same visual language.
  • I'd love to have the same muted brightness on notes based on their velocity as in the piano roll.

Of the basic UX now, I think my only major concern is around how the note pitch being displayed while the gate is not "on". I understand you referencing physical gear but I've never actually touched one so unfortunately I can only comment from a synth noob first impressions PoW 🙂

Maybe this is an interesting use case: I jammed around a very simple sequence that combined a few piano roll clips and one step sequencer clip in an infine loop. When switching between the clips after a while, I'm pretty disoriented on what clip is playing what because of the polymeters and how it's easy to forget instrument assignments on the Deluge. In this scenario, seeing only the notes that are active (pic 1)...

Image

...makes it easier for my brain than the same clip but scrolled by two clicks on the up/down encoder (pic 2). Never mind the white pads. That's a stuck playhead from song view.

Image 2

Here, I intentionally shifted all "off" and "skip" notes to the top so they would not be visible (pic 1), leaving only active notes and visually-off pads. I find this simplicity really helpful. In the latter image, I have to look at the top pad of a column and the bottom pad of a column and combine the info from the two to know what the column will sound like, because my eyes read the screen top->bottom instead of bottom->up.

So far, I have not found value in having a visible note be assigned at the same time as the step is "off" or "skipped". Maybe that's just something I don't know how to benefit from because I've never had a hardware step sequencer like this? Looking at this with the context that I have of other Deluge UX, I think I would prefer to get the same functional states by:

  1. Changing the bottom row to only toggle between "skipped/not-skipped" status, defaulting to "not skipped".
  2. Changing the note columns to not have a pitch selected by default. This would be the same as the current "off".
  3. Changing the "press active note pad" action to turn the step "off" and visually hide the note. The column becomes empty of notes.
  4. Changing the "press inactive note pad" to both set the pitch like now, but also set the step to "on" (whether it was "off or "skipped".

This way, interacting with the steps would require less button presses as multiple actions can combine into one press in the case of "set this step to 'on' and 'F2' regardless of its current state". I would argue it also requires less learning because that's how the piano roll interactions work.

...but I fully appreciate that this suggestion is not based on previous experiences with these types of sequencers. Please excuse my ignorance 🙏

And again, thanks for the work on this. I'm having a blast just playing around with it!

ogabrielluiz added a commit to ogabrielluiz/DelugeFirmware that referenced this pull request Mar 19, 2026
…work

Integrates the Lanes generative sequencer as a selectable sequencer mode
within the Sequencer Modes framework (PR SynthstromAudible#4143), available alongside
Step Sequencer and Pulse Sequencer via the Clip Type menu.

- LanesSequencerMode wraps LanesEngine and implements SequencerMode interface
- 8 independent parameter lanes (trigger, pitch, octave, velocity, gate,
  interval, retrigger, probability) with polymetric phasing
- Performance mode toggle via Cross-Screen button for control column access
  (transpose, octave, evolve, randomize, reset, scenes)
- Adaptive evolve: gentle drift at low %, chaotic mutations at high %
- Full playback with gate/retrigger/tie/legato state machine
- Undo/redo via ConsequenceLanesChange snapshots
- Serialization within the sequencer mode XML format
- Lane editor menus (track length, base note, interval range)

Based on PR SynthstromAudible#4143 (sequencer-modes-pr) by @seangoodvibes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants