Yanfei tracker sequencer
For operating instructions, read the user guide.
Use the quick reference for the controls.
This document contains implementation and validation details.
Four-page section editing (y13)
New sections use a fixed length of one through four bars. Four bars are 16
musical beats. At 1/16 division and 16-row phrase lengths, a section spans 64 rows.
ALL and detailed PHRASE scroll over four 16-row pages. The existing phrases,
chains and working caches remain the storage model. Reading a missing page does
not allocate a phrase. Editing one allocates it from the shared 32-phrase bank.
Reference copy/paste shares a phrase; clone makes independent notes and automation.
A section stores two bytes: beats (0 AUTO, 1..16 timed) and a four-track repeat
mask. The UI offers whole bars. A master sixteenth clock uses the transport's
sample advance, including external MIDI clock. It resets all track schedulers at
a common boundary. Shorter tracks repeat their chains or wait silently. An
internal missing page consumes 16 silent rows at the track's division. Longer
chains are cut at the fixed boundary. AUTO retains the previous chain barrier.
PLAY in section editing loops the selected section; SONG advances the arrangement.
Recording and note edits during arrangement playback remain disabled.
The project payload is 15,792 bytes, up by 64 bytes. Version 2 appends section
settings after the unchanged version 1 body. The journal and backup paths read
both lengths and verify CRCs over the stored length. Old projects use AUTO;
rename or save upgrades the envelope while preserving notes and metadata.
The flash allocation and eight-voice budget remain unchanged.
The y13 app is 436,192 bytes, up by 4,836 bytes from y12. Ordinary RAM is
66,312 of 73,728 bytes. The pool uses 345,112 of 368,640 bytes. Both RAM totals
increase by 64 bytes. The combined static interrupt/keyboard/step/section cost
is 6,634 against the original 8,285 baseline and its unchanged tolerance.
Screen lint passes 13,200 scenes. Browser checks cover all four pages, row 3F,
reference cloning, repeat/wait and section playback. Device audio deadlines
remain unmeasured. See the user guide for controls and the build report for logs.
Yanfei name (y12)
The custom firmware is named Yanfei. The boot screen, ABOUT page, serial
console, editor identity and USB port names use that name. The source QR
links to github.com/izumoe/yanfei. Upstream credits and licence notices remain.
Projects, presets, backups, protocol command IDs and flash layout are unchanged.
Build with build-yanfei.sh. The package is yanfei.fwsc.
The earlier core11 build is the baseline for this name change.
The app is 431,356 bytes, an increase of 24 bytes. Ordinary RAM remains
66,248 bytes and the pool remains 345,048 bytes. The original interrupt
budget passes at 6,531 weighted instructions. The update package is 50 bytes
smaller because the USB names in the loader are shorter.
Core11 default view
The tracker starts in ALL after a fresh boot. SHIFT + UP opens detailed PHRASE.
Leaving the tracker and returning keeps the current view during the session.
This changes the initial UI state only. Project, sound and playback formats
remain unchanged from core10.
The app grows by 16 bytes. Ordinary RAM, the pool, and the interrupt instruction
budget stay unchanged. Fresh-boot emulator checks verify the default and
return navigation.
Core10 four-track overview
SHIFT + UP toggles PHRASE and ALL (view 3). The existing CHAIN and SONG
shortcuts stay available. ALL uses four 54-pixel columns and sixteen rows.
Each cell shows a pitch, two pitches, an exact chord label, or MULTI.
The chord matcher compares pitch-class sets against a small fixed table in
main-loop display code. It accepts inversions and octave doubling. It tries
the bass as root first for ambiguous sets. Drum summaries use kit-aware lane
abbreviations. Neither summaries nor transposition change the audio format.
ALL edits the selected track's working phrase through the existing entry,
clipboard, undo and instrument metadata paths. Pitch changes transpose the
whole stored chord, with group clamping at 0 and 127. Drum editing uses note
entry or the detailed lane view. PLAY uses the existing TS_ALL transport.
The display shows independent track playheads, including arrangement playback.
There is no additional framebuffer, project payload, engine workspace or audio
callback work. The format remains compatible with core8 and core9 projects.
The core10 app is 431,316 bytes, an increase of 2,704 bytes from core9.
Ordinary RAM remains 66,248 bytes. The pool remains 345,048 bytes.
The original target interrupt budget passes at 6,531 weighted instructions.
Display lint passes 9,200 scenes across ten palettes and all display styles.
Control tests run under address and undefined-behavior sanitizers. Browser
checks exercise actual WASM note entry, row edits, drum entry and playback.
The existing tracker library, backup and all-engine audio regressions pass.
Device audio deadlines have not been measured here.
Core9 display update
PHRASE has four compact fields in its existing 16-pixel footer: CH (chance or
condition), RT (ratchet), ND (nudge), and VEL (velocity). These fields show the
selected row, including when the playhead is elsewhere. Inapplicable values are
dim. Messages temporarily replace the fields, including row-gate feedback.
The sixteen-row layout and engine sound-knob controls remain the same.
Idle screens draw nothing. A cursor move redraws at most two 12-pixel rows and
the 16-pixel footer. A selected-row value edit redraws its row and footer;
an edit on another row leaves the footer alone. Layout lint adds chance/condition,
nudge, ratchet, accent, and inactive-row cases, for 7,280 scenes in total.
Core9 uses the same project and preset formats as core8.
The core9 app is 428,612 bytes. Ordinary RAM and pool use are unchanged.
The control reference is Ketch,
reviewed at 87ff579. This firmware implements the keypad workflow around our
engines, four-note chords, eight drum lanes and existing sound automation.
Phrases, chains and song sections
Four tracks play simultaneously, sharing the existing eight-voice budget.
Each project has a fixed library:
| Item |
Limit |
Contents |
| Phrase |
32 shared phrases, 1–16 rows each |
Four-note chords or eight drum lanes, row instruments, gates and step settings |
| Chain |
16 chains, 16 links each |
Phrase references with −24..+24 semitones transpose |
| Song |
32 section rows × four tracks |
One chain reference per track per section |
| Instrument |
16 shared sounds |
Engine, sound parameters and the full FM6 patch |
| Automation |
128 unique events/locks across the project |
Sparse events attached to phrase rows |
IDs display in hexadecimal: P00..P1F, C00..C0F, instruments 00..0F.
A/B/C sections can be represented by song rows using different chains; there
are no additional named section banks. Paste reuses an existing item. Clone
creates a variation: a cloned phrase copies notes, instrument references, gates
and automation; its instruments are still shared. A cloned chain copies its
sequence and transpose values while retaining references to the same phrases.
Clone a phrase within that chain when its notes should differ too.
To make a variation, copy a chain reference to another song cell, clone that
chain, open it and clone whichever phrases need different notes. The original
section keeps its original phrases. To introduce another sound, select an unused
I number on a phrase row (it starts as a copy of the selected sound), then use
the normal preset/engine pages to edit it. Reusing an I number shares that sound.
PLAY on PHRASE loops the selected track. PLAY on CHAIN loops that chain on
the selected track. PLAY on SONG, or SHIFT+PLAY, plays the arrangement from
the selected song row. Fixed sections end at their set length; each track repeats
or waits. AUTO waits for all tracks and skips empty sections and links.
The song stops at its end. HOME/panel PLAY outside the
tracker loops the four currently selected phrases. The normal clock and MIDI
transport remain available. Chain/song editing and recording require stopping.
Keybed controls
| Keys |
Action |
| F3 / A3 |
Left / right |
| G3 / G#3 |
Down / up |
| D5 |
SHIFT |
| E5 |
PLAY / stop |
| F5 |
OPTION |
| G5 |
EDIT |
| SHIFT + left |
Phrase → chain → song |
| SHIFT + right |
Song → selected chain → selected phrase; from phrase, instrument editing |
| OPTION + left/right |
Select track |
| OPTION + up/down |
Change section page; in separate phrase mode select phrase ID; in CHAIN select chain ID |
| EDIT tap |
Insert last note into an empty cell; copy a filled note/value; toggle drum hit; create/copy a library reference |
| EDIT + arrows |
Edit selected value; notes move by semitone/octave |
| OPTION + EDIT |
Clear selected cell/reference |
| SHIFT + OPTION |
Copy phrase row, chain link, or whole four-track song section |
| SHIFT + EDIT |
Paste row/link/section; EDIT on a filled song cell copies just that reference |
| SHIFT + OPTION + EDIT |
Clone the phrase referenced by a chain cell, or chain referenced by a song cell |
| EDIT + PLAY |
Audition cursor row while stopped, on PHRASE |
| SHIFT + PLAY |
Play song from selected section |
EDIT on an empty chain cell allocates a phrase. EDIT on an empty song cell
allocates an unused chain. PRESETS or EDIT+arrows can select an existing ID.
An exhausted library reports FULL; it never overwrites another phrase to make
room. Undo removes a newly created reference while retaining its library item.
Notes and row parameters
Melodic rows display four notes, instrument (I), velocity, chance/condition and
ratchet. Drum rows display eight lanes, I and velocity; DETAIL supplies chance,
ratchet and nudge. Values other than pitch apply to the whole row/chord.
Drum lane accents are independent and play at velocity 127.
| Parameter |
Range / behavior |
| Pitch |
MIDI 0–127, up to four notes per row |
| Instrument |
00..0F; .. inherits the latest earlier instrument, or the phrase's default |
| Velocity |
1–127; imported zero uses the existing default 96 |
| Chance / condition |
0–100%, or cycle conditions 1:2..4:4, FILL and !FILL |
| Ratchet |
1–4 evenly spaced triggers in a step |
| Nudge |
−8..+7 sixteenths of a step; QUANTIZE OFF, without ratchet |
| Gate |
HOLD, or 1..128 units of a step (displayed as a percentage) |
| Ties |
Extend an entire chord across following rows |
| Locks / automation |
Existing eligible engine/envelope/mix/FX parameters through STEP and AUTOMATION |
A blank row does not trigger or cut a note. HOLD sustains until a new note,
an explicit OFF, section completion or stop. HOLD does not imply pitch glide.
Finite gates release earlier; a following tie extends them. F#3 in NOTE mode
writes OFF; EDIT+F#3 writes a tie. Clearing a note cell leaves a blank.
Ratchets use a finite gate within each subdivision; HOLD maps to the full
subdivision for repeated hits. Existing slide flags remain supported.
Instrument changes use the existing short engine fade and workspace handoff;
release tails do not accumulate independent engine instances. Instrument edits
are shared across all references. Track timing/routing are not replaced by a
sound change. Live knob tweaks during playback are temporary; stop restores the
selected edit instrument. Dedicated tracker pitch-slide/vibrato/arpeggio command
columns are not added in this build; existing engines, modulation, locks and
ratchets remain available.
Panel controls and undo
| Control |
Action |
| REC |
NOTE entry → ARM for live recording → NAV |
| A#3..C#5 in NOTE mode |
Play/write a chord; advance once all note keys are released |
| SELECT |
Move row cursor |
| EDIT + SELECT |
Extend/shorten note with ties |
| OPTION + SELECT |
Set cursor row gate; zero = HOLD; footer shows value |
| PRESETS |
Edit selected cell without loading another sound |
| ALGORITHM |
Select track |
| KNOB 1–4 |
Current engine's HOME sound controls |
| HOME tap |
Toggle playhead following |
| HOME held |
Settings menu |
| GLO |
Open tracker SONG once library is active |
| GLO held + SELECT |
Tempo |
| SEQ tap |
Tracker, STEP, DETAIL, AUTOMATION |
| SAVE |
Existing save pages; PROJECT includes the entire library |
| SAVE held |
One-gesture undo/redo, including row instrument/gate/OFF metadata |
Navigation silences the keybed. NOTE mode sounds only the middle sixteen keys;
modifiers remain silent. Live recording writes only the running play position.
Row paste includes instrument, gate and OFF along with notes/step settings;
automation stays attached to the destination. Phrase clone includes automation.
Undo of a pattern edit requires returning to its phrase to avoid applying a
snapshot to another phrase. Reference and instrument-cell edits also have undo.
Storage, compatibility and budgets
On first entry to TRACKER while stopped, all four working 64-step patterns are
split into sixteen phrase pages, preserving even notes outside the active LEN.
Four initial chains preserve each track's active length. Existing notes, chords,
drum hits, chance/ratchet/nudge, automation and complete FM6 patches are kept.
Imported rests become explicit OFFs and existing gates are copied to their rows,
so conversion does not change their articulation. New phrases start blank.
Existing saved-project song arrangements remain readable through the legacy
path before activation; they are not automatically translated into the new song
library. Save a converted project into another slot to retain its original.
The new store has four manual project objects and one restore-last object.
Each uses two 16 KiB copies in 0xA0000..0xC7FFF, the first two otherwise unused
sample slots. The third sample slot (0xC8000..0xDBFFF), user presets, FM6 banks,
settings and OTA are outside this allocation. Core sample upload/erase refuses
the two reserved slots. SAMPLE remains deferred.
The version 2 payload is 15,792 bytes, including 64 bytes of section settings,
the legacy 3,840-byte base
project and compact instrument parameters. Writes erase only the alternate copy,
verify the body and commit its CRC-protected header last. Loading fully validates
both copies and can fall back from a torn or semantically invalid newer copy.
Erase commits a tombstone. Rename, restore-last and full browser backups preserve
the entire library. Legacy core projects remain loadable; new tracker libraries
require core8; version 2 section settings require y13. The desktop sequencer still exposes the compatible working steps;
tracker-only fields and arrangement are edited on the device/emulator.
The active library is 13,648 bytes of ordinary RAM. Project staging and undo use
the fixed pool; there are no heap allocations or unbounded audio-path walks.
Target builds retain at least 4 KiB ordinary RAM and 8 KiB pool headroom. Exact
build totals and checks are recorded alongside the firmware in build/yanfei13.
The original core8 build uses 428,864 bytes of app space, 66,248/73,728 bytes ordinary RAM,
and 345,048/368,640 bytes of the pool. The combined static ISR/keyboard/step
dispatch cost is 6,531 against the original 8,285 baseline and its unchanged
tolerance; the out-of-line step and keyboard work is charged back into that guard.
Verification
tests/run_core_tests.sh covers the compatibility editor, full migration,
shared edits and automation, clone/reference undo, note articulation, arrangement
barriers, transposition, all factory sounds, journal failure/fallback, and the
full backup protocol. Section tests exercise all 64 rows, common timed boundaries,
repeat/wait, silent gaps, shared pages and clone undo. An unchanged y12 fixture
checks old project import, journal load and rename upgrade. NOR tests inject power cuts through body/header writes and
erases, checking canaries outside the reserved region. Screen lint exercises
5,360 scenes across palettes, styles, LARGE settings, engines and library views.
tools/capture_tracker.py drives the actual WASM firmware panel, captures the
screens and checks a save/reload in a fresh instance. Host/sanitizer checks and
static target budgets supplement these tests; device audio deadlines and physical
control ergonomics still need FM-1 testing.