diff --git a/tracker/gioui/oscilloscope.go b/tracker/gioui/oscilloscope.go index 5ca13d2..9d66900 100644 --- a/tracker/gioui/oscilloscope.go +++ b/tracker/gioui/oscilloscope.go @@ -2,6 +2,7 @@ package gioui import ( "math" + "strconv" "gioui.org/layout" "gioui.org/unit" @@ -21,7 +22,6 @@ type ( Theme *Theme Model *tracker.ScopeModel State *OscilloscopeState - Style *PlotStyle } ) @@ -40,7 +40,6 @@ func Scope(th *Theme, m *tracker.ScopeModel, st *OscilloscopeState) Oscilloscope Theme: th, Model: m, State: st, - Style: &th.Oscilloscope, } } @@ -80,12 +79,12 @@ func (s *Oscilloscope) Layout(gtx C) D { a := max(int(math.Ceil(float64(r.a*float32(l)))), 0) b := min(int(math.Floor(float64(r.b*float32(l)))), l) for i := a; i <= b; i++ { - yield(float32(i)/float32(l), "") + yield(float32(i)/float32(l), strconv.Itoa(i)) } } yticks := func(r plotRange, yield func(pos float32, label string)) { - yield(-1, "1") - yield(1, "-1") + yield(-1, "") + yield(1, "") } return s.State.plot.Layout(gtx, data, xticks, yticks, cx, 2) diff --git a/tracker/gioui/plot.go b/tracker/gioui/plot.go index 372a9bd..138296e 100644 --- a/tracker/gioui/plot.go +++ b/tracker/gioui/plot.go @@ -8,6 +8,7 @@ import ( "gioui.org/f32" "gioui.org/io/event" "gioui.org/io/pointer" + "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" ) @@ -27,6 +28,7 @@ type ( CurveColors [2]color.NRGBA `yaml:",flow"` LimitColor color.NRGBA `yaml:",flow"` CursorColor color.NRGBA `yaml:",flow"` + Ticks LabelStyle } PlotDataFunc func(chn int, xr plotRange) (yr plotRange) @@ -47,7 +49,7 @@ func NewPlot(xlim, ylim plotRange) *Plot { func (p *Plot) Layout(gtx C, data PlotDataFunc, xticks, yticks PlotTickFunc, cursornx float32, numchns int) D { p.update(gtx) t := TrackerFromContext(gtx) - style := t.Theme.Oscilloscope + style := t.Theme.Plot s := gtx.Constraints.Max if s.X <= 1 || s.Y <= 1 { return D{} @@ -59,16 +61,21 @@ func (p *Plot) Layout(gtx C, data PlotDataFunc, xticks, yticks PlotTickFunc, cur ylim := p.ylim() // draw tick marks - paint.ColorOp{Color: style.LimitColor}.Add(gtx.Ops) - xticks(xlim, func(x float32, label string) { + xticks(xlim, func(x float32, txt string) { + paint.ColorOp{Color: style.LimitColor}.Add(gtx.Ops) sx := plotPx(s.X).toScreen(xlim.toRelative(x)) fillRect(gtx, clip.Rect{Min: image.Pt(sx, 0), Max: image.Pt(sx+1, s.Y)}) + defer op.Offset(image.Pt(sx, gtx.Dp(2))).Push(gtx.Ops).Pop() + Label(t.Theme, &t.Theme.Plot.Ticks, txt).Layout(gtx) }) - yticks(ylim, func(y float32, label string) { + yticks(ylim, func(y float32, txt string) { + paint.ColorOp{Color: style.LimitColor}.Add(gtx.Ops) sy := plotPx(s.Y).toScreen(ylim.toRelative(y)) fillRect(gtx, clip.Rect{Min: image.Pt(0, sy), Max: image.Pt(s.X, sy+1)}) + defer op.Offset(image.Pt(gtx.Dp(2), sy)).Push(gtx.Ops).Pop() + Label(t.Theme, &t.Theme.Plot.Ticks, txt).Layout(gtx) }) // draw cursor diff --git a/tracker/gioui/specanalyzer.go b/tracker/gioui/specanalyzer.go index f573f0f..4f049fd 100644 --- a/tracker/gioui/specanalyzer.go +++ b/tracker/gioui/specanalyzer.go @@ -68,10 +68,8 @@ func (s *SpectrumState) Layout(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Flexed(1, func(gtx C) D { data := func(chn int, xr plotRange) (yr plotRange) { - xr.a = softplus(xr.a*10) / 10 - xr.b = softplus(xr.b*10) / 10 - xr.a = float32(math.Log(float64(xr.a))) + 1 - xr.b = float32(math.Log(float64(xr.b))) + 1 + xr.a = float32(math.Exp2(float64(xr.a-1) * 8)) + xr.b = float32(math.Exp2(float64(xr.b-1) * 8)) w1, f1 := math.Modf(float64(xr.a) * float64(speclen)) w2, f2 := math.Modf(float64(xr.b) * float64(speclen)) x1 := max(int(w1), 0) @@ -104,13 +102,33 @@ func (s *SpectrumState) Layout(gtx C) D { return plotRange{-y1, -y2} } + type pair struct { + freq float64 + label string + } xticks := func(r plotRange, yield func(pos float32, label string)) { - yield(0, "") - yield(1, "") + for _, p := range []pair{ + {freq: 10, label: "10 Hz"}, + {freq: 20, label: "20 Hz"}, + {freq: 50, label: "50 Hz"}, + {freq: 100, label: "100 Hz"}, + {freq: 200, label: "200 Hz"}, + {freq: 500, label: "500 Hz"}, + {freq: 1e3, label: "1 kHz"}, + {freq: 2e3, label: "2 kHz"}, + {freq: 5e3, label: "5 kHz"}, + {freq: 1e4, label: "10 kHz"}, + {freq: 2e4, label: "20 kHz"}, + } { + x := float32(math.Log2((p.freq/22050))/8 + 1) + if x >= r.a && x <= r.b { + yield(x, p.label) + } + } } yticks := func(r plotRange, yield func(pos float32, label string)) { - yield(-1, "") - yield(0, "") + yield(-1, "0 dB") + yield(0, "-Inf dB") } return s.plot.Layout(gtx, data, xticks, yticks, 0, numchns) }), diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index e01bcd5..8ea4a41 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -32,7 +32,7 @@ type Theme struct { Emphasis IconButtonStyle Error IconButtonStyle } - Oscilloscope PlotStyle + Plot PlotStyle NumericUpDown NumericUpDownStyle SongPanel struct { RowHeader LabelStyle diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index 03716b0..78ce13c 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -83,10 +83,11 @@ iconbutton: color: *errorcolor size: 24 inset: { top: 6, bottom: 6, left: 6, right: 6 } -oscilloscope: +plot: curvecolors: [*primarycolor, *secondarycolor] limitcolor: { r: 255, g: 255, b: 255, a: 8 } cursorcolor: { r: 252, g: 186, b: 3, a: 255 } + ticks: { textsize: 12, color: *disabled, maxlines: 1} numericupdown: bgcolor: { r: 255, g: 255, b: 255, a: 3 } textcolor: *fg