feat: add automatic master volume and mute state preservation across WirePlumber restarts in apply.sh

This commit is contained in:
mynameisdeleted
2026-09-01 09:09:45 -04:00
parent d22bbfd325
commit 2bfa50b792
2 changed files with 67 additions and 29 deletions

View File

@@ -97,6 +97,19 @@ if [ "$FORCE" -eq 0 ]; then
fi
fi
# --- preserve master volume --------------------------------------------
SAVED_VOL=""
IS_MUTED=0
if have wpctl; then
VOL_OUT="$(wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null || true)"
if [ -n "$VOL_OUT" ]; then
SAVED_VOL="$(echo "$VOL_OUT" | awk '{print $2}')"
if echo "$VOL_OUT" | grep -qi "MUTED"; then
IS_MUTED=1
fi
fi
fi
# --- install ----------------------------------------------------------
if [ "$SIMPLE" -eq 1 ]; then
echo "Installing baked FIR files -> $(dirname "$GRAPH_DST")/"
@@ -109,8 +122,17 @@ sudo cp "$MERGED" "$GRAPH_DST"
echo "Restarting WirePlumber"
systemctl --user restart wireplumber
# --- confirm --------------------------------------------------------
# --- restore master volume ---------------------------------------------
sleep 1
if [ -n "$SAVED_VOL" ] && have wpctl; then
wpctl set-volume @DEFAULT_AUDIO_SINK@ "$SAVED_VOL" 2>/dev/null || true
if [ "$IS_MUTED" -eq 1 ]; then
wpctl set-mute @DEFAULT_AUDIO_SINK@ 1 2>/dev/null || true
fi
echo "ok: preserved master volume (${SAVED_VOL})"
fi
# --- confirm --------------------------------------------------------
if have wpctl && wpctl status 2>/dev/null | grep -qi "DSP Speakers"; then
echo "Done - 'MacBook Pro 15,1 DSP Speakers' sink is up."
else

View File

@@ -266,41 +266,57 @@ def bake_driver_ir(src_wav, dst_wav, is_woofer=False, hp_freq=180.0, driver_gain
except Exception as e:
print(f"System Voicing Equalizer note: {e}")
# 2.7 Apply User EQ Boosts ("user_eq.json" if present and enabled)
# 2.7 Apply Effective User EQ (user_eq.json override if present, else default user_eq from graph.json)
ueq = None
user_eq_path = os.path.join(SCRIPT_DIR, "user_eq.json")
if os.path.exists(user_eq_path):
try:
with open(user_eq_path, 'r') as f:
ueq = json.load(f)
if ueq.get("enabled", 1) == 1:
g_out = ueq.get("g_out", 1.0)
if g_out != 1.0:
samples = [s * g_out for s in samples]
except Exception as e:
print(f"Error reading user_eq.json: {e}")
for i in range(8):
f_key = f"f_{i}"
g_key = f"g_{i}"
q_key = f"q_{i}"
ft_key = f"ft_{i}"
if f_key in ueq and g_key in ueq:
f0 = ueq[f_key]
gain = ueq[g_key]
q = ueq.get(q_key, 1.0)
ft = ueq.get(ft_key, 1)
gain_db = 20.0 * math.log10(max(gain, 0.001))
if ft == 5: # Low Shelf
b0, b1, b2, a0, a1, a2 = biquad_lowshelf(fs, f0, gain_db, q)
elif ft == 3: # High Shelf
b0, b1, b2, a0, a1, a2 = biquad_highshelf(fs, f0, gain_db, q)
elif ft == 2: # High-Pass
b0, b1, b2, a0, a1, a2 = biquad_highpass(fs, f0, q)
elif ft == 4: # Low-Pass
b0, b1, b2, a0, a1, a2 = biquad_lowpass(fs, f0, q)
else: # Peaking EQ
b0, b1, b2, a0, a1, a2 = biquad_peaking(fs, f0, gain_db, q)
if ueq is None and os.path.exists(graph_path):
try:
with open(graph_path, 'r') as f:
g = json.load(f)
for n in g.get("filter.graph", {}).get("nodes", []):
if n.get("name") == "user_eq":
ueq = n.get("control", {})
break
except Exception as e:
print(f"Error reading default user_eq from graph.json: {e}")
samples = process_biquad(samples, b0, b1, b2, a0, a1, a2)
if ueq and ueq.get("enabled", 1) == 1:
try:
g_out = ueq.get("g_out", 1.0)
if g_out != 1.0:
samples = [s * g_out for s in samples]
for i in range(8):
f_key = f"f_{i}"
g_key = f"g_{i}"
q_key = f"q_{i}"
ft_key = f"ft_{i}"
if f_key in ueq and g_key in ueq:
f0 = ueq[f_key]
gain = ueq[g_key]
q = ueq.get(q_key, 1.0)
ft = ueq.get(ft_key, 1)
gain_db = 20.0 * math.log10(max(gain, 0.001))
if ft == 5: # Low Shelf
b0, b1, b2, a0, a1, a2 = biquad_lowshelf(fs, f0, gain_db, q)
elif ft == 3: # High Shelf
b0, b1, b2, a0, a1, a2 = biquad_highshelf(fs, f0, gain_db, q)
elif ft == 2: # High-Pass
b0, b1, b2, a0, a1, a2 = biquad_highpass(fs, f0, q)
elif ft == 4: # Low-Pass
b0, b1, b2, a0, a1, a2 = biquad_lowpass(fs, f0, q)
else: # Peaking EQ
b0, b1, b2, a0, a1, a2 = biquad_peaking(fs, f0, gain_db, q)
samples = process_biquad(samples, b0, b1, b2, a0, a1, a2)
except Exception as e:
print(f"User EQ processing note: {e}")