Repository navigation
Release 2.2.0
🚀 What’s New in 2.2.0
Lets a note keep the noise period and the continuous pulse duty it authored, even when the Nes or Hybrid sound profile would otherwise overwrite them. Curated percussion and custom duty values stay expressible under any profile, and the default output remains byte-identical.
🔊 Note-Pinned Character
- Noise Period Under NES Profiles: Adds
InstrumentPreset::noisePeriodModewithNoisePeriodMode::Note.NesandHybridarm the NES period LUT, which used to retune a noise voice to a one-sample clock; a note can now keep its ownnoisePeriod, so a kick authored with a 60-sample body stays a kick instead of becoming white hiss. - Continuous Pulse Duty: Adds
InstrumentPreset::pulseDutyModewithPulseDutyMode::Continuous. A static duty is no longer snapped to one of the four NES patterns, so values a caller can already express, such as 30 % or 20 %, survive the profile. - Per Note, Not Per Slot: Both requests resolve on note-on and leave the slot clean, so the next note on that voice gets the profile character again. Neither writes a per-voice override.
🔧 Changed
- Preset Layout:
sizeof(InstrumentPreset)grows from 72 to 76 bytes, entirely from trailing padding.sizeof(AudioChannel),sizeof(AudioCommand),sizeof(AudioEvent)and bothsizeof(ApuCore)figures (13,344 host and 13,368 test build) are unchanged, because the two requests reach the character hook as parameters instead of being stored per voice.
🧪 Testing & Tools
- Character Regression Tests: Adds 13 cases covering the pinned period, the frequency-derived path, no leakage into the next note, a voice pin outranking the note, PULSE-only duty scope and
Legacyinertness.test_apu_coremoves from 210 to 223 cases. - Default-Path Matrix: A 15-scenario comparison against 2.1.0, covering three profiles, both duty and noise paths,
nesAccurateand two-note sequences, reproduces identical PCM hashes and identical slot state. - Independent Verification: A separate review of the change reported no blockers; the two defects it found are fixed before this release.
📌 Compatibility Notes
- Default Output Unchanged: With the new fields at their defaults,
Legacy,NesandHybridrender byte-identical PCM. None of the reference fixtures was regenerated. - Source Compatible, Rebuild Required: The fields are appended after
envelopeCurve, so existing 17-value positionalInstrumentPresetliterals keep their meaning. Consumers must rebuild against 2.2.0. - Voice Pins Still Win:
setVoiceNesNoiseLutMode()andsetVoicePulseDutyMode()outrank the note-level request, exactly as they already outrank an animated duty. - Consumer Pin: The engine's
^2.0.0range already resolves 2.2.0 with no manifest change. The Tool Suite needs>= 2.2.0to use the new fields.