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(), which means the JACK process callback started firing with the new buffer size while the old NAM subprocess was still running at the old block size. The pipe read/write byte counts desynchronized, causing NAMEngineProcess.process() to return audio_block as passthrough (direct input / DI signal) — every subsequent callback showed dry audio. Fix: reload the NAM engine with the correct block size BEFORE restarting the JACK client. Now when the process callback fires, the NAM subprocess is already ready with the matching block size.
This commit is contained in:
+44
-5
@@ -1051,6 +1051,29 @@ class WebServer:
|
||||
"current": nam.current_model.name if nam.current_model else None,
|
||||
}
|
||||
|
||||
@app.get("/api/nam/engine")
|
||||
async def get_nam_engine(channel: str = "guitar"):
|
||||
"""Get current NAM engine mode."""
|
||||
_pm, _pl, nam, _ir = self._channel_deps(channel)
|
||||
if not nam:
|
||||
raise HTTPException(status_code=503)
|
||||
mode = getattr(nam, 'engine_mode', 'cpp')
|
||||
return {"engine_mode": mode}
|
||||
|
||||
@app.post("/api/nam/engine")
|
||||
async def set_nam_engine(data: dict, channel: str = "guitar"):
|
||||
"""Switch NAM engine between 'cpp' and 'pytorch'."""
|
||||
_pm, _pl, nam, _ir = self._channel_deps(channel)
|
||||
if not nam:
|
||||
raise HTTPException(status_code=503)
|
||||
mode = data.get("engine_mode", "cpp")
|
||||
if mode not in ("cpp", "pytorch"):
|
||||
raise HTTPException(status_code=400, detail="engine_mode must be 'cpp' or 'pytorch'")
|
||||
ok = nam.set_engine(mode)
|
||||
if not ok:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to switch to {mode} engine")
|
||||
return {"ok": True, "engine_mode": mode}
|
||||
|
||||
@app.post("/api/models/load")
|
||||
async def load_model(data: dict, channel: str = "guitar"):
|
||||
"""Load a NAM model by path for the given channel."""
|
||||
@@ -1486,12 +1509,17 @@ class WebServer:
|
||||
logger.warning("jack_client.stop() failed (expected if JACK was mid-callback)")
|
||||
|
||||
# Start JACK with new parameters
|
||||
ok = audio_sys.start_jack(timeout=10)
|
||||
# Disable auto_connect temporarily — fx_in/fx_out ports don't
|
||||
# exist until jack_client.start() recreates the JACK client below
|
||||
saved_auto_connect = audio_sys.config.auto_connect
|
||||
audio_sys.config.auto_connect = False
|
||||
ok = audio_sys.start_jack(timeout=15)
|
||||
audio_sys.config.auto_connect = saved_auto_connect
|
||||
if not ok:
|
||||
# Rollback on failure
|
||||
audio_sys.config.profile = old_key
|
||||
logger.warning("JACK restart failed — attempting rollback to %s", old_key)
|
||||
audio_sys.start_jack(timeout=10)
|
||||
audio_sys.start_jack(timeout=15)
|
||||
if jack_client:
|
||||
try:
|
||||
jack_client.start()
|
||||
@@ -1509,6 +1537,13 @@ class WebServer:
|
||||
except Exception as e:
|
||||
logger.warning("jack_client.start() failed after profile switch: %s", e)
|
||||
|
||||
# Reconnect FX ports now that pipeline's JACK client is alive
|
||||
if saved_auto_connect:
|
||||
try:
|
||||
audio_sys.connect_fx_ports()
|
||||
except Exception as e:
|
||||
logger.warning("connect_fx_ports() failed after profile switch: %s", e)
|
||||
|
||||
# Sync NAM engine block size
|
||||
nam_host = self.deps.nam_host
|
||||
if nam_host and hasattr(nam_host, 'set_block_size'):
|
||||
@@ -1751,7 +1786,7 @@ class WebServer:
|
||||
return {"online": ok}
|
||||
|
||||
@app.get("/api/models/tonedownload/search")
|
||||
async def tonedownload_search_models(q: str = "", page: int = 0, arch: str = ""):
|
||||
async def tonedownload_search_models(q: str = "", page: int = 0, arch: str = "", gear: str = "", sort: str = "created_at.desc"):
|
||||
"""Search Tone3000 for NAM models."""
|
||||
try:
|
||||
client = await self._get_tonedownload()
|
||||
@@ -1765,10 +1800,11 @@ class WebServer:
|
||||
},
|
||||
)
|
||||
arch_val = arch.strip() or None
|
||||
gear_val = gear.strip() or None
|
||||
if not q.strip():
|
||||
results = await client.get_trending_models(arch=arch_val)
|
||||
results = await client.get_trending_models(arch=arch_val, gear=gear_val)
|
||||
else:
|
||||
results = await client.search_models(q.strip(), page=page, arch=arch_val)
|
||||
results = await client.search_models(q.strip(), page=page, arch=arch_val, gear=gear_val, sort=sort)
|
||||
return {
|
||||
"results": [
|
||||
{
|
||||
@@ -1786,9 +1822,12 @@ class WebServer:
|
||||
"pack_name": r.pack_name,
|
||||
"architecture": r.architecture,
|
||||
"created_at": r.created_at,
|
||||
"downloads": r.downloads,
|
||||
"likes": r.likes,
|
||||
}
|
||||
for r in results
|
||||
],
|
||||
"page": page,
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning("Tone3000 model search failed: %s", e)
|
||||
|
||||
Reference in New Issue
Block a user