fix(player): эквалайзер «в ритм» — перекрытие окон + быстрый спад
Визуализатор отставал/висел: медленный спад (бар держался ~300мс после удара) и редкие обновления. Теперь FFT с перекрытием 50% (~43 обновл/с), мгновенный рост на удар и быстрый спад (0.78→0.55), убран искусственный троттл 33мс. Реакция плотнее попадает в бит. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,6 @@ class AudioSpectrumAnalyzer(
|
||||
private var channelCount = 2
|
||||
private var pcm16 = true
|
||||
private var sampleRate = 44100
|
||||
private var lastEmit = 0L
|
||||
// Автогейн: бегущий пик амплитуды — чтобы столбики всегда использовали всю
|
||||
// высоту независимо от громкости трека.
|
||||
private var agcPeak = 1e-4f
|
||||
@@ -100,22 +99,22 @@ class AudioSpectrumAnalyzer(
|
||||
if (!pcm16) return
|
||||
val b = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN)
|
||||
val ch = channelCount
|
||||
val hop = fftSize / 2
|
||||
while (b.remaining() >= 2 * ch) {
|
||||
var sum = 0f
|
||||
for (c in 0 until ch) sum += b.short.toFloat()
|
||||
sample[filled++] = (sum / ch) / 32768f
|
||||
if (filled >= fftSize) {
|
||||
compute()
|
||||
filled = 0
|
||||
// Перекрытие 50%: оставляем вторую половину — чаще обновляем (~43к/с),
|
||||
// спектр идёт «впритык» к биту, без рывков.
|
||||
System.arraycopy(sample, hop, sample, 0, fftSize - hop)
|
||||
filled = fftSize - hop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compute() {
|
||||
val now = System.nanoTime()
|
||||
if (now - lastEmit < 33_000_000L) return // ~30 кадров/с
|
||||
lastEmit = now
|
||||
|
||||
for (i in 0 until fftSize) {
|
||||
re[i] = sample[i] * window[i]
|
||||
im[i] = 0f
|
||||
@@ -154,8 +153,8 @@ class AudioSpectrumAnalyzer(
|
||||
// Нормируем по пику + перцептивный лифт (sqrt), чтобы тихое было видно.
|
||||
val v = sqrt((raw[band] / agcPeak).coerceIn(0f, 1f))
|
||||
val prev = smoothed[band]
|
||||
// Быстрый рост, плавный спад — как у настоящего эквалайзера.
|
||||
smoothed[band] = if (v > prev) v else prev * 0.78f + v * 0.22f
|
||||
// Мгновенный рост на удар, быстрый спад — чтобы попадать в ритм, не «висеть».
|
||||
smoothed[band] = if (v > prev) v else prev * 0.55f + v * 0.45f
|
||||
out[band] = smoothed[band]
|
||||
}
|
||||
_spectrum.value = out
|
||||
|
||||
Reference in New Issue
Block a user