From 5daf81f33151b553eff1d2e15c9fcf8f9c30b1d9 Mon Sep 17 00:00:00 2001 From: vsariola <5684185+vsariola@users.noreply.github.com> Date: Sun, 14 Mar 2021 18:19:13 +0200 Subject: [PATCH] fix(tracker): avoid NaNs in volume analyzer better --- tracker/gioui/tracker.go | 2 +- tracker/gioui/vumeter.go | 4 ++-- tracker/vuanalyzer.go | 21 ++++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tracker/gioui/tracker.go b/tracker/gioui/tracker.go index 1a7e8ee..2195065 100644 --- a/tracker/gioui/tracker.go +++ b/tracker/gioui/tracker.go @@ -149,7 +149,7 @@ func New(audioContext sointu.AudioContext, synthService sointu.SynthService, syn } t.Model = tracker.NewModel() vuBufferObserver := make(chan []float32) - go tracker.VuAnalyzer(0.3, 1e-4, 1, -100, vuBufferObserver, t.volumeChan) + go tracker.VuAnalyzer(0.3, 1e-4, 1, -100, 20, vuBufferObserver, t.volumeChan) t.Theme.Palette.Fg = primaryColor t.Theme.Palette.ContrastFg = black t.SetEditMode(tracker.EditTracks) diff --git a/tracker/gioui/vumeter.go b/tracker/gioui/vumeter.go index dee5166..714db4d 100644 --- a/tracker/gioui/vumeter.go +++ b/tracker/gioui/vumeter.go @@ -21,7 +21,7 @@ func (v VuMeter) Layout(gtx C) D { gtx.Constraints.Max.Y = gtx.Px(unit.Dp(12)) height := gtx.Px(unit.Dp(6)) for j := 0; j < 2; j++ { - value := v.Volume.Average[j] + v.Range + value := float32(v.Volume.Average[j]) + v.Range if value > 0 { x := int(value/v.Range*float32(gtx.Constraints.Max.X) + 0.5) if x > gtx.Constraints.Max.X { @@ -29,7 +29,7 @@ func (v VuMeter) Layout(gtx C) D { } paint.FillShape(gtx.Ops, mediumEmphasisTextColor, clip.Rect(image.Rect(0, 0, x, height)).Op()) } - valueMax := v.Volume.Peak[j] + v.Range + valueMax := float32(v.Volume.Peak[j]) + v.Range if valueMax > 0 { color := white if valueMax >= v.Range { diff --git a/tracker/vuanalyzer.go b/tracker/vuanalyzer.go index 198634c..9168ca6 100644 --- a/tracker/vuanalyzer.go +++ b/tracker/vuanalyzer.go @@ -7,8 +7,8 @@ import ( // Volume represents an average and peak volume measurement, in decibels. 0 dB = // signal level of +-1. type Volume struct { - Average [2]float32 - Peak [2]float32 + Average [2]float64 + Peak [2]float64 } // VuAnalyzer receives stereo from the bc channel and converts these into peak & @@ -28,11 +28,11 @@ type Volume struct { // // minVolume is just a hard limit for the vuanalyzer volumes, in decibels, just to // prevent negative infinities for volumes -func VuAnalyzer(tau float64, attack float64, release float64, minVolume float32, bc <-chan []float32, vc chan<- Volume) { - v := Volume{Average: [2]float32{minVolume, minVolume}, Peak: [2]float32{minVolume, minVolume}} - alpha := 1 - float32(math.Exp(-1.0/(tau*44100))) // from https://en.wikipedia.org/wiki/Exponential_smoothing - alphaAttack := 1 - float32(math.Exp(-1.0/(attack*44100))) - alphaRelease := 1 - float32(math.Exp(-1.0/(release*44100))) +func VuAnalyzer(tau float64, attack float64, release float64, minVolume float64, maxVolume float64, bc <-chan []float32, vc chan<- Volume) { + v := Volume{Average: [2]float64{minVolume, minVolume}, Peak: [2]float64{minVolume, minVolume}} + alpha := 1 - math.Exp(-1.0/(tau*44100)) // from https://en.wikipedia.org/wiki/Exponential_smoothing + alphaAttack := 1 - math.Exp(-1.0/(attack*44100)) + alphaRelease := 1 - math.Exp(-1.0/(release*44100)) for buffer := range bc { for j := 0; j < 2; j++ { for i := 0; i < len(buffer); i += 2 { @@ -40,10 +40,13 @@ func VuAnalyzer(tau float64, attack float64, release float64, minVolume float32, if math.IsNaN(sample2) { sample2 = float64(minVolume) } - dB := float32(10 * math.Log10(float64(sample2))) - if dB < minVolume { + dB := 10 * math.Log10(float64(sample2)) + if dB < minVolume || math.IsNaN(dB) { dB = minVolume } + if dB > maxVolume { + dB = maxVolume + } v.Average[j] += (dB - v.Average[j]) * alpha alphaPeak := alphaAttack if dB < v.Peak[j] {