Files
sointu/tracker/gioui/specanalyzer.go
5684185+vsariola@users.noreply.github.com 2303e89bbd drafting
2025-12-30 22:43:35 +02:00

107 lines
3.2 KiB
Go

package gioui
import (
"image"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"github.com/vsariola/sointu/tracker"
)
type (
SpectrumState struct {
resolutionNumber *NumericUpDownState
smoothingBtn *Clickable
chnModeBtn *Clickable
}
)
func NewSpectrumState() *SpectrumState {
return &SpectrumState{
resolutionNumber: NewNumericUpDownState(),
smoothingBtn: new(Clickable),
chnModeBtn: new(Clickable),
}
}
func (s *SpectrumState) Layout(gtx C) D {
s.Update(gtx)
t := TrackerFromContext(gtx)
leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout
rightSpacer := layout.Spacer{Width: unit.Dp(6)}.Layout
var chnModeTxt string = "???"
switch tracker.SpecChnMode(t.Model.SpecAnChannelsInt().Value()) {
case tracker.SpecChnModeCombine:
chnModeTxt = "Combine"
case tracker.SpecChnModeSeparate:
chnModeTxt = "Separate"
case tracker.SpecChnModeLeft:
chnModeTxt = "Left"
case tracker.SpecChnModeRight:
chnModeTxt = "Right"
case tracker.SpecChnModeOff:
chnModeTxt = "Off"
}
var smoothTxt string = "???"
switch tracker.SpecSmoothing(t.Model.SpecAnSmoothing().Value()) {
case tracker.SpecSmoothingSlow:
smoothTxt = "Slow"
case tracker.SpecSmoothingMedium:
smoothTxt = "Medium"
case tracker.SpecSmoothingFast:
smoothTxt = "Fast"
}
resolution := NumUpDown(t.Model.SpecAnResolution(), t.Theme, s.resolutionNumber, "Resolution")
chnModeBtn := Btn(t.Theme, &t.Theme.Button.Filled, s.chnModeBtn, chnModeTxt, "Channel mode")
smoothBtn := Btn(t.Theme, &t.Theme.Button.Filled, s.smoothingBtn, smoothTxt, "Smoothing")
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Flexed(1, s.drawSpectrum),
layout.Rigid(func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(leftSpacer),
layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }),
layout.Rigid(chnModeBtn.Layout),
layout.Rigid(smoothBtn.Layout),
layout.Rigid(resolution.Layout),
layout.Rigid(rightSpacer),
)
}),
)
}
func (s *SpectrumState) Update(gtx C) {
t := TrackerFromContext(gtx)
for s.chnModeBtn.Clicked(gtx) {
t.Model.SpecAnChannelsInt().SetValue((t.SpecAnChannelsInt().Value() + 1) % int(tracker.NumSpecChnModes))
}
for s.smoothingBtn.Clicked(gtx) {
r := t.Model.SpecAnSmoothing().Range()
t.Model.SpecAnSmoothing().SetValue((t.SpecAnSmoothing().Value()+1)%(r.Max-r.Min+1) + r.Min)
}
}
func (s *SpectrumState) drawSpectrum(gtx C) D {
t := TrackerFromContext(gtx)
for chn := range 2 {
paint.ColorOp{Color: t.Theme.Oscilloscope.CurveColors[chn]}.Add(gtx.Ops)
p := t.Spectrum()[chn]
if len(p) <= 0 {
continue
}
fillRect(gtx, clip.Rect{Min: image.Pt(0, 0), Max: image.Pt(gtx.Constraints.Max.X, 1)})
fillRect(gtx, clip.Rect{Min: image.Pt(0, gtx.Constraints.Min.Y-1), Max: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)})
for px := range gtx.Constraints.Max.X {
y2 := gtx.Constraints.Max.Y - 1
y1 := int(-p[px*len(p)/gtx.Constraints.Max.X] / 80 * float32(y2))
fillRect(gtx, clip.Rect{Min: image.Pt(px, y1), Max: image.Pt(px+1, y2+1)})
}
}
return D{Size: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}
}