fix: move NAM block size sync before JACK client restart
The profile change handler was calling nam_host.set_block_size() AFTER jack_client.start(), creating a race where the JACK callback fired with the new buffer size while the old NAM subprocess was still running at the old block_size. Pipe byte counts desynced => NAM returned passthrough. + also: auto_connect disable during restart, connect_fx_ports reorder, Tone3000 gear/sort/pagination params, NAM engine switch API endpoints
This commit is contained in:
@@ -25,7 +25,7 @@ import yaml
|
||||
from src.system.audio import AudioConfig, AudioSystem, JackAudioClient, _jack_is_running
|
||||
from src.system.defaults import ensure_defaults_exist
|
||||
from src.dsp.pipeline import AudioPipeline
|
||||
from src.dsp.nam_engine_host import FastNAMHost
|
||||
from src.dsp.nam_router import NAMEngineRouter
|
||||
from src.dsp.ir_loader import IRLoader
|
||||
from src.presets.manager import PresetManager
|
||||
from src.presets.types import Channel, MIDIMapping, Preset
|
||||
@@ -69,6 +69,7 @@ class PedalApp:
|
||||
|
||||
def __init__(self, config_path: Path = DEFAULT_CONFIG_PATH) -> None:
|
||||
self._config = load_config(config_path)
|
||||
self._config_path = config_path
|
||||
|
||||
# ── Runtime state ──────────────────────────────────────────────
|
||||
self._running = False
|
||||
@@ -79,7 +80,7 @@ class PedalApp:
|
||||
self.audio_config: AudioConfig | None = None
|
||||
self.audio_system: AudioSystem | None = None
|
||||
self.jack_audio: JackAudioClient | None = None
|
||||
self.nam_host: FastNAMHost | None = None
|
||||
self.nam_host: NAMEngineRouter | None = None
|
||||
self.ir_loader: IRLoader | None = None
|
||||
self.pipeline: AudioPipeline | None = None
|
||||
self.presets: PresetManager | None = None
|
||||
@@ -124,6 +125,8 @@ class PedalApp:
|
||||
output_device=acfg.get("output_device", "hw:0,0"),
|
||||
jack_enabled=acfg.get("jack_enabled", True),
|
||||
auto_connect=acfg.get("auto_connect", True),
|
||||
period=acfg.get("period"),
|
||||
rate=acfg.get("rate"),
|
||||
)
|
||||
self.audio_system = AudioSystem(self.audio_config)
|
||||
self.audio_system.setup_i2s(reboot_hint=True)
|
||||
@@ -134,7 +137,7 @@ class PedalApp:
|
||||
|
||||
# ── 2. DSP pipeline (NAM + IR + FX chain) ────────────
|
||||
block_size = self.audio_config.latency_profile["period"]
|
||||
self.nam_host = FastNAMHost(block_size=block_size)
|
||||
self.nam_host = NAMEngineRouter(block_size=block_size)
|
||||
self.ir_loader = IRLoader()
|
||||
self.pipeline = AudioPipeline(nam_host=self.nam_host, ir_loader=self.ir_loader)
|
||||
self.nam_host.warm_up()
|
||||
@@ -251,6 +254,8 @@ class PedalApp:
|
||||
ir_loader=self.ir_loader,
|
||||
audio_system=self.audio_system,
|
||||
jack_audio=self.jack_audio,
|
||||
config=self._config,
|
||||
config_path=self._config_path,
|
||||
),
|
||||
host="0.0.0.0",
|
||||
port=80,
|
||||
@@ -681,6 +686,29 @@ def main() -> int:
|
||||
|
||||
Returns exit code 0 on clean shutdown, 1 on boot failure.
|
||||
"""
|
||||
# Lock process memory early to prevent page faults in RT callback
|
||||
try:
|
||||
import ctypes
|
||||
libc = ctypes.CDLL('libc.so.6')
|
||||
# MCL_CURRENT | MCL_FUTURE = 1 | 2 = 3
|
||||
if libc.mlockall(3) == 0:
|
||||
logger.info("mlockall() OK — process memory locked")
|
||||
else:
|
||||
logger.warning("mlockall() failed — check LimitMEMLOCK in systemd unit")
|
||||
except Exception as exc:
|
||||
logger.warning("mlockall() not available: %s", exc)
|
||||
|
||||
# Set CPU governor to performance for stable RT audio
|
||||
try:
|
||||
for c in range(4): # RPi 4B has 4 cores
|
||||
gov_path = f"/sys/devices/system/cpu/cpu{c}/cpufreq/scaling_governor"
|
||||
if os.path.exists(gov_path):
|
||||
with open(gov_path, "w") as f:
|
||||
f.write("performance")
|
||||
logger.info("CPU%d governor set to performance", c)
|
||||
except Exception as exc:
|
||||
logger.warning("Could not set CPU governor (non-root?): %s", exc)
|
||||
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
|
||||
Reference in New Issue
Block a user