83 lines
2.1 KiB
Svelte
83 lines
2.1 KiB
Svelte
<script lang="ts">
|
|
// Live input level meter while recording (T7.3, FR-CAP-5/7). One bar with the
|
|
// system/loopback level (green) and — when the mic is enabled — the microphone
|
|
// level overlaid in the accent colour, so both sides of the call are visible
|
|
// at a glance. Each stream shows an rms fill + a peak marker.
|
|
import { t } from "../i18n/index.svelte";
|
|
let {
|
|
rms,
|
|
peak,
|
|
micRms = 0,
|
|
micPeak = 0,
|
|
showMic = false,
|
|
}: {
|
|
rms: number;
|
|
peak: number;
|
|
micRms?: number;
|
|
micPeak?: number;
|
|
showMic?: boolean;
|
|
} = $props();
|
|
|
|
// Perceptual loudness isn't linear; sqrt gives a meter that "looks right"
|
|
// for typical speech levels instead of sitting near-empty most of the time.
|
|
const pct = (v: number) => Math.min(1, Math.sqrt(Math.max(0, v))) * 100;
|
|
let rmsPct = $derived(pct(rms));
|
|
let peakPct = $derived(pct(peak));
|
|
let micRmsPct = $derived(pct(micRms));
|
|
let micPeakPct = $derived(pct(micPeak));
|
|
</script>
|
|
|
|
<div
|
|
class="meter"
|
|
role="meter"
|
|
aria-label={showMic ? t("levelmeter.system_mic") : t("levelmeter.system")}
|
|
aria-valuenow={Math.round(Math.max(rmsPct, showMic ? micRmsPct : 0))}
|
|
aria-valuemin={0}
|
|
aria-valuemax={100}
|
|
>
|
|
<div class="fill system" style="width: {rmsPct}%"></div>
|
|
<div class="peak system" style="left: {peakPct}%"></div>
|
|
{#if showMic}
|
|
<div class="fill mic" style="width: {micRmsPct}%"></div>
|
|
<div class="peak mic" style="left: {micPeakPct}%"></div>
|
|
{/if}
|
|
</div>
|
|
|
|
<style>
|
|
.meter {
|
|
position: relative;
|
|
width: 60px;
|
|
height: 8px;
|
|
border-radius: var(--radius-full);
|
|
background: var(--border);
|
|
overflow: hidden;
|
|
}
|
|
.fill {
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
transition: width 60ms linear;
|
|
/* Overlap is visible because the mic layer is translucent. */
|
|
opacity: 0.7;
|
|
}
|
|
.fill.system {
|
|
background: var(--success);
|
|
}
|
|
.fill.mic {
|
|
background: var(--accent);
|
|
}
|
|
.peak {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 2px;
|
|
transition: left 60ms linear;
|
|
}
|
|
.peak.system {
|
|
background: var(--fg);
|
|
opacity: 0.6;
|
|
}
|
|
.peak.mic {
|
|
background: var(--accent);
|
|
}
|
|
</style>
|