Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

notepat + install: decay via kill fade, rescue unmountable ESP

notepat:
- Attack zero mode now uses 3ms ramp (was 1ms) to prevent onset pop.
- Decay mode now controls the RELEASE envelope time via sound.kill()'s
fade parameter. Previously the synth's decay param only applied to
finite-duration notes, but sustained melodic notes have infinite
duration so decay never fired. stopSoundKey() now defaults its fade
argument to currentDecay() when no explicit fade is passed.
- Decay values bumped: zero=15ms, short=100ms, long=800ms.

install:
- When the ESP partition exists but can't be mounted as vfat (because a
prior install ran sfdisk successfully but mkfs never completed),
attempt a rescue format: BLKFLSBUF + drop_caches + mkfs.vfat, then
retry mount. Only runs on partition 1 and only if it's >= 512MB.
Fixes "no internal FAT32/ESP partition found" when the nvme ESP was
repartitioned but never formatted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+61 -5
+14 -3
fedac/native/pieces/notepat.mjs
··· 566 566 const DECAY_MODES = ["zero", "short", "long"]; 567 567 let attackModeIdx = 1; // default: short 568 568 let decayModeIdx = 1; // default: short 569 - const ATTACK_VALUES = { zero: 0.001, short: 0.005, long: 0.06 }; 570 - const DECAY_VALUES = { zero: 0.01, short: 0.1, long: 0.9 }; 569 + // Zero still has a tiny ramp (~3ms) to avoid click/pop transients at 570 + // note onset. The audio engine needs at least a short attack to settle 571 + // the biquad LPF on noise-type waveforms without a discontinuity. 572 + const ATTACK_VALUES = { zero: 0.003, short: 0.02, long: 0.12 }; 573 + // Decay = the release-time fade when a key is lifted (sustained notes 574 + // have infinite duration, so the synth's own decay param never fires — 575 + // we pass this through as the `fade` arg to sound.kill()). 576 + const DECAY_VALUES = { zero: 0.015, short: 0.1, long: 0.8 }; 571 577 let envelopeNotice = null; // { text, icon, until } — transient overlay 572 578 573 579 // Arrow-key octave offsets for left and right grids (added to base `octave`) ··· 1527 1533 pushUsbMidiRecent(">", entry.note, entry.octave); 1528 1534 } 1529 1535 1530 - function stopSoundKey(key, sound, system, fade = 0.08) { 1536 + function stopSoundKey(key, sound, system, fade) { 1531 1537 const entry = sounds[key]; 1532 1538 if (!entry) return; 1539 + // Default fade to the user-selected decay mode (zero/short/long). For 1540 + // sustained melodic notes the synth's own `decay` param never fires 1541 + // because duration is infinite — the release envelope is controlled 1542 + // here via the kill fade duration. 1543 + if (fade === undefined) fade = currentDecay(); 1533 1544 if (entry.compositeVoices) { 1534 1545 for (const voice of entry.compositeVoices) sound?.kill?.(voice, fade); 1535 1546 } else {
+47 -2
fedac/native/src/ac-native.c
··· 1174 1174 // Try mounting as FAT (ESP is always FAT32) 1175 1175 ac_log("[install] trying %s\n", devpath); 1176 1176 if (mount(devpath, "/tmp/hd", "vfat", 0, NULL) != 0) { 1177 - ac_log("[install] mount failed: %s (errno=%d)\n", devpath, errno); 1178 - continue; 1177 + int mount_errno = errno; 1178 + ac_log("[install] mount failed: %s (errno=%d)\n", devpath, mount_errno); 1179 + // If the partition exists but has no filesystem (e.g. a prior 1180 + // sfdisk created it but mkfs never succeeded), try to format 1181 + // it now. Only attempt this on the first partition (which is 1182 + // the ESP slot) and only if the partition is large enough. 1183 + if (p == 1) { 1184 + long long part_bytes = 0; 1185 + int pfd = open(devpath, O_RDONLY | O_CLOEXEC); 1186 + if (pfd >= 0) { 1187 + unsigned long long sz = 0; 1188 + if (ioctl(pfd, BLKGETSIZE64, &sz) == 0) part_bytes = (long long)sz; 1189 + close(pfd); 1190 + } 1191 + long part_mb = (long)(part_bytes / 1048576LL); 1192 + ac_log("[install] %s size=%ldMB — try format to rescue unmountable partition\n", 1193 + devpath, part_mb); 1194 + if (part_mb >= 512) { 1195 + // Flush buffer cache, then mkfs 1196 + int fpfd = open(devpath, O_RDONLY | O_CLOEXEC); 1197 + if (fpfd >= 0) { ioctl(fpfd, BLKFLSBUF); close(fpfd); } 1198 + system("echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true"); 1199 + sync(); 1200 + usleep(500000); 1201 + char mkfs_cmd[256]; 1202 + snprintf(mkfs_cmd, sizeof(mkfs_cmd), 1203 + "mkfs.vfat -F 32 -n AC-NATIVE %s 2>&1", devpath); 1204 + int mkrc = system(mkfs_cmd); 1205 + ac_log("[install] rescue mkfs rc=%d\n", mkrc); 1206 + if (WIFEXITED(mkrc) && WEXITSTATUS(mkrc) == 0) { 1207 + usleep(500000); 1208 + if (mount(devpath, "/tmp/hd", "vfat", 0, NULL) == 0) { 1209 + ac_log("[install] rescue format + mount OK\n"); 1210 + // Fall through to normal install flow below 1211 + } else { 1212 + ac_log("[install] rescue mount still failed\n"); 1213 + continue; 1214 + } 1215 + } else { 1216 + continue; 1217 + } 1218 + } else { 1219 + continue; 1220 + } 1221 + } else { 1222 + continue; 1223 + } 1179 1224 } 1180 1225 1181 1226 // Create EFI boot directories