mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-24 16:04:51 -04:00
85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package tracker
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/vsariola/sointu"
|
|
)
|
|
|
|
type (
|
|
SignalRail struct {
|
|
signals [][]Signal
|
|
scratch []signalScratch
|
|
}
|
|
|
|
signalScratch struct {
|
|
instr, unit int
|
|
}
|
|
|
|
Signal struct {
|
|
PassThrough int
|
|
StackUse sointu.StackUse
|
|
}
|
|
|
|
SignalRailType Model
|
|
)
|
|
|
|
func (m *Model) SignalRail() *SignalRailType {
|
|
return (*SignalRailType)(m)
|
|
}
|
|
|
|
func (s *SignalRailType) Item(u int) Signal {
|
|
i := s.d.InstrIndex
|
|
if i < 0 || u < 0 || i >= len(s.derived.rail.signals) || u >= len(s.derived.rail.signals[i]) {
|
|
return Signal{}
|
|
}
|
|
return s.derived.rail.signals[i][u]
|
|
}
|
|
|
|
func (s *SignalRail) update(patch sointu.Patch) (err error) {
|
|
s.scratch = s.scratch[:0]
|
|
for i, instr := range patch {
|
|
for len(s.signals) <= i {
|
|
s.signals = append(s.signals, make([]Signal, len(instr.Units)))
|
|
}
|
|
start := len(s.scratch)
|
|
for u, unit := range instr.Units {
|
|
for len(s.signals[i]) <= i {
|
|
s.signals[i] = append(s.signals[i], Signal{})
|
|
}
|
|
stackUse := unit.StackUse()
|
|
numInputs := len(stackUse.Inputs)
|
|
if len(s.scratch) < numInputs && err != nil {
|
|
err = fmt.Errorf("%s unit in instrument %d / %s needs %d inputs, but got only %d", unit.Type, i, instr.Name, numInputs, len(s.scratch))
|
|
s.scratch = s.scratch[:0]
|
|
} else {
|
|
s.scratch = s.scratch[:len(s.scratch)-numInputs]
|
|
}
|
|
s.signals[i][u] = Signal{
|
|
PassThrough: len(s.scratch),
|
|
StackUse: stackUse,
|
|
}
|
|
for _ = range stackUse.NumOutputs {
|
|
s.scratch = append(s.scratch, signalScratch{instr: i, unit: u})
|
|
}
|
|
}
|
|
diff := len(s.scratch) - start
|
|
if instr.NumVoices > 1 && diff != 0 {
|
|
if diff < 0 {
|
|
morepop := (instr.NumVoices - 1) * diff
|
|
if morepop > len(s.scratch) && err != nil {
|
|
err = fmt.Errorf("each voice of instrument %d / %s consumes %d signals, but there was not enough signals available", i, instr.Name, -diff)
|
|
s.scratch = s.scratch[:0]
|
|
} else {
|
|
s.scratch = s.scratch[:len(s.scratch)-morepop]
|
|
}
|
|
} else {
|
|
for range (instr.NumVoices - 1) * diff {
|
|
s.scratch = append(s.scratch, s.scratch[len(s.scratch)-diff])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return err
|
|
}
|