Yanfei engines and firmware budgets
For sound controls and examples, read the engine guide.
This document records implementation details and firmware budgets.
See the waveform review for live scopes, signal measurements,
the corrected decay/envelope details and the high-note WARP limitation.
This is the first implementation of the twelve-engine profile. ./build-yanfei.sh
builds it; ./build.sh retains the upstream profile for reference. Both write into
build/, so rebuild the desired profile before packaging or emulator comparisons.
Yanfei identifies itself as v1.6.1-y13. Engine additions are
paused for the tracker sequencer work; core8 adds reusable phrases, chains, song sections and row instruments.
The engines and 96 presets are retained; tracker projects use a larger journal.
Y13 adds scrolling over four section pages, a four-bar limit, and repeat/wait per track.
Core11 makes ALL the default tracker view after a restart.
Core10 adds an editable four-track ALL view. SHIFT + UP switches to PHRASE.
Core9 adds the selected row's four DETAIL values to the PHRASE footer.
| Engine |
Eight factory presets |
| ANALOG |
SQR BASS, SAW LEAD, SOFT PAD, JUNO CHORUS, JUPITER SYNC, 303 SQUELCH, MINI ROUND, MS REED |
| NES |
PULSE LD, WAVE BASS, NOISE HIT, FAMI HERO, FAMI LOW, FAMI ARP, 8BIT SNARE, DUNGEON PAD |
| DMG |
HANDHELD, WAVE LEAD, SHORT HIT, POCKET BASS, POCKET BELL, POCKET WIND, 7BIT TOM, LINK LEAD |
| PSG |
BUZZ BASS, PSG CHORD, SEGA HIT, AY BUZZ LEAD, AY ZAP, SEGA SQUARE, SEGA CHORD, SEGA HAT |
| TRIO |
FAT BASS, SYNC LEAD, RING BELL, SID PWM, SID RUBBER, SID SYNC, SID METAL, SID CHOIR |
| FM6 |
TINE EP, FM BASS, PAD, TX RUBBER, DX GLASS, DX MALLET, DX BRASS, DX ORGAN |
| YM |
MD BASS, FM BRASS, METAL BELL, MD SLAP, MD REED, ARCADE LEAD, MD EPIANO, MD CHIME |
| WAVE |
MORPH PAD, GLASS WALK, WAVE SUB, PPG CHOIR, ESQ BRASS, VS AIR, PPG METAL, ESQ REED |
| PHASE |
BRASS, RESO, BELL, CZ BASS, CZ STRINGS, CZ GLASS, CZ ORGAN, CZ WIRE |
| STRING |
PLUCK, DRONE STRING, HARP, KOTO PICK, SITAR BUZZ, ZITHER, CLAVI PLUCK, BOWED WIRE |
| MODAL |
BELL TREE, MARIMBA, HAND DRUM, VIBE KEYS, TOY BELL, GAMELAN, STEEL TINE, SYNTH TOM |
| DRUM |
DRUM KIT, DEEP KIT, TIGHT KIT, ELECTRO KIT, HOUSE KIT, ARCADE KIT, DUB KIT, MINIMAL KIT |
There are 96 factory presets. The first three per engine keep their indices and
sound; five new inspired sounds are appended to each. See the inspired preset
catalog for references, compatibility details and audition
clips. The reference profile retains its original presets.
FM6 retains three compatible SLOT entries; its five new full operator patches
load into OWN. OWN remains 3 and B1..B32 remain 4..35, so stored sounds do not
change meaning. The new FM6 patch travels with projects and user presets.
Existing user files are not rewritten or converted into unrelated engines.
YM and PSG
YM is separate from FM6 and has six voices per part. Its eight presets
use the same saved format as other core sounds, including all operator controls.
EDIT cycles through two main pages, four operator envelope pages, operator levels, four
operator tone pages and AM controls. AR/D1R/D1L/RR/TL and MUL/DT are per operator;
D2R, SSG and KS are shared. The chip ladder DAC behavior is built in. It does not
stream game music, play PCM drums or expose channel-3 mode or CSM timers.
PSG's third EDIT page, CHIP, selects AY or SEGA with knob 1. Pause more than
300 ms between EDIT taps to avoid opening its double-tap shortcut layer. AY preserves the existing buzzer path. SEGA
uses a MAME-derived PSG core, with BUZZ becoming the white/periodic noise mode
and B-RATE becoming stepped VOL. The third factory preset demonstrates Sega noise.
Existing saved PSG sounds stay in AY mode. The core code retains its BSD license
notices; test-only reference cores are not part of the firmware.
PSG HOME controls (core5)
| Chip |
Knob 1 |
Knob 2 |
Knob 3 |
Knob 4 |
| AY |
TONE2 |
N-MIX |
BUZZ |
B-RATE |
| SEGA |
TONE2 |
N-MIX |
NOISE |
TONE |
TONE2 blends the second square tone; N-MIX moves between tones and noise.
AY's BUZZ and B-RATE set its buzzer envelope shape and clock rate; B-RATE
has no effect at FLAT. Sega's NOISE picks white (W) or periodic (P) noise at
HI/MID/LO clock rates, or LNK for the tone-linked clock. TONE sets brightness.
Sega's stepped VOL remains on EDIT > COLOR. N-DIV affects Sega noise only
in a LNK mode. The neutral COLOR page title applies to both chips.
The mode-dependent HOME map also drives MIDI learn, momentary edits and step
locks. Existing sounds, parameter IDs, ranges and preset audio are unchanged;
this is a control/layout update. HOME > LEVELS still controls the four part levels.
WAVE banks
BANK selects four related waves; POS morphs along them. RATE and SCAN move the
position automatically. The five banks are:
| Bank |
Wave corners |
Character |
| BASIC |
Sine, triangle, square, saw |
Familiar oscillator shapes |
| COLOR |
Hollow, glass, octaves, bright glass |
General digital colors |
| PPG |
Nasal, comb, vocal, metal |
Upper harmonics and formant-like peaks |
| ESQ |
Bass, reed, keys, hollow reed |
Hybrid digital synth-style tones |
| VS |
Airy, glass, brass, shimmer |
Vector synth-style pad colors |
These are original harmonic recipes inspired by vintage timbral families. They
use linear scanning through four corners; VS does not add two-dimensional vector
mixing. All four harmonic limits are generated offline, including the new waves.
Core3 adds 24 KiB of tables over core2, with no new RAM buffers or sample-loop work.
The original eight tables are byte-identical and keep bank IDs 0/1. Core2 project,
preset and settings formats are retained; existing saved sounds stay compatible.
Core6 adds factory presets using the same five WAVE banks; no tables are added.
SAMPLE remains a possible later addition, GRAIN second priority, FORMANT/WHEEL
optional, NOISE/SLICE omitted. The upstream implementations remain in source as
references, but are not selectable in the core profile. Link-time elimination and
an empty core sample header remove unused engine descriptors/render paths and the
instrument PCM bank from the target image. Shared noise primitives remain.
Saved data
The profile deliberately uses a fresh namespace: projects 0x59434632, user-bank
magic 0x32435055, preset versions 8/9, settings 0x59435032. Upstream projects,
settings and user banks are refused rather than interpreted using the new IDs.
The internal slots are ANALOG=0, PHASE=2, NES=3, DMG=4, PSG=5, TRIO=6,
WAVE=7, STRING=8, MODAL=9, DRUM=10, FM6=12, YM=13. Slots 1 and 11 are unavailable;
the visible order is the twelve above. Keeping several host IDs avoids unrelated
changes in FM6 and DRUM code. The editor receives names and descriptors from the
firmware. The web editor refreshes engine-specific common descriptors and preserves stable
parameter keys across engines. Core4 keeps core2/core3 saved data compatible;
existing PSG sounds retain CHIP=AY. See OPN core integration for
YM and Sega PSG controls, upstream provenance, licenses and reference tests.
Budget and validation
The upstream baseline app is 511,472 bytes, ordinary RAM 60,984/73,728, pool
328,896/368,640. The core8 app is 428,864 bytes (152,700 bytes free in its app slot),
with ordinary RAM 66,248/73,728 bytes and pool use 345,048/368,640 bytes. Its
13,648-byte active tracker library and fixed project staging buffer fit the
existing guards; see tracker storage and validation.
The WAVE tables total exactly 40,960 bytes. YM, PSG and STRING/MODAL share the existing
12,888-byte per-part workspace; no voice struct or pool expansion was needed.
Preserve the build guards: 4 KiB ordinary RAM and 8 KiB pool free.
The core DSP uses fixed point with no audio-path allocation. Table interpolation
and adjacent-wave interpolation are separate. Harmonic limits crossfade before
their partials reach Nyquist; selection and
brightness run at block rate. Phase warp tapers at high pitches. This reduces
aliasing without oversampling or extra RAM; it is not an alias-free guarantee.
NES/DMG/AY are inspired instruments. YM and Sega PSG use tested chip cores,
with instrument controls, rate conversion and the common mixer/effects around them. DMG's DUTY descriptor uses four groups of four values
within the same 0..15 parameter range as WAV# so switching modes keeps a valid
stored value and editor range.
export JIELI_TOOLCHAIN=/workspace/yanfei/build/jieli/toolchain
export AC79_SDK=/workspace/yanfei/build/ac79-sdk
./build-core.sh
sh tests/run_core_tests.sh
python3 tests/core_budget.py
sh firmware/engines/tests/run.sh # existing 108 golden renders remain unchanged
source /workspace/shared/emsdk/emsdk_env.sh
FELUCCA_CORE=1 sh web/emu/build.sh
cc -DFELUCCA_CORE=1 -fwrapv -O2 -ffp-contract=off -w -Ibuild/gen -Ifirmware/src \
-o build/emu/core_native web/emu/native_check.c -lm
build/emu/core_native build/emu/core_native.f32
node web/emu/emu_test.mjs build/emu/felucca.wasm build/emu/core_native.f32
The core test renders every factory preset, checks new-engine releases, checks
foreign-data rejection and current-data round trips, exercises concurrent parts
and engine workspace switching. The standalone chip test checks noise periods,
distinct envelope clocks and 128 parameter-extreme/low/high-note renders.
tests/core_budget.py retains upstream cost limits for shared DSP and uses
tests/core_target_budget.txt for new functions. These initial cost baselines and
second-core split estimates are not hardware timing claims.
The core builds explicitly use -fwrapv: existing fixed-point FM6 phase
accumulators rely on signed wrapping. Sanitizer runs retain overflow checks with
that defined behavior, disabling only shift checks for existing fixed-point DSP.
The standalone chip/WAVE tests also pass without -fwrapv.
GCC 14.2 at -O1 miscompiles the existing dynamic custom-palette count: disassembly
reuses a previous menu_n result across cpal_store. The same test passes at
-O2 and with -fno-ipa-pure-const; the broader host review uses the latter.
This workaround is for the host compiler, not a firmware source change. The target
and emulator use Clang. See the review record for checks and limits.
Next stages
DRUM still has its existing synthesis styles. The proposed 808 redesign, 909
hybrid and 707/DMX PCM kits are not implemented or renamed into existence here.
They need sound-design work, sample provenance and separate asset budgets.
Sega PSG mode is included; WAV import remains deferred. Hardware testing is
still required for audio deadlines, latency, USB behavior and the sound of dense
parts with FX and long releases. This environment has not flashed a device.