refactor(tracker): refactor IntData to IntValue, following Bool example

This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-05-26 14:50:09 +03:00
parent fb3a0da3ed
commit 74f37318d6
11 changed files with 186 additions and 189 deletions

View File

@ -215,37 +215,37 @@ func (t *Tracker) KeyEvent(e key.Event, gtx C) {
t.Solo().Toggle()
// Integers
case "InstrumentVoicesAdd":
t.Model.InstrumentVoices().Int().Add(1)
t.Model.InstrumentVoices().Add(1)
case "InstrumentVoicesSubtract":
t.Model.InstrumentVoices().Int().Add(-1)
t.Model.InstrumentVoices().Add(-1)
case "TrackVoicesAdd":
t.TrackVoices().Int().Add(1)
t.TrackVoices().Add(1)
case "TrackVoicesSubtract":
t.TrackVoices().Int().Add(-1)
t.TrackVoices().Add(-1)
case "SongLengthAdd":
t.SongLength().Int().Add(1)
t.SongLength().Add(1)
case "SongLengthSubtract":
t.SongLength().Int().Add(-1)
t.SongLength().Add(-1)
case "BPMAdd":
t.BPM().Int().Add(1)
t.BPM().Add(1)
case "BPMSubtract":
t.BPM().Int().Add(-1)
t.BPM().Add(-1)
case "RowsPerPatternAdd":
t.RowsPerPattern().Int().Add(1)
t.RowsPerPattern().Add(1)
case "RowsPerPatternSubtract":
t.RowsPerPattern().Int().Add(-1)
t.RowsPerPattern().Add(-1)
case "RowsPerBeatAdd":
t.RowsPerBeat().Int().Add(1)
t.RowsPerBeat().Add(1)
case "RowsPerBeatSubtract":
t.RowsPerBeat().Int().Add(-1)
t.RowsPerBeat().Add(-1)
case "StepAdd":
t.Step().Int().Add(1)
t.Step().Add(1)
case "StepSubtract":
t.Step().Int().Add(-1)
t.Step().Add(-1)
case "OctaveAdd":
t.Octave().Int().Add(1)
t.Octave().Add(1)
case "OctaveSubtract":
t.Octave().Int().Add(-1)
t.Octave().Add(-1)
// Other miscellaneous
case "Paste":
gtx.Execute(clipboard.ReadCmd{Tag: t})

View File

@ -76,7 +76,7 @@ type NoteEditor struct {
func NewNoteEditor(model *tracker.Model) *NoteEditor {
ret := &NoteEditor{
TrackVoices: NewNumberInput(model.TrackVoices().Int()),
TrackVoices: NewNumberInput(model.TrackVoices()),
NewTrackBtn: NewActionClickable(model.AddTrack()),
DeleteTrackBtn: NewActionClickable(model.DeleteTrack()),
SplitTrackBtn: NewActionClickable(model.SplitTrack()),

View File

@ -84,7 +84,7 @@ func (s *NumericUpDown) Update(gtx layout.Context) {
case pointer.Drag:
var deltaCoord float32
deltaCoord = e.Position.X - e.Position.Y - s.NumberInput.dragStartXY
s.NumberInput.Int.Set(s.NumberInput.dragStartValue + int(deltaCoord/pxPerStep+0.5))
s.NumberInput.Int.SetValue(s.NumberInput.dragStartValue + int(deltaCoord/pxPerStep+0.5))
}
}
}

View File

@ -47,8 +47,8 @@ func NewOscilloscope(model *tracker.Model) *OscilloscopeState {
return &OscilloscopeState{
onceBtn: NewBoolClickable(model.SignalAnalyzer().Once()),
wrapBtn: NewBoolClickable(model.SignalAnalyzer().Wrap()),
lengthInBeatsNumber: NewNumberInput(model.SignalAnalyzer().LengthInBeats().Int()),
triggerChannelNumber: NewNumberInput(model.SignalAnalyzer().TriggerChannel().Int()),
lengthInBeatsNumber: NewNumberInput(model.SignalAnalyzer().LengthInBeats()),
triggerChannelNumber: NewNumberInput(model.SignalAnalyzer().TriggerChannel()),
}
}

View File

@ -39,11 +39,11 @@ type SongPanel struct {
func NewSongPanel(model *tracker.Model) *SongPanel {
ret := &SongPanel{
BPM: NewNumberInput(model.BPM().Int()),
RowsPerPattern: NewNumberInput(model.RowsPerPattern().Int()),
RowsPerBeat: NewNumberInput(model.RowsPerBeat().Int()),
Step: NewNumberInput(model.Step().Int()),
SongLength: NewNumberInput(model.SongLength().Int()),
BPM: NewNumberInput(model.BPM()),
RowsPerPattern: NewNumberInput(model.RowsPerPattern()),
RowsPerBeat: NewNumberInput(model.RowsPerBeat()),
Step: NewNumberInput(model.Step()),
SongLength: NewNumberInput(model.SongLength()),
Scope: NewOscilloscope(model),
MenuBar: NewMenuBar(model),
PlayBar: NewPlayBar(model),
@ -61,7 +61,7 @@ func NewSongPanel(model *tracker.Model) *SongPanel {
func (s *SongPanel) Update(gtx C, t *Tracker) {
for s.WeightingTypeBtn.Clicked(gtx) {
t.Model.DetectorWeighting().Int().Set((t.DetectorWeighting().Value() + 1) % int(tracker.NumWeightingTypes))
t.Model.DetectorWeighting().SetValue((t.DetectorWeighting().Value() + 1) % int(tracker.NumWeightingTypes))
}
for s.OversamplingBtn.Clicked(gtx) {
t.Model.Oversampling().SetValue(!t.Oversampling().Value())

View File

@ -71,8 +71,8 @@ var ZoomFactors = []float32{.25, 1. / 3, .5, 2. / 3, .75, .8, 1, 1.1, 1.25, 1.5,
func NewTracker(model *tracker.Model) *Tracker {
t := &Tracker{
OctaveNumberInput: NewNumberInput(model.Octave().Int()),
InstrumentVoices: NewNumberInput(model.InstrumentVoices().Int()),
OctaveNumberInput: NewNumberInput(model.Octave()),
InstrumentVoices: NewNumberInput(model.InstrumentVoices()),
TopHorizontalSplit: &Split{Ratio: -.5, MinSize1: 180, MinSize2: 180},
BottomHorizontalSplit: &Split{Ratio: -.6, MinSize1: 180, MinSize2: 180},

View File

@ -208,22 +208,22 @@ func (pe *UnitEditor) command(e key.Event, t *Tracker) {
if sel == nil {
return
}
i := (&tracker.Int{IntData: sel})
i := tracker.MakeInt(sel)
if e.Modifiers.Contain(key.ModShift) {
i.Set(i.Value() - sel.LargeStep())
i.SetValue(i.Value() - sel.LargeStep())
} else {
i.Set(i.Value() - 1)
i.SetValue(i.Value() - 1)
}
case key.NameRightArrow:
sel := params.SelectedItem()
if sel == nil {
return
}
i := (&tracker.Int{IntData: sel})
i := tracker.MakeInt(sel)
if e.Modifiers.Contain(key.ModShift) {
i.Set(i.Value() + sel.LargeStep())
i.SetValue(i.Value() + sel.LargeStep())
} else {
i.Set(i.Value() + 1)
i.SetValue(i.Value() + 1)
}
case key.NameEscape:
t.InstrumentEditor.unitDragList.Focus()
@ -286,7 +286,7 @@ func (p ParameterStyle) Layout(gtx C) D {
}
if ev, ok := e.(pointer.Event); ok && ev.Kind == pointer.Scroll {
delta := math.Min(math.Max(float64(ev.Scroll.Y), -1), 1)
tracker.Int{IntData: p.w.Parameter}.Add(-int(delta))
tracker.MakeInt(p.w.Parameter).Add(-int(delta))
}
}
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(200))
@ -306,7 +306,7 @@ func (p ParameterStyle) Layout(gtx C) D {
event.Op(gtx.Ops, &p.w.floatWidget)
}
dims := sliderStyle.Layout(gtx)
tracker.Int{IntData: p.w.Parameter}.Set(int(p.w.floatWidget.Value*float32(ra.Max-ra.Min) + float32(ra.Min) + 0.5))
tracker.MakeInt(p.w.Parameter).SetValue(int(p.w.floatWidget.Value*float32(ra.Max-ra.Min) + float32(ra.Min) + 0.5))
return dims
case tracker.BoolParameter:
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(60))
@ -318,9 +318,9 @@ func (p ParameterStyle) Layout(gtx C) D {
defer pointer.PassOp{}.Push(gtx.Ops).Pop()
dims := layout.Center.Layout(gtx, boolStyle.Layout)
if p.w.boolWidget.Value {
tracker.Int{IntData: p.w.Parameter}.Set(ra.Max)
tracker.MakeInt(p.w.Parameter).SetValue(ra.Max)
} else {
tracker.Int{IntData: p.w.Parameter}.Set(ra.Min)
tracker.MakeInt(p.w.Parameter).SetValue(ra.Min)
}
return dims
case tracker.IDParameter:
@ -334,7 +334,7 @@ func (p ParameterStyle) Layout(gtx C) D {
instrItems[i].IconBytes = icons.NavigationChevronRight
instrItems[i].Doer = tracker.MakeEnabledAction((tracker.DoFunc)(func() {
if id, ok := p.tracker.Instruments().FirstID(i); ok {
tracker.Int{IntData: p.w.Parameter}.Set(id)
tracker.MakeInt(p.w.Parameter).SetValue(id)
}
}))
}
@ -351,7 +351,7 @@ func (p ParameterStyle) Layout(gtx C) D {
unitItems[j].Text = buildUnitLabel(j, unit)
unitItems[j].IconBytes = icons.NavigationChevronRight
unitItems[j].Doer = tracker.MakeEnabledAction((tracker.DoFunc)(func() {
tracker.Int{IntData: p.w.Parameter}.Set(id)
tracker.MakeInt(p.w.Parameter).SetValue(id)
}))
}
}

View File

@ -5,147 +5,151 @@ import (
)
type (
// Int represents an integer value in the tracker model e.g. BPM, song
// length, etc. It is a wrapper around an IntValue interface that provides
// methods to manipulate the value, but Int guard that all changes are
// within the range of the underlying IntValue implementation and that
// SetValue is not called when the value is unchanged.
Int struct {
IntData
value IntValue
}
IntData interface {
IntValue interface {
Value() int
Range() intRange
setValue(int)
change(kind string) func()
SetValue(int) bool // returns true if the value was changed
Range() IntRange
}
intRange struct {
IntRange struct {
Min, Max int
}
InstrumentVoices Model
TrackVoices Model
SongLength Model
BPM Model
RowsPerPattern Model
RowsPerBeat Model
Step Model
Octave Model
InstrumentVoices Model
TrackVoices Model
SongLength Model
BPM Model
RowsPerPattern Model
RowsPerBeat Model
Step Model
Octave Model
DetectorWeighting Model
)
func MakeInt(value IntValue) Int {
return Int{value}
}
func (v Int) Add(delta int) (ok bool) {
return v.SetValue(v.Value() + delta)
}
func (v Int) SetValue(value int) (ok bool) {
r := v.Range()
value := r.Clamp(v.Value() + delta)
value = r.Clamp(value)
if value == v.Value() || value < r.Min || value > r.Max {
return false
}
defer v.change("Add")()
v.setValue(value)
return true
return v.value.SetValue(value)
}
func (v Int) Set(value int) (ok bool) {
r := v.Range()
value = v.Range().Clamp(value)
if value == v.Value() || value < r.Min || value > r.Max {
return false
func (v Int) Range() IntRange {
if v.value == nil {
return IntRange{0, 0}
}
defer v.change("Set")()
v.setValue(value)
return true
return v.value.Range()
}
func (r intRange) Clamp(value int) int {
func (v Int) Value() int {
if v.value == nil {
return 0
}
return v.value.Value()
}
func (r IntRange) Clamp(value int) int {
return max(min(value, r.Max), r.Min)
}
// Model methods
func (m *Model) InstrumentVoices() *InstrumentVoices { return (*InstrumentVoices)(m) }
func (m *Model) TrackVoices() *TrackVoices { return (*TrackVoices)(m) }
func (m *Model) SongLength() *SongLength { return (*SongLength)(m) }
func (m *Model) BPM() *BPM { return (*BPM)(m) }
func (m *Model) RowsPerPattern() *RowsPerPattern { return (*RowsPerPattern)(m) }
func (m *Model) RowsPerBeat() *RowsPerBeat { return (*RowsPerBeat)(m) }
func (m *Model) Step() *Step { return (*Step)(m) }
func (m *Model) Octave() *Octave { return (*Octave)(m) }
func (m *Model) DetectorWeighting() *DetectorWeighting { return (*DetectorWeighting)(m) }
func (m *Model) BPM() Int { return MakeInt((*BPM)(m)) }
func (m *Model) InstrumentVoices() Int { return MakeInt((*InstrumentVoices)(m)) }
func (m *Model) TrackVoices() Int { return MakeInt((*TrackVoices)(m)) }
func (m *Model) SongLength() Int { return MakeInt((*SongLength)(m)) }
func (m *Model) RowsPerPattern() Int { return MakeInt((*RowsPerPattern)(m)) }
func (m *Model) RowsPerBeat() Int { return MakeInt((*RowsPerBeat)(m)) }
func (m *Model) Step() Int { return MakeInt((*Step)(m)) }
func (m *Model) Octave() Int { return MakeInt((*Octave)(m)) }
func (m *Model) DetectorWeighting() Int { return MakeInt((*DetectorWeighting)(m)) }
// BeatsPerMinuteInt
func (v *BPM) Int() Int { return Int{v} }
func (v *BPM) Value() int { return v.d.Song.BPM }
func (v *BPM) setValue(value int) { v.d.Song.BPM = value }
func (v *BPM) Range() intRange { return intRange{1, 999} }
func (v *BPM) change(kind string) func() {
return (*Model)(v).change("BPMInt."+kind, SongChange, MinorChange)
func (v *BPM) Value() int { return v.d.Song.BPM }
func (v *BPM) SetValue(value int) bool {
defer (*Model)(v).change("BPMInt", SongChange, MinorChange)()
v.d.Song.BPM = value
return true
}
func (v *BPM) Range() IntRange { return IntRange{1, 999} }
// RowsPerPatternInt
func (v *RowsPerPattern) Int() Int { return Int{v} }
func (v *RowsPerPattern) Value() int { return v.d.Song.Score.RowsPerPattern }
func (v *RowsPerPattern) setValue(value int) { v.d.Song.Score.RowsPerPattern = value }
func (v *RowsPerPattern) Range() intRange { return intRange{1, 256} }
func (v *RowsPerPattern) change(kind string) func() {
return (*Model)(v).change("RowsPerPatternInt."+kind, SongChange, MinorChange)
func (v *RowsPerPattern) Value() int { return v.d.Song.Score.RowsPerPattern }
func (v *RowsPerPattern) SetValue(value int) bool {
defer (*Model)(v).change("RowsPerPatternInt", SongChange, MinorChange)()
v.d.Song.Score.RowsPerPattern = value
return true
}
func (v *RowsPerPattern) Range() IntRange { return IntRange{1, 256} }
// SongLengthInt
func (v *SongLength) Int() Int { return Int{v} }
func (v *SongLength) Value() int { return v.d.Song.Score.Length }
func (v *SongLength) setValue(value int) { v.d.Song.Score.Length = value }
func (v *SongLength) Range() intRange { return intRange{1, math.MaxInt32} }
func (v *SongLength) change(kind string) func() {
return (*Model)(v).change("SongLengthInt."+kind, SongChange, MinorChange)
func (v *SongLength) Value() int { return v.d.Song.Score.Length }
func (v *SongLength) SetValue(value int) bool {
defer (*Model)(v).change("SongLengthInt", SongChange, MinorChange)()
v.d.Song.Score.Length = value
return true
}
func (v *SongLength) Range() IntRange { return IntRange{1, math.MaxInt32} }
// StepInt
func (v *Step) Int() Int { return Int{v} }
func (v *Step) Value() int { return v.d.Step }
func (v *Step) setValue(value int) { v.d.Step = value }
func (v *Step) Range() intRange { return intRange{0, 8} }
func (v *Step) change(kind string) func() {
return (*Model)(v).change("StepInt"+kind, NoChange, MinorChange)
func (v *Step) Value() int { return v.d.Step }
func (v *Step) SetValue(value int) bool {
defer (*Model)(v).change("StepInt", NoChange, MinorChange)()
v.d.Step = value
return true
}
func (v *Step) Range() IntRange { return IntRange{0, 8} }
// OctaveInt
func (v *Octave) Int() Int { return Int{v} }
func (v *Octave) Value() int { return v.d.Octave }
func (v *Octave) setValue(value int) { v.d.Octave = value }
func (v *Octave) Range() intRange { return intRange{0, 9} }
func (v *Octave) change(kind string) func() { return func() {} }
func (v *Octave) Value() int { return v.d.Octave }
func (v *Octave) SetValue(value int) bool { v.d.Octave = value; return true }
func (v *Octave) Range() IntRange { return IntRange{0, 9} }
// RowsPerBeatInt
func (v *RowsPerBeat) Int() Int { return Int{v} }
func (v *RowsPerBeat) Value() int { return v.d.Song.RowsPerBeat }
func (v *RowsPerBeat) setValue(value int) { v.d.Song.RowsPerBeat = value }
func (v *RowsPerBeat) Range() intRange { return intRange{1, 32} }
func (v *RowsPerBeat) change(kind string) func() {
return (*Model)(v).change("RowsPerBeatInt."+kind, SongChange, MinorChange)
func (v *RowsPerBeat) Value() int { return v.d.Song.RowsPerBeat }
func (v *RowsPerBeat) SetValue(value int) bool {
defer (*Model)(v).change("RowsPerBeatInt", SongChange, MinorChange)()
v.d.Song.RowsPerBeat = value
return true
}
func (v *RowsPerBeat) Range() IntRange { return IntRange{1, 32} }
// ModelLoudnessType
func (v *DetectorWeighting) Int() Int { return Int{v} }
func (v *DetectorWeighting) Value() int { return int(v.weightingType) }
func (v *DetectorWeighting) setValue(value int) {
func (v *DetectorWeighting) SetValue(value int) bool {
v.weightingType = WeightingType(value)
TrySend(v.broker.ToDetector, MsgToDetector{HasWeightingType: true, WeightingType: WeightingType(value)})
return true
}
func (v *DetectorWeighting) Range() intRange { return intRange{0, int(NumLoudnessTypes) - 1} }
func (v *DetectorWeighting) change(kind string) func() { return func() {} }
func (v *DetectorWeighting) Range() IntRange { return IntRange{0, int(NumLoudnessTypes) - 1} }
// InstrumentVoicesInt
func (v *InstrumentVoices) Int() Int {
return Int{v}
}
func (v *InstrumentVoices) Value() int {
if v.d.InstrIndex < 0 || v.d.InstrIndex >= len(v.d.Song.Patch) {
return 1
@ -153,10 +157,11 @@ func (v *InstrumentVoices) Value() int {
return max(v.d.Song.Patch[v.d.InstrIndex].NumVoices, 1)
}
func (m *InstrumentVoices) setValue(value int) {
func (m *InstrumentVoices) SetValue(value int) bool {
if m.d.InstrIndex < 0 || m.d.InstrIndex >= len(m.d.Song.Patch) {
return
return false
}
defer (*Model)(m).change("InstrumentVoices", SongChange, MinorChange)()
voiceIndex := m.d.Song.Patch.FirstVoiceForInstrument(m.d.InstrIndex)
voiceRange := Range{voiceIndex, voiceIndex + m.d.Song.Patch[m.d.InstrIndex].NumVoices}
ranges := MakeSetLength(voiceRange, value)
@ -164,22 +169,15 @@ func (m *InstrumentVoices) setValue(value int) {
if !ok {
m.changeCancel = true
}
return ok
}
func (v *InstrumentVoices) Range() intRange {
return intRange{1, (*Model)(v).remainingVoices(true, v.linkInstrTrack) + v.Value()}
}
func (v *InstrumentVoices) change(kind string) func() {
return (*Model)(v).change("InstrumentVoices."+kind, SongChange, MinorChange)
func (v *InstrumentVoices) Range() IntRange {
return IntRange{1, (*Model)(v).remainingVoices(true, v.linkInstrTrack) + v.Value()}
}
// TrackVoicesInt
func (v *TrackVoices) Int() Int {
return Int{v}
}
func (v *TrackVoices) Value() int {
t := v.d.Cursor.Track
if t < 0 || t >= len(v.d.Song.Score.Tracks) {
@ -188,7 +186,8 @@ func (v *TrackVoices) Value() int {
return max(v.d.Song.Score.Tracks[t].NumVoices, 1)
}
func (m *TrackVoices) setValue(value int) {
func (m *TrackVoices) SetValue(value int) bool {
defer (*Model)(m).change("TrackVoices", SongChange, MinorChange)()
voiceIndex := m.d.Song.Score.FirstVoiceForTrack(m.d.Cursor.Track)
voiceRange := Range{voiceIndex, voiceIndex + m.d.Song.Score.Tracks[m.d.Cursor.Track].NumVoices}
ranges := MakeSetLength(voiceRange, value)
@ -196,16 +195,13 @@ func (m *TrackVoices) setValue(value int) {
if !ok {
m.changeCancel = true
}
return ok
}
func (v *TrackVoices) Range() intRange {
func (v *TrackVoices) Range() IntRange {
t := v.d.Cursor.Track
if t < 0 || t >= len(v.d.Song.Score.Tracks) {
return intRange{1, 1}
return IntRange{1, 1}
}
return intRange{1, (*Model)(v).remainingVoices(v.linkInstrTrack, true) + v.d.Song.Score.Tracks[t].NumVoices}
}
func (v *TrackVoices) change(kind string) func() {
return (*Model)(v).change("TrackVoices."+kind, SongChange, MinorChange)
return IntRange{1, (*Model)(v).remainingVoices(v.linkInstrTrack, true) + v.d.Song.Score.Tracks[t].NumVoices}
}

View File

@ -46,14 +46,14 @@ func (mwc *myWriteCloser) Close() error {
func (s *modelFuzzState) Iterate(yield func(string, func(p string, t *testing.T)) bool, seed int) {
// Ints
s.IterateInt("InstrumentVoices", s.model.InstrumentVoices().Int(), yield, seed)
s.IterateInt("TrackVoices", s.model.TrackVoices().Int(), yield, seed)
s.IterateInt("SongLength", s.model.SongLength().Int(), yield, seed)
s.IterateInt("BPM", s.model.BPM().Int(), yield, seed)
s.IterateInt("RowsPerPattern", s.model.RowsPerPattern().Int(), yield, seed)
s.IterateInt("RowsPerBeat", s.model.RowsPerBeat().Int(), yield, seed)
s.IterateInt("Step", s.model.Step().Int(), yield, seed)
s.IterateInt("Octave", s.model.Octave().Int(), yield, seed)
s.IterateInt("InstrumentVoices", s.model.InstrumentVoices(), yield, seed)
s.IterateInt("TrackVoices", s.model.TrackVoices(), yield, seed)
s.IterateInt("SongLength", s.model.SongLength(), yield, seed)
s.IterateInt("BPM", s.model.BPM(), yield, seed)
s.IterateInt("RowsPerPattern", s.model.RowsPerPattern(), yield, seed)
s.IterateInt("RowsPerBeat", s.model.RowsPerBeat(), yield, seed)
s.IterateInt("Step", s.model.Step(), yield, seed)
s.IterateInt("Octave", s.model.Octave(), yield, seed)
// Lists
s.IterateList("Instruments", s.model.Instruments().List(), yield, seed)
s.IterateList("Units", s.model.Units().List(), yield, seed)
@ -135,7 +135,7 @@ func (s *modelFuzzState) Iterate(yield func(string, func(p string, t *testing.T)
func (s *modelFuzzState) IterateInt(name string, i tracker.Int, yield func(string, func(p string, t *testing.T)) bool, seed int) {
r := i.Range()
yield(name+".Set", func(p string, t *testing.T) {
i.Set(seed%(r.Max-r.Min+10) - 5 + r.Min)
i.SetValue(seed%(r.Max-r.Min+10) - 5 + r.Min)
})
yield(name+".Value", func(p string, t *testing.T) {
if v := i.Value(); v < r.Min || v > r.Max {

View File

@ -12,7 +12,7 @@ import (
type (
Parameter interface {
IntData
IntValue
Type() ParameterType
Name() string
Hint() ParameterHint
@ -61,12 +61,6 @@ const (
func (m *Model) Params() *Params { return (*Params)(m) }
// parameter methods
func (p parameter) change(kind string) func() {
return p.m.change("Parameter."+kind, PatchChange, MinorChange)
}
// ParamList
func (pl *Params) List() List { return List{pl} }
@ -151,17 +145,21 @@ func (pl *Params) Iterate(yield ParamYieldFunc) {
// NamedParameter
func (p NamedParameter) Name() string { return p.up.Name }
func (p NamedParameter) Range() intRange { return intRange{Min: p.up.MinValue, Max: p.up.MaxValue} }
func (p NamedParameter) Value() int { return p.unit.Parameters[p.up.Name] }
func (p NamedParameter) setValue(value int) { p.unit.Parameters[p.up.Name] = value }
func (p NamedParameter) Name() string { return p.up.Name }
func (p NamedParameter) Range() IntRange { return IntRange{Min: p.up.MinValue, Max: p.up.MaxValue} }
func (p NamedParameter) Value() int { return p.unit.Parameters[p.up.Name] }
func (p NamedParameter) SetValue(value int) bool {
defer p.m.change("Parameter"+p.Name(), PatchChange, MinorChange)()
p.unit.Parameters[p.up.Name] = value
return true
}
func (p NamedParameter) Reset() {
v, ok := defaultUnits[p.unit.Type].Parameters[p.up.Name]
if !ok || p.unit.Parameters[p.up.Name] == v {
return
}
defer p.parameter.change("Reset")()
defer p.m.change("Reset"+p.Name(), PatchChange, MinorChange)()
p.unit.Parameters[p.up.Name] = v
}
@ -220,7 +218,7 @@ func (p NamedParameter) Unit() sointu.Unit {
func (p GmDlsEntryParameter) Name() string { return "sample" }
func (p GmDlsEntryParameter) Type() ParameterType { return IntegerParameter }
func (p GmDlsEntryParameter) Range() intRange { return intRange{Min: 0, Max: len(GmDlsEntries)} }
func (p GmDlsEntryParameter) Range() IntRange { return IntRange{Min: 0, Max: len(GmDlsEntries)} }
func (p GmDlsEntryParameter) LargeStep() int { return 16 }
func (p GmDlsEntryParameter) Reset() { return }
@ -232,15 +230,17 @@ func (p GmDlsEntryParameter) Value() int {
return 0
}
func (p GmDlsEntryParameter) setValue(v int) {
func (p GmDlsEntryParameter) SetValue(v int) bool {
if v < 1 || v > len(GmDlsEntries) {
return
return false
}
defer p.m.change("GmDlsEntryParameter", PatchChange, MinorChange)()
e := GmDlsEntries[v-1]
p.unit.Parameters["samplestart"] = e.Start
p.unit.Parameters["loopstart"] = e.LoopStart
p.unit.Parameters["looplength"] = e.LoopLength
p.unit.Parameters["transpose"] = 64 + e.SuggestedTranspose
return true
}
func (p GmDlsEntryParameter) Hint() ParameterHint {
@ -265,15 +265,17 @@ func (p DelayTimeParameter) Value() int {
return p.unit.VarArgs[p.index]
}
func (p DelayTimeParameter) setValue(v int) {
func (p DelayTimeParameter) SetValue(v int) bool {
defer p.m.change("DelayTimeParameter", PatchChange, MinorChange)()
p.unit.VarArgs[p.index] = v
return true
}
func (p DelayTimeParameter) Range() intRange {
func (p DelayTimeParameter) Range() IntRange {
if p.unit.Parameters["notetracking"] == 2 {
return intRange{Min: 1, Max: 576}
return IntRange{Min: 1, Max: 576}
}
return intRange{Min: 1, Max: 65535}
return IntRange{Min: 1, Max: 65535}
}
func (p DelayTimeParameter) Hint() ParameterHint {
@ -325,7 +327,7 @@ func (p DelayTimeParameter) Hint() ParameterHint {
func (p DelayLinesParameter) Name() string { return "delaylines" }
func (p DelayLinesParameter) Type() ParameterType { return IntegerParameter }
func (p DelayLinesParameter) Range() intRange { return intRange{Min: 1, Max: 32} }
func (p DelayLinesParameter) Range() IntRange { return IntRange{Min: 1, Max: 32} }
func (p DelayLinesParameter) LargeStep() int { return 4 }
func (p DelayLinesParameter) Reset() { return }
@ -341,7 +343,8 @@ func (p DelayLinesParameter) Value() int {
return val
}
func (p DelayLinesParameter) setValue(v int) {
func (p DelayLinesParameter) SetValue(v int) bool {
defer p.m.change("DelayLinesParameter", PatchChange, MinorChange)()
targetLines := v
if p.unit.Parameters["stereo"] == 1 {
targetLines *= 2
@ -350,13 +353,14 @@ func (p DelayLinesParameter) setValue(v int) {
p.unit.VarArgs = append(p.unit.VarArgs, 1)
}
p.unit.VarArgs = p.unit.VarArgs[:targetLines]
return true
}
// ReverbParameter
func (p ReverbParameter) Name() string { return "reverb" }
func (p ReverbParameter) Type() ParameterType { return IntegerParameter }
func (p ReverbParameter) Range() intRange { return intRange{Min: 0, Max: len(reverbs)} }
func (p ReverbParameter) Range() IntRange { return IntRange{Min: 0, Max: len(reverbs)} }
func (p ReverbParameter) LargeStep() int { return 1 }
func (p ReverbParameter) Reset() { return }
@ -367,15 +371,17 @@ func (p ReverbParameter) Value() int {
return i + 1
}
func (p ReverbParameter) setValue(v int) {
func (p ReverbParameter) SetValue(v int) bool {
if v < 1 || v > len(reverbs) {
return
return false
}
defer p.m.change("ReverbParameter", PatchChange, MinorChange)()
entry := reverbs[v-1]
p.unit.Parameters["stereo"] = entry.stereo
p.unit.Parameters["notetracking"] = 0
p.unit.VarArgs = make([]int, len(entry.varArgs))
copy(p.unit.VarArgs, entry.varArgs)
return true
}
func (p ReverbParameter) Hint() ParameterHint {

View File

@ -67,10 +67,10 @@ func NewScopeModel(broker *Broker, bpm int) *ScopeModel {
func (s *ScopeModel) Waveform() RingBuffer[[2]float32] { return s.waveForm }
func (s *ScopeModel) Once() Bool { return MakeEnabledBool((*SignalOnce)(s)) }
func (s *ScopeModel) Wrap() Bool { return MakeEnabledBool((*SignalWrap)(s)) }
func (s *ScopeModel) LengthInBeats() *SignalLengthInBeats { return (*SignalLengthInBeats)(s) }
func (s *ScopeModel) TriggerChannel() *TriggerChannel { return (*TriggerChannel)(s) }
func (s *ScopeModel) Once() Bool { return MakeEnabledBool((*SignalOnce)(s)) }
func (s *ScopeModel) Wrap() Bool { return MakeEnabledBool((*SignalWrap)(s)) }
func (s *ScopeModel) LengthInBeats() Int { return MakeInt((*SignalLengthInBeats)(s)) }
func (s *ScopeModel) TriggerChannel() Int { return MakeInt((*TriggerChannel)(s)) }
func (m *SignalOnce) Value() bool { return m.once }
func (m *SignalOnce) SetValue(val bool) { m.once = val }
@ -78,22 +78,17 @@ func (m *SignalOnce) SetValue(val bool) { m.once = val }
func (m *SignalWrap) Value() bool { return m.wrap }
func (m *SignalWrap) SetValue(val bool) { m.wrap = val }
func (m *SignalLengthInBeats) Int() Int { return Int{m} }
func (m *SignalLengthInBeats) Value() int { return m.lengthInBeats }
func (m *SignalLengthInBeats) setValue(val int) {
func (m *SignalLengthInBeats) SetValue(val int) bool {
m.lengthInBeats = val
(*ScopeModel)(m).updateBufferLength()
return true
}
func (m *SignalLengthInBeats) Enabled() bool { return true }
func (m *SignalLengthInBeats) Range() intRange { return intRange{1, 999} }
func (m *SignalLengthInBeats) change(string) func() { return func() {} }
func (m *SignalLengthInBeats) Range() IntRange { return IntRange{1, 999} }
func (m *TriggerChannel) Int() Int { return Int{m} }
func (m *TriggerChannel) Value() int { return m.triggerChannel }
func (m *TriggerChannel) setValue(val int) { m.triggerChannel = val }
func (m *TriggerChannel) Enabled() bool { return true }
func (m *TriggerChannel) Range() intRange { return intRange{0, vm.MAX_VOICES} }
func (m *TriggerChannel) change(string) func() { return func() {} }
func (m *TriggerChannel) Value() int { return m.triggerChannel }
func (m *TriggerChannel) SetValue(val int) bool { m.triggerChannel = val; return true }
func (m *TriggerChannel) Range() IntRange { return IntRange{0, vm.MAX_VOICES} }
func (s *ScopeModel) ProcessAudioBuffer(bufPtr *sointu.AudioBuffer) {
if s.wrap {