Add ! key toggle for effected mic loopback monitor
This commit is contained in:
@@ -61,6 +61,7 @@
|
|||||||
<p><b>P:</b> Ping server</p>
|
<p><b>P:</b> Ping server</p>
|
||||||
<p><b>M:</b> Mute/unmute</p>
|
<p><b>M:</b> Mute/unmute</p>
|
||||||
<p><b>Shift+M:</b> Toggle stereo/mono output</p>
|
<p><b>Shift+M:</b> Toggle stereo/mono output</p>
|
||||||
|
<p><b>! (Shift+1):</b> Toggle loopback monitor</p>
|
||||||
<p><b>E:</b> Cycle voice effect</p>
|
<p><b>E:</b> Cycle voice effect</p>
|
||||||
<p><b>Dash or Equals:</b> Lower/raise active effect value</p>
|
<p><b>Dash or Equals:</b> Lower/raise active effect value</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.20 R59";
|
window.CHGRID_WEB_VERSION = "2026.02.20 R60";
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ export class AudioEngine {
|
|||||||
private outboundInputGain: GainNode | null = null;
|
private outboundInputGain: GainNode | null = null;
|
||||||
private outboundDestination: MediaStreamAudioDestinationNode | null = null;
|
private outboundDestination: MediaStreamAudioDestinationNode | null = null;
|
||||||
private outboundEffectRuntime: EffectRuntime | null = null;
|
private outboundEffectRuntime: EffectRuntime | null = null;
|
||||||
|
private loopbackEnabled = false;
|
||||||
|
private loopbackRuntime: EffectRuntime | null = null;
|
||||||
private outputMode: OutputMode = 'stereo';
|
private outputMode: OutputMode = 'stereo';
|
||||||
private effectIndex = EFFECT_SEQUENCE.findIndex((effect) => effect.id === 'off');
|
private effectIndex = EFFECT_SEQUENCE.findIndex((effect) => effect.id === 'off');
|
||||||
private readonly effectValues: Record<EffectId, number> = {
|
private readonly effectValues: Record<EffectId, number> = {
|
||||||
@@ -160,6 +162,12 @@ export class AudioEngine {
|
|||||||
return this.outputMode;
|
return this.outputMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleLoopback(): boolean {
|
||||||
|
this.loopbackEnabled = !this.loopbackEnabled;
|
||||||
|
this.rebuildOutboundEffectGraph();
|
||||||
|
return this.loopbackEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
async attachRemoteStream(
|
async attachRemoteStream(
|
||||||
peer: SpatialPeerRuntime,
|
peer: SpatialPeerRuntime,
|
||||||
stream: MediaStream,
|
stream: MediaStream,
|
||||||
@@ -321,6 +329,19 @@ export class AudioEngine {
|
|||||||
effect,
|
effect,
|
||||||
this.effectValues[effect],
|
this.effectValues[effect],
|
||||||
);
|
);
|
||||||
|
this.rebuildLoopbackGraph(effect, this.effectValues[effect]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private rebuildLoopbackGraph(effect: EffectId, effectValue: number): void {
|
||||||
|
if (!this.audioCtx || !this.outboundInputGain) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
disconnectEffectRuntime(this.loopbackRuntime);
|
||||||
|
this.loopbackRuntime = null;
|
||||||
|
if (!this.loopbackEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loopbackRuntime = connectEffectChain(this.audioCtx, this.outboundInputGain, this.audioCtx.destination, effect, effectValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private clampLevel(value: number): number {
|
private clampLevel(value: number): number {
|
||||||
|
|||||||
@@ -988,6 +988,13 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code === 'Digit1' && shiftKey) {
|
||||||
|
const enabled = audio.toggleLoopback();
|
||||||
|
updateStatus(enabled ? 'Loopback on.' : 'Loopback off.');
|
||||||
|
audio.sfxUiBlip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (code === 'KeyE') {
|
if (code === 'KeyE') {
|
||||||
const effect = audio.cycleOutboundEffect();
|
const effect = audio.cycleOutboundEffect();
|
||||||
updateStatus(effect.label);
|
updateStatus(effect.label);
|
||||||
|
|||||||
Reference in New Issue
Block a user