From 454c940ab0275f92ee2f6cf40d3b56c6012669f1 Mon Sep 17 00:00:00 2001 From: "Skylar \"The Cobra\" Widulski" Date: Fri, 22 Dec 2023 10:18:15 -0500 Subject: [PATCH] Add exponential smoothing and interpolation Signed-off-by: Skylar "The Cobra" Widulski --- README.md | 11 ++++++++--- config.example.scm | 5 ++++- yammer.scm | 48 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1b79c0a..f1f813e 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,15 @@ Below is a list of values and what they do * `bgcolor`: Background color * `queue-size`: The size of the queue (minimum of 1), delays displaying bars by `queue-size` frames. Useful if desync is noticed * `fft`: Whether or not to perform a fourier transform to show frequencies (like `spectrum` mode in most other visualizers) +* `fft-interpolation`: Number of points to interpolate between fft values. <1 means disable * `smoothing`: Smoothing mode. Possible values are: - * `#f`: No smoothing - * `moving-average`: Moving average + * `#f`: No smoothing or interpolation. Disregards `fft-interpolation` + * `'none`: No smoothing + * `'moving-average`: Moving average + * `'exponential`: Simple (basic) exponential smoothing * `moving-average-block-size`: Size of the moving average window. Higher is smoother. +* `exponential-factor`: Exponential smoothing factor, lower is more smooth. +* `exponential-init-factor`: The first value of the exponentially smoothed list is multiplied by this # Running Either install libyammer.so and yammer.h to their respective systemwide locations, or do the following: @@ -42,7 +47,7 @@ guile -L . yammer.scm # Wishlist * Native PulseAudio and PipeWire sources -* More smoothing modes +* More smoothing modes (one that actually works would be nice) * Average over `resolution` * Offload some calculations to the GPU diff --git a/config.example.scm b/config.example.scm index 8e60b73..9ddb43c 100644 --- a/config.example.scm +++ b/config.example.scm @@ -7,5 +7,8 @@ (define bgcolor #x2e2016ff) (define queue-size 1) (define fft #f) -(define smoothing-mode 'moving-average) +(define fft-interpolation 0) +(define smoothing-mode 'none) (define moving-average-block-size 25) +(define exponential-factor 0.5) +(define exponential-init-factor 10) diff --git a/yammer.scm b/yammer.scm index 9555f18..df8e977 100755 --- a/yammer.scm +++ b/yammer.scm @@ -112,9 +112,10 @@ (make-rect (floor i) 0 (* (ceiling/ x (length plst)) resolution) - ;; Math to make scale a sane value - (- y-mid (abs (round/ (* y (car (list-ref plst j))) - (/ 76800 scale))))) + ;; Math to make `scale' a sane value + (exact + (- y-mid (abs (round/ (* y (car (list-ref plst j))) + (/ 76800 scale)))))) bgcolor) ;; This value is used twice, define in let statement (let ((n (abs (round/ (* y (cadr (list-ref plst j))) @@ -122,9 +123,10 @@ (fill-rect surf (make-rect - (floor i) (+ y-mid n) + (floor i) (exact (+ y-mid n)) (* (ceiling/ x (length plst)) resolution) - (- y-mid n)) + (exact + (- y-mid n))) bgcolor))))) ;; Create texture from surface (define texture (surface->texture ren surf)) @@ -137,18 +139,46 @@ ;; Smooth non-chunked list `lst' with mode `type' (define (smooth lst type) + (define input lst) (define ret '()) (define window 0) + (if (> fft-interpolation 0) + ;; Interpolate FFT values + (begin + (set! input '()) + (do ((i 0 (1+ i))) + ((>= (1+ i) (length lst))) + (set! input (append input (list (list-ref lst i)))) + (do ((j 0 (1+ j))) + ((> j fft-interpolation)) + (let ((n (- (list-ref lst (1+ i)) (list-ref lst i)))) + (set! input (append input (list (* (expt (1+ j) (/ n 100000)) + (list-ref lst i)))))))))) (cond ((eq? type 'moving-average) (do ((i 1 (1+ i))) - ((>= i (- (length lst) moving-average-block-size))) - (set! window (list-ref lst (- i 1))) + ((>= i (- (length input) moving-average-block-size))) + (set! window (list-ref input (- i 1))) (do ((j 0 (1+ j))) ((>= j moving-average-block-size)) - (set! window (+ window (list-ref lst (+ i j))))) + (set! window (+ window (list-ref input (+ i j))))) (set! window (round/ window moving-average-block-size)) - (set! ret (append ret (list window)))))) + (set! ret (append ret (list window))))) + ((eq? type 'exponential) + (do ((i 0 (1+ i))) + ((>= i (length input))) + (if (= i 0) + (set! ret (list (* exponential-init-factor (car input)))) + (set! ret + (append + ret + (list + (/ (+ (list-ref ret (1- i)) + (* exponential-factor + (- (list-ref input i) + (list-ref ret (1- i))))) + (/ (log (log (expt i 2))) (log 3))))))))) + (else (set! ret input))) ret) ;; Run loop