feat(tracker): multithreading is enabled with a separate bool toggle

This commit is contained in:
5684185+vsariola@users.noreply.github.com
2026-01-31 20:50:00 +02:00
parent 4bb5df9c87
commit 287bd036a6
7 changed files with 44 additions and 25 deletions

View File

@ -31,9 +31,10 @@ type SongPanel struct {
CPUExpander *Expander
SpectrumExpander *Expander
WeightingTypeBtn *Clickable
OversamplingBtn *Clickable
SynthBtn *Clickable
WeightingTypeBtn *Clickable
OversamplingBtn *Clickable
SynthBtn *Clickable
MultithreadingBtn *Clickable
BPM *NumericUpDownState
RowsPerPattern *NumericUpDownState
@ -67,9 +68,10 @@ func NewSongPanel(tr *Tracker) *SongPanel {
MenuBar: NewMenuBar(tr),
PlayBar: NewPlayBar(),
WeightingTypeBtn: new(Clickable),
OversamplingBtn: new(Clickable),
SynthBtn: new(Clickable),
WeightingTypeBtn: new(Clickable),
OversamplingBtn: new(Clickable),
SynthBtn: new(Clickable),
MultithreadingBtn: new(Clickable),
SongSettingsExpander: &Expander{Expanded: true},
ScopeExpander: &Expander{},
@ -159,7 +161,8 @@ func (t *SongPanel) layoutSongOptions(gtx C) D {
return cpuLabel.Layout(gtx)
}
synthBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.SynthBtn, tr.Model.Play().SyntherName(), "")
synthBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.SynthBtn, tr.Model.Play().SyntherIndex().String(), "")
multithreadingBtn := ToggleIconBtn(tr.Play().Multithreading(), tr.Theme, t.MultithreadingBtn, icons.ToggleCheckBoxOutlineBlank, icons.ToggleCheckBox, "Threading disabled", "Threading enabled")
listItem := func(gtx C, index int) D {
switch index {
@ -198,6 +201,7 @@ func (t *SongPanel) layoutSongOptions(gtx C) D {
return layout.Flex{Axis: layout.Vertical, Alignment: layout.End}.Layout(gtx,
layout.Rigid(func(gtx C) D { return layoutSongOptionRow(gtx, tr.Theme, "Load", cpuEnlargedWidget) }),
layout.Rigid(func(gtx C) D { return layoutSongOptionRow(gtx, tr.Theme, "Synth", synthBtn.Layout) }),
layout.Rigid(func(gtx C) D { return layoutSongOptionRow(gtx, tr.Theme, "Multithreading", multithreadingBtn.Layout) }),
)
},
)

View File

@ -237,7 +237,7 @@ func (m *InstrModel) warnAboutCrossThreadSends() {
func (m *InstrModel) warnNoMultithreadSupport() {
for _, instr := range m.d.Song.Patch {
if instr.ThreadMaskM1 > 0 && !m.synthers[m.syntherIndex].SupportsMultithreading() {
if instr.ThreadMaskM1 > 0 && !m.curSynther.SupportsMultithreading() {
(*Alerts)(m).AddNamed("NoMultithreadSupport", "The current synth does not support multithreading and the patch was configured to use more than one thread", Warning)
return
}

View File

@ -82,8 +82,10 @@ type (
alerts []Alert
dialog Dialog
syntherIndex int // the index of the synther used to create new synths
synthers []sointu.Synther // the synther used to create new synths
syntherIndex int // the index of the synther used to create new synths
synthers []sointu.Synther // the synther used to create new synths
multithreading bool // is the multithreading enabled or not
curSynther sointu.Synther // the current synther, either multithreaded or not depending on multithreading
broker *Broker
@ -197,6 +199,7 @@ func NewModel(broker *Broker, synthers []sointu.Synther, midiContext MIDIContext
m.derived.searchResults = make([]string, 0, len(sointu.UnitNames))
m.Unit().updateDerivedUnitSearch()
m.MIDI().Refresh().Do()
m.Play().setSynther(0, false)
go runDetector(broker)
go runSpecAnalyzer(broker)
return m

View File

@ -1,6 +1,9 @@
package tracker
import "github.com/vsariola/sointu"
import (
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/vm"
)
type Play Model
@ -175,11 +178,7 @@ type playSyntherIndex Play
func (v *playSyntherIndex) Value() int { return v.syntherIndex }
func (v *playSyntherIndex) Range() RangeInclusive { return RangeInclusive{0, len(v.synthers) - 1} }
func (v *playSyntherIndex) SetValue(value int) bool {
if value < 0 || value >= len(v.synthers) {
return false
}
v.syntherIndex = value
TrySend(v.broker.ToPlayer, any(v.synthers[value]))
(*Play)(v).setSynther(value, v.multithreading)
return true
}
func (v *playSyntherIndex) StringOf(value int) string {
@ -189,8 +188,26 @@ func (v *playSyntherIndex) StringOf(value int) string {
return v.synthers[value].Name()
}
// SyntherName returns the name of the currently selected synther.
func (v *Play) SyntherName() string { return v.synthers[v.syntherIndex].Name() }
func (m *Play) Multithreading() Bool { return MakeBool((*playMultithreading)(m)) }
type playMultithreading Play
func (v *playMultithreading) Value() bool { return v.multithreading }
func (v *playMultithreading) SetValue(value bool) { (*Play)(v).setSynther(v.syntherIndex, value) }
func (m *Play) setSynther(index int, multithreading bool) {
if index < 0 || index >= len(m.synthers) {
return
}
m.syntherIndex = index
m.multithreading = multithreading
if multithreading {
m.curSynther = vm.MakeMultithreadSynther(m.synthers[m.syntherIndex])
} else {
m.curSynther = m.synthers[m.syntherIndex]
}
TrySend(m.broker.ToPlayer, any(m.curSynther))
}
// CPULoad fills the given buffer with CPU load information and returns the
// number of threads filled.

View File

@ -346,7 +346,7 @@ func (m *SongModel) WriteWav(w io.WriteCloser, pcm16 bool) {
b := make([]byte, 32+2)
rand.Read(b)
name := fmt.Sprintf("%x", b)[2 : 32+2]
data, err := sointu.Play(m.synthers[m.syntherIndex], song, func(p float32) {
data, err := sointu.Play(m.curSynther, song, func(p float32) {
txt := fmt.Sprintf("Exporting song: %.0f%%", p*100)
TrySend(m.broker.ToModel, MsgToModel{Data: Alert{Message: txt, Priority: Info, Name: name, Duration: defaultAlertDuration}})
}) // render the song to calculate its length