mirror of
https://codeberg.org/armin/noiz.git
synced 2026-09-01 05:50:52 +02:00
Add configurable spectrum analyzer peak hold, fade, and snap behavior
This commit is contained in:
parent
45bf10105b
commit
dd657c6ab3
1 changed files with 40 additions and 2 deletions
42
index.html
42
index.html
|
|
@ -228,6 +228,23 @@ footer .footer-track { flex: 1; min-width: 0; white-space: nowrap; overflow: hid
|
|||
<option value="60">1s</option>
|
||||
<option value="120">2s</option>
|
||||
</select>
|
||||
<span style="font-size:11px;color:#6b7089;margin-left:8px">Spec Peak Hold:</span>
|
||||
<select id="peakHoldSelect">
|
||||
<option value="0">Off</option>
|
||||
<option value="60">1s</option>
|
||||
<option value="120" selected>2s</option>
|
||||
<option value="180">3s</option>
|
||||
<option value="240">4s</option>
|
||||
</select>
|
||||
<span style="font-size:11px;color:#6b7089;margin-left:8px">Peak Fade:</span>
|
||||
<select id="peakFadeSelect">
|
||||
<option value="0" selected>0ms</option>
|
||||
<option value="12">200ms</option>
|
||||
<option value="24">400ms</option>
|
||||
<option value="36">600ms</option>
|
||||
<option value="48">800ms</option>
|
||||
<option value="60">1s</option>
|
||||
</select>
|
||||
<span style="font-size:11px;color:#6b7089;margin-left:8px">Crossfade:</span>
|
||||
<select id="crossfadeSelect">
|
||||
<option value="0" selected>Off</option>
|
||||
|
|
@ -361,11 +378,15 @@ const canvas = document.getElementById('spectrum');
|
|||
const ctx = canvas.getContext('2d');
|
||||
const bigTime = document.getElementById('bigTime');
|
||||
let peakData = [];
|
||||
let peakHoldCounters = [];
|
||||
let peakFadeCounters = [];
|
||||
let smoothedData = [];
|
||||
let vuPeakL = 0, vuPeakR = 0;
|
||||
let vuSmoothL = 0, vuSmoothR = 0;
|
||||
let vuPeakHoldL = 0, vuPeakHoldR = 0;
|
||||
let vuPeakGrace = 0;
|
||||
let peakHoldGrace = 0;
|
||||
let peakFadeGrace = 0;
|
||||
function bessi0(x) {
|
||||
let s = 1, t = 1;
|
||||
for (let k = 1; k <= 20; k++) {
|
||||
|
|
@ -495,6 +516,8 @@ function drawSpectrum() {
|
|||
}
|
||||
if (peakData.length !== NUM_BARS) {
|
||||
peakData = new Float32Array(NUM_BARS);
|
||||
peakHoldCounters = new Uint32Array(NUM_BARS);
|
||||
peakFadeCounters = new Uint32Array(NUM_BARS);
|
||||
smoothedData = new Float32Array(NUM_BARS);
|
||||
}
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
|
|
@ -532,15 +555,23 @@ function drawSpectrum() {
|
|||
ctx.fillRect(x, h - barH, barW, barH);
|
||||
if (barH > peakData[i]) {
|
||||
peakData[i] = barH;
|
||||
peakHoldCounters[i] = 0;
|
||||
peakFadeCounters[i] = 0;
|
||||
} else if (peakHoldCounters[i] < peakHoldGrace) {
|
||||
peakHoldCounters[i]++;
|
||||
} else if (peakFadeCounters[i] < peakFadeGrace) {
|
||||
const remaining = peakFadeGrace - peakFadeCounters[i];
|
||||
peakData[i] *= (remaining - 1) / remaining;
|
||||
peakFadeCounters[i]++;
|
||||
} else {
|
||||
peakData[i] *= peakDecay;
|
||||
peakData[i] = 0;
|
||||
}
|
||||
}
|
||||
ctx.fillStyle = '#e27878';
|
||||
for (let i = 0; i < NUM_BARS; i++) {
|
||||
const x = offset + i * totalBar;
|
||||
if (peakData[i] > 1) {
|
||||
ctx.fillRect(x, h - Math.round(peakData[i]), barW, 4);
|
||||
ctx.fillRect(x, Math.min(h - 4, h - Math.round(peakData[i])), barW, 4);
|
||||
}
|
||||
}
|
||||
const vuCanvas = document.getElementById('vuMeter');
|
||||
|
|
@ -743,6 +774,8 @@ const windowSelect = document.getElementById('windowSelect');
|
|||
const decaySelect = document.getElementById('decaySelect');
|
||||
const barDecaySelect = document.getElementById('barDecaySelect');
|
||||
const vuPeakHoldSelect = document.getElementById('vuPeakHoldSelect');
|
||||
const peakHoldSelect = document.getElementById('peakHoldSelect');
|
||||
const peakFadeSelect = document.getElementById('peakFadeSelect');
|
||||
const crossfadeSelect = document.getElementById('crossfadeSelect');
|
||||
const infoBtn = document.getElementById('infoBtn');
|
||||
const tagEditorOverlay = document.getElementById('tagEditorOverlay');
|
||||
|
|
@ -1706,7 +1739,12 @@ windowSelect.addEventListener('change', () => { windowType = windowSelect.value;
|
|||
decaySelect.addEventListener('change', () => { peakDecay = parseFloat(decaySelect.value); });
|
||||
barDecaySelect.addEventListener('change', () => { barDecay = parseFloat(barDecaySelect.value); });
|
||||
vuPeakHoldSelect.addEventListener('change', () => { vuPeakGrace = parseInt(vuPeakHoldSelect.value, 10); });
|
||||
peakHoldSelect.addEventListener('change', () => { peakHoldGrace = parseInt(peakHoldSelect.value, 10); });
|
||||
peakFadeSelect.addEventListener('change', () => { peakFadeGrace = parseInt(peakFadeSelect.value, 10); });
|
||||
crossfadeSelect.addEventListener('change', () => { crossfadeDuration = parseFloat(crossfadeSelect.value); });
|
||||
vuPeakGrace = parseInt(vuPeakHoldSelect.value, 10);
|
||||
peakHoldGrace = parseInt(peakHoldSelect.value, 10);
|
||||
peakFadeGrace = parseInt(peakFadeSelect.value, 10);
|
||||
crossfadeDuration = parseFloat(crossfadeSelect.value);
|
||||
repeatSelect.addEventListener('change', () => { repeatMode = repeatSelect.value; });
|
||||
shuffleSelect.addEventListener('change', () => { shuffleOn = shuffleSelect.value === 'on'; });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue