tracker

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2025 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package tracker contains the data model for the Sointu tracker GUI.

Index

Constants

View Source
const (
	NoDialog = iota
	SaveAsExplorer
	NewSongChanges
	NewSongSaveExplorer
	OpenSongChanges
	OpenSongSaveExplorer
	OpenSongOpenExplorer
	Export
	ExportFloatExplorer
	ExportInt16Explorer
	QuitChanges
	QuitSaveExplorer
	License
)
View Source
const MAX_INTEGRATED_DATA = 10 * 60 * 60 // 1 hour of samples at 10 Hz (100 ms per sample)

Variables

View Source
var ErrInvalidRows = errors.New("rows per beat and rows per pattern must be greater than 1")
View Source
var ErrNotFinished = errors.New("the recording was not finished")
View Source
var GmDlsEntries = []GmDlsEntry{}/* 495 elements not displayed */

GmDlsEntries is a list of all samples in the gm.dls file. Do not modify during runtime.

Functions

func Insert added in v0.5.0

func Insert[T any, S ~[]T](slice S, index int, inserted ...T) (ret S, ok bool)

Insert inserts elements into a slice at the given index. If the index is out of bounds, the function returns false.

func NumPresets added in v0.4.1

func NumPresets() int

func RemoveUnusedUnitParameters added in v0.5.0

func RemoveUnusedUnitParameters(instr *sointu.Instrument) bool

RemoveUnusedUnitParameters removes any parameters from the instrument that are not valid for the unit type. It returns true if any parameters were removed.

func TimeoutReceive added in v0.5.0

func TimeoutReceive[T any](c <-chan T, t time.Duration) (v T, ok bool)

TimeoutReceive is a helper function to block until a value is received from a channel, or timing out after t. ok will be false if the timeout occurred or if the channel is closed.

func TrySend added in v0.5.0

func TrySend[T any](c chan<- T, v T) bool

TrySend is a helper function to send a value to a channel if it is not full. It is guaranteed to be non-blocking. Return true if the value was sent, false otherwise.

func VoiceSlice added in v0.5.0

func VoiceSlice[T any, S ~[]T, P sointu.NumVoicerPointer[T]](slice S, ranges ...Range) (ret S, ok bool)

VoiceSlice works similar to the Slice function, but takes a slice of NumVoicer:s and treats it as a "virtual slice", with element repeated by the number of voices it has. NumVoicer interface is implemented at least by sointu.Tracks and sointu.Instruments. For example, if parameter "slice" has three elements, returning GetNumVoices 2, 1, and 3, the VoiceSlice thinks of this as a virtual slice of 6 elements [0,0,1,2,2,2]. Then, the "ranges" parameter are slicing ranges to this virtual slice. Continuing with the example, if "ranges" was [2,5), the virtual slice would be [1,2,2], and the function would return a slice with two elements: first with NumVoices 1 and second with NumVoices 2. If multiple ranges are given, multiple virtual slices are concatenated. However, when doing so, splitting an element is not allowed. In the previous example, if the ranges were [1,3) and [0,1), the resulting concatenated virtual slice would be [0,1,0], and here the 0 element would be split. This is to avoid accidentally making shallow copies of reference types.

Types

type Action added in v0.4.0

type Action struct {
	// contains filtered or unexported fields
}

Action describes a user action that can be performed on the model, which can be initiated by calling the Do() method. It is usually initiated by a button press or a menu item. Action advertises whether it is enabled, so UI can e.g. gray out buttons when the underlying action is not allowed. Action also implements the Doer and Enabler interfaces, but guarding that the underlying doer will never get called if enabler return false. That's why the doer and enabler are private fields, so that they cannot be called directly from outside, circumventing the Enabled() check.

func MakeAction added in v0.5.0

func MakeAction(doerEnabler interface {
	Doer
	Enabler
}) Action

simple version for when both doer and enabler are the same

func MakeAction2 added in v0.5.0

func MakeAction2(doer Doer, enabler Enabler) Action

a version for cases where doer and enabler are different

func MakeEnabledAction added in v0.5.0

func MakeEnabledAction(doer Doer) Action

func (Action) Do added in v0.4.0

func (a Action) Do()

func (Action) Enabled added in v0.5.0

func (a Action) Enabled() bool

type AddInstrument added in v0.5.0

type AddInstrument Model

func (*AddInstrument) Do added in v0.5.0

func (m *AddInstrument) Do()

func (*AddInstrument) Enabled added in v0.5.0

func (m *AddInstrument) Enabled() bool

type AddOctave added in v0.5.0

type AddOctave Model

func (*AddOctave) Do added in v0.5.0

func (m *AddOctave) Do()

type AddOrderRow added in v0.5.0

type AddOrderRow struct {
	Before bool
	*Model
}

func (AddOrderRow) Do added in v0.5.0

func (a AddOrderRow) Do()

type AddSemitone added in v0.5.0

type AddSemitone Model

func (*AddSemitone) Do added in v0.5.0

func (m *AddSemitone) Do()

type AddTrack added in v0.5.0

type AddTrack Model

func (*AddTrack) Do added in v0.5.0

func (m *AddTrack) Do()

func (*AddTrack) Enabled added in v0.5.0

func (m *AddTrack) Enabled() bool

type AddUnit added in v0.5.0

type AddUnit struct {
	Before bool
	*Model
}

func (AddUnit) Do added in v0.5.0

func (a AddUnit) Do()

type Alert added in v0.4.0

type Alert struct {
	Name      string
	Priority  AlertPriority
	Message   string
	Duration  time.Duration
	FadeLevel float64
}

type AlertPriority added in v0.4.0

type AlertPriority int
const (
	None AlertPriority = iota
	Info
	Warning
	Error
)

type AlertYieldFunc added in v0.4.0

type AlertYieldFunc func(index int, alert Alert) bool

type Alerts added in v0.4.0

type Alerts Model

func (*Alerts) Add added in v0.4.0

func (m *Alerts) Add(message string, priority AlertPriority)

func (*Alerts) AddAlert added in v0.4.0

func (m *Alerts) AddAlert(a Alert)

func (*Alerts) AddNamed added in v0.4.0

func (m *Alerts) AddNamed(name, message string, priority AlertPriority)

func (*Alerts) Iterate added in v0.4.0

func (m *Alerts) Iterate(yield func(index int, alert Alert) bool)

func (Alerts) Len added in v0.4.0

func (m Alerts) Len() int

func (Alerts) Less added in v0.4.0

func (m Alerts) Less(i, j int) bool

func (*Alerts) Pop added in v0.4.0

func (m *Alerts) Pop() any

func (*Alerts) Push added in v0.4.0

func (m *Alerts) Push(x any)

func (Alerts) Swap added in v0.4.0

func (m Alerts) Swap(i, j int)

func (*Alerts) Update added in v0.4.0

func (m *Alerts) Update(d time.Duration) (animating bool)

type BPM added in v0.4.0

type BPM Model

func (*BPM) Range added in v0.4.0

func (v *BPM) Range() IntRange

func (*BPM) SetValue added in v0.5.0

func (v *BPM) SetValue(value int) bool

func (*BPM) Value added in v0.4.0

func (v *BPM) Value() int

type BPMMsg added in v0.4.0

type BPMMsg struct {
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type Bool added in v0.4.0

type Bool struct {
	// contains filtered or unexported fields
}

func MakeBool added in v0.5.0

func MakeBool(valueEnabler interface {
	BoolValue
	Enabler
}) Bool

func MakeEnabledBool added in v0.5.0

func MakeEnabledBool(value BoolValue) Bool

func (Bool) Enabled added in v0.5.0

func (v Bool) Enabled() bool

func (Bool) SetValue added in v0.5.0

func (v Bool) SetValue(value bool)

func (Bool) Toggle added in v0.4.0

func (v Bool) Toggle()

func (Bool) Value added in v0.5.0

func (v Bool) Value() bool

type BoolValue added in v0.5.0

type BoolValue interface {
	Value() bool
	SetValue(bool)
}

type Broker added in v0.5.0

type Broker struct {
	ToModel    chan MsgToModel
	ToPlayer   chan any // TODO: consider using a sum type here, for a bit more type safety. See: https://www.jerf.org/iri/post/2917/
	ToDetector chan MsgToDetector
	ToGUI      chan any

	CloseDetector chan struct{}
	CloseGUI      chan struct{}

	FinishedGUI      chan struct{}
	FinishedDetector chan struct{}
	// contains filtered or unexported fields
}

Broker is the centralized message broker for the tracker. It is used to communicate between the player, the model, and the loudness detector. At the moment, the broker is just many-to-one communication, implemented with one channel for each recipient. Additionally, the broker has a sync.pool for *sointu.AudioBuffers, from which the player can get and return buffers to pass buffers around without allocating new memory every time. We can later consider making many-to-many types of communication and more complex routing logic to the Broker if needed.

For closing goroutines, the broker has two channels for each goroutine: CloseXXX and FinishedXXX. The CloseXXX channel has a capacity of 1, so you can always send a empty message (struct{}{}) to it without blocking. If the channel is already full, that means someone else has already requested its closure and the goroutine is already closing, so dropping the message is fine. Then, FinishedXXX is used to signal that a goroutine has succesfully closed and cleaned up. Nothing is ever sent to the channel, it is only closed. You can wait until the goroutines is done closing with "<- FinishedXXX", which for avoiding deadlocks can be combined with a timeout:

select {
  case <-FinishedXXX:
  case <-time.After(3 * time.Second):
}

func NewBroker added in v0.5.0

func NewBroker() *Broker

func (*Broker) GetAudioBuffer added in v0.5.0

func (b *Broker) GetAudioBuffer() *sointu.AudioBuffer

GetAudioBuffer returns an audio buffer from the buffer pool. The buffer is guaranteed to be empty. After using the buffer, it should be returned to the pool with PutAudioBuffer.

func (*Broker) MIDIChannel added in v0.5.0

func (b *Broker) MIDIChannel() chan<- any

func (*Broker) PutAudioBuffer added in v0.5.0

func (b *Broker) PutAudioBuffer(buf *sointu.AudioBuffer)

PutAudioBuffer returns an audio buffer to the buffer pool. If the buffer is not empty, its length is resetted (but capacity kept) before returning it to the pool.

type Cancel added in v0.5.0

type Cancel Model

func (*Cancel) Do added in v0.5.0

func (m *Cancel) Do()

type ChangeSeverity added in v0.4.0

type ChangeSeverity int

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

const (
	MajorChange ChangeSeverity = iota
	MinorChange
)

type ChangeType added in v0.4.0

type ChangeType int

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

const (
	NoChange    ChangeType = 0
	PatchChange ChangeType = 1 << iota
	ScoreChange
	BPMChange
	RowsPerBeatChange
	SongChange ChangeType = PatchChange | ScoreChange | BPMChange | RowsPerBeatChange
)

type ChooseSendSource added in v0.5.0

type ChooseSendSource struct {
	ID int
	*Model
}

func (ChooseSendSource) Do added in v0.5.0

func (s ChooseSendSource) Do()

type ChooseSendTarget added in v0.5.0

type ChooseSendTarget struct {
	ID   int
	Port int
	*Model
}

func (ChooseSendTarget) Do added in v0.5.0

func (s ChooseSendTarget) Do()

type ClearUnit added in v0.5.0

type ClearUnit Model

func (*ClearUnit) Do added in v0.5.0

func (m *ClearUnit) Do()

func (*ClearUnit) Enabled added in v0.5.0

func (m *ClearUnit) Enabled() bool

type CommentExpanded added in v0.4.0

type CommentExpanded Model

func (*CommentExpanded) SetValue added in v0.5.0

func (m *CommentExpanded) SetValue(val bool)

func (*CommentExpanded) Value added in v0.4.0

func (m *CommentExpanded) Value() bool

type Cursor added in v0.4.0

type Cursor struct {
	Track int
	sointu.SongPos
}

Cursor identifies a row and a track in a song score.

type Decibel added in v0.5.0

type Decibel float32

type DeleteInstrument added in v0.5.0

type DeleteInstrument Model

func (*DeleteInstrument) Do added in v0.5.0

func (m *DeleteInstrument) Do()

func (*DeleteInstrument) Enabled added in v0.5.0

func (m *DeleteInstrument) Enabled() bool

type DeleteOrderRow added in v0.5.0

type DeleteOrderRow struct {
	Backwards bool
	*Model
}

func (DeleteOrderRow) Do added in v0.5.0

func (d DeleteOrderRow) Do()

type DeleteTrack added in v0.5.0

type DeleteTrack Model

func (*DeleteTrack) Do added in v0.5.0

func (m *DeleteTrack) Do()

func (*DeleteTrack) Enabled added in v0.5.0

func (m *DeleteTrack) Enabled() bool

type DeleteUnit added in v0.5.0

type DeleteUnit Model

func (*DeleteUnit) Do added in v0.5.0

func (m *DeleteUnit) Do()

func (*DeleteUnit) Enabled added in v0.5.0

func (m *DeleteUnit) Enabled() bool

type Detector added in v0.5.0

type Detector struct {
	// contains filtered or unexported fields
}

func NewDetector added in v0.5.0

func NewDetector(b *Broker) *Detector

func (*Detector) Run added in v0.5.0

func (s *Detector) Run()

type DetectorResult added in v0.5.0

type DetectorResult struct {
	Loudness LoudnessResult
	Peaks    PeakResult
}

type DetectorWeighting added in v0.5.0

type DetectorWeighting Model

func (*DetectorWeighting) Range added in v0.5.0

func (v *DetectorWeighting) Range() IntRange

func (*DetectorWeighting) SetValue added in v0.5.0

func (v *DetectorWeighting) SetValue(value int) bool

func (*DetectorWeighting) Value added in v0.5.0

func (v *DetectorWeighting) Value() int

type Dialog added in v0.4.0

type Dialog int

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type DiscardSong added in v0.5.0

type DiscardSong Model

func (*DiscardSong) Do added in v0.5.0

func (m *DiscardSong) Do()

type DoFunc added in v0.5.0

type DoFunc func()

func (DoFunc) Do added in v0.5.0

func (d DoFunc) Do()

type Doer added in v0.5.0

type Doer interface {
	Do()
}

Doer is an interface that defines a single Do() method, which is called when an action is performed.

type EditNoteOff added in v0.5.0

type EditNoteOff Model

func (*EditNoteOff) Do added in v0.5.0

func (m *EditNoteOff) Do()

type Effect added in v0.4.0

type Effect Model

func (*Effect) SetValue added in v0.5.0

func (m *Effect) SetValue(val bool)

func (*Effect) Value added in v0.4.0

func (m *Effect) Value() bool

type Enabler added in v0.5.0

type Enabler interface {
	Enabled() bool
}

Enabler is an interface that defines a single Enabled() method, which is used by the UI to check if UI Action/Bool/Int etc. is enabled or not.

type Explore added in v0.4.0

type Explore struct {
	IsSave       bool         // true if this is a save operation, false if open operation
	IsSong       bool         // true if this is a song, false if instrument
	Continuation func(string) // function to call with the selected file path
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type ExportAction added in v0.5.0

type ExportAction Model

func (*ExportAction) Do added in v0.5.0

func (m *ExportAction) Do()

type ExportFloat added in v0.5.0

type ExportFloat Model

func (*ExportFloat) Do added in v0.5.0

func (m *ExportFloat) Do()

type ExportInt16 added in v0.5.0

type ExportInt16 Model

func (*ExportInt16) Do added in v0.5.0

func (m *ExportInt16) Do()

type FilePath added in v0.4.0

type FilePath Model

func (*FilePath) SetValue added in v0.5.0

func (v *FilePath) SetValue(value string) bool

func (*FilePath) Value added in v0.4.0

func (v *FilePath) Value() string

type Follow added in v0.5.0

type Follow Model

func (*Follow) SetValue added in v0.5.0

func (m *Follow) SetValue(val bool)

func (*Follow) Value added in v0.5.0

func (m *Follow) Value() bool

type ForceQuit added in v0.5.0

type ForceQuit Model

func (*ForceQuit) Do added in v0.5.0

func (m *ForceQuit) Do()

type GUIMessageKind added in v0.5.0

type GUIMessageKind int
const (
	GUIMessageKindNone GUIMessageKind = iota
	GUIMessageCenterOnRow
	GUIMessageEnsureCursorVisible
)

type GmDlsEntry

type GmDlsEntry struct {
	Start              int    // sample start offset in words
	LoopStart          int    // loop start offset in words
	LoopLength         int    // loop length in words
	SuggestedTranspose int    // suggested transpose in semitones, so that all samples play at same pitch
	Name               string // sample Name
}

GmDlsEntry is a single sample entry from the gm.dls file

type InstrEnlarged added in v0.4.0

type InstrEnlarged Model

func (*InstrEnlarged) SetValue added in v0.5.0

func (m *InstrEnlarged) SetValue(val bool)

func (*InstrEnlarged) Value added in v0.4.0

func (m *InstrEnlarged) Value() bool

type InstrumentComment added in v0.4.0

type InstrumentComment Model

func (*InstrumentComment) SetValue added in v0.5.0

func (v *InstrumentComment) SetValue(value string) bool

func (*InstrumentComment) Value added in v0.4.0

func (v *InstrumentComment) Value() string

type InstrumentName added in v0.4.0

type InstrumentName Model

func (*InstrumentName) SetValue added in v0.5.0

func (v *InstrumentName) SetValue(value string) bool

func (*InstrumentName) Value added in v0.4.0

func (v *InstrumentName) Value() string

type InstrumentPresetYieldFunc added in v0.4.0

type InstrumentPresetYieldFunc func(index int, item string) (ok bool)

type InstrumentVoices added in v0.4.0

type InstrumentVoices Model

func (*InstrumentVoices) Range added in v0.4.0

func (v *InstrumentVoices) Range() IntRange

func (*InstrumentVoices) SetValue added in v0.5.0

func (m *InstrumentVoices) SetValue(value int) bool

func (*InstrumentVoices) Value added in v0.4.0

func (v *InstrumentVoices) Value() int

type Instruments added in v0.4.0

type Instruments Model // Instruments is a list of instruments, implementing ListData & MutableListData interfaces

func (*Instruments) Count added in v0.4.0

func (v *Instruments) Count() int

func (*Instruments) FirstID added in v0.4.0

func (v *Instruments) FirstID(i int) (id int, ok bool)

func (*Instruments) Item added in v0.4.0

func (v *Instruments) Item(i int) (name string, maxLevel float32, mute bool, ok bool)

func (*Instruments) List added in v0.4.0

func (v *Instruments) List() List

func (*Instruments) Selected added in v0.4.0

func (v *Instruments) Selected() int

func (*Instruments) Selected2 added in v0.4.0

func (v *Instruments) Selected2() int

func (*Instruments) SetSelected added in v0.4.0

func (v *Instruments) SetSelected(value int)

func (*Instruments) SetSelected2 added in v0.4.0

func (v *Instruments) SetSelected2(value int)

type Int added in v0.4.0

type Int struct {
	// contains filtered or unexported fields
}

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.

func MakeInt added in v0.5.0

func MakeInt(value IntValue) Int

func (Int) Add added in v0.4.0

func (v Int) Add(delta int) (ok bool)

func (Int) Range added in v0.5.0

func (v Int) Range() IntRange

func (Int) SetValue added in v0.5.0

func (v Int) SetValue(value int) (ok bool)

func (Int) Value added in v0.5.0

func (v Int) Value() int

type IntRange added in v0.5.0

type IntRange struct {
	Min, Max int
}

func (IntRange) Clamp added in v0.5.0

func (r IntRange) Clamp(value int) int

type IntValue added in v0.5.0

type IntValue interface {
	Value() int
	SetValue(int) bool // returns true if the value was changed
	Range() IntRange
}

type IsPlayingMsg added in v0.4.0

type IsPlayingMsg struct {
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type IsRecording added in v0.4.0

type IsRecording Model

func (*IsRecording) SetValue added in v0.5.0

func (m *IsRecording) SetValue(val bool)

func (*IsRecording) Value added in v0.4.0

func (m *IsRecording) Value() bool

type LinkInstrTrack added in v0.5.0

type LinkInstrTrack Model

func (*LinkInstrTrack) SetValue added in v0.5.0

func (m *LinkInstrTrack) SetValue(val bool)

func (*LinkInstrTrack) Value added in v0.5.0

func (m *LinkInstrTrack) Value() bool

type List added in v0.4.0

type List struct {
	ListData
}

func (List) CopyElements added in v0.4.0

func (v List) CopyElements() ([]byte, bool)

CopyElements copies the selected elements in a list. The list must implement the MutableListData interface. Returns the copied data, marshaled into byte slice, and true if successful.

func (List) DeleteElements added in v0.4.0

func (v List) DeleteElements(backwards bool) bool

DeleteElements deletes the selected elements in a list. The list must implement the MutableListData interface.

func (List) MoveElements added in v0.4.0

func (v List) MoveElements(delta int) bool

MoveElements moves the selected elements in a list by delta. The list must implement the MutableListData interface.

func (List) PasteElements added in v0.4.0

func (v List) PasteElements(data []byte) (ok bool)

PasteElements pastes the data into the list. The data is unmarshaled from the byte slice. The list must implement the MutableListData interface. Returns true if successful.

type ListData added in v0.4.0

type ListData interface {
	Selected() int
	Selected2() int
	SetSelected(int)
	SetSelected2(int)
	Count() int
}

type LoadPreset added in v0.4.0

type LoadPreset struct {
	Index int
	*Model
}

func (LoadPreset) Do added in v0.5.0

func (m LoadPreset) Do()

type Loop added in v0.4.0

type Loop struct {
	Start, Length int
}

Loop identifier the order rows, which are the loop positions Length = 0 means no loop is chosen, regardless of start

type LoopToggle added in v0.4.0

type LoopToggle Model

func (*LoopToggle) SetValue added in v0.5.0

func (t *LoopToggle) SetValue(val bool)

func (*LoopToggle) Value added in v0.4.0

func (m *LoopToggle) Value() bool

type LoudnessResult added in v0.5.0

type LoudnessResult [NumLoudnessTypes]Decibel

type LoudnessType added in v0.5.0

type LoudnessType int
const (
	LoudnessMomentary LoudnessType = iota
	LoudnessShortTerm
	LoudnessMaxMomentary
	LoudnessMaxShortTerm
	LoudnessIntegrated
	NumLoudnessTypes
)

type MIDIContext added in v0.5.0

type MIDIContext interface {
	InputDevices(yield func(MIDIDevice) bool)
	Close()
	HasDeviceOpen() bool
	TryToOpenBy(name string, first bool)
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type MIDIDevice added in v0.5.0

type MIDIDevice interface {
	String() string
	Open() error
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type Model

type Model struct {
	MIDI MIDIContext
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

func NewModel

func NewModel(broker *Broker, synthers []sointu.Synther, midiContext MIDIContext, recoveryFilePath string) *Model

NewModelPlayer creates a new model and a player that communicates with it

func (*Model) AddInstrument

func (m *Model) AddInstrument() Action

func (*Model) AddOctave added in v0.4.0

func (m *Model) AddOctave() Action

func (*Model) AddOrderRow

func (m *Model) AddOrderRow(before bool) Action

func (*Model) AddSemitone added in v0.4.0

func (m *Model) AddSemitone() Action

func (*Model) AddTrack

func (m *Model) AddTrack() Action

func (*Model) AddUnit

func (m *Model) AddUnit(before bool) Action

func (*Model) Alerts added in v0.4.0

func (m *Model) Alerts() *Alerts

func (*Model) BPM added in v0.4.0

func (m *Model) BPM() Int

func (*Model) Broker added in v0.5.0

func (m *Model) Broker() *Broker

func (*Model) CPULoad added in v0.5.0

func (m *Model) CPULoad() float64

func (*Model) Cancel added in v0.4.0

func (m *Model) Cancel() Action

func (*Model) ChangedSinceSave

func (m *Model) ChangedSinceSave() bool

func (*Model) ChooseSendSource added in v0.5.0

func (m *Model) ChooseSendSource(id int) Action

func (*Model) ChooseSendTarget added in v0.5.0

func (m *Model) ChooseSendTarget(id int, port int) Action

func (*Model) ClearUnit added in v0.4.0

func (m *Model) ClearUnit() Action

func (*Model) CommentExpanded added in v0.4.0

func (m *Model) CommentExpanded() Bool

func (*Model) DeleteInstrument

func (m *Model) DeleteInstrument() Action

func (*Model) DeleteOrderRow

func (m *Model) DeleteOrderRow(backwards bool) Action

func (*Model) DeleteTrack

func (m *Model) DeleteTrack() Action

func (*Model) DeleteUnit

func (m *Model) DeleteUnit() Action

func (*Model) DetectorResult added in v0.5.0

func (m *Model) DetectorResult() DetectorResult

func (*Model) DetectorWeighting added in v0.5.0

func (m *Model) DetectorWeighting() Int

func (*Model) Dialog added in v0.4.0

func (m *Model) Dialog() Dialog

func (*Model) DiscardSong added in v0.4.0

func (m *Model) DiscardSong() Action

func (*Model) EditNoteOff added in v0.4.0

func (m *Model) EditNoteOff() Action

func (*Model) Effect added in v0.4.0

func (m *Model) Effect() Bool

func (*Model) Export added in v0.4.0

func (m *Model) Export() Action

func (*Model) ExportFloat added in v0.4.0

func (m *Model) ExportFloat() Action

func (*Model) ExportInt16 added in v0.4.0

func (m *Model) ExportInt16() Action

func (*Model) FilePath

func (m *Model) FilePath() String

func (*Model) Follow added in v0.5.0

func (m *Model) Follow() Bool

func (*Model) ForceQuit added in v0.4.0

func (m *Model) ForceQuit() Action

func (*Model) InstrEnlarged added in v0.2.0

func (m *Model) InstrEnlarged() Bool

func (*Model) InstrumentComment added in v0.4.0

func (m *Model) InstrumentComment() String

func (*Model) InstrumentName added in v0.4.0

func (m *Model) InstrumentName() String

func (*Model) InstrumentVoices added in v0.4.0

func (m *Model) InstrumentVoices() Int

func (*Model) Instruments added in v0.4.0

func (m *Model) Instruments() *Instruments

func (*Model) IsChoosingSendTarget added in v0.5.0

func (m *Model) IsChoosingSendTarget() bool

func (*Model) IsRecording added in v0.4.0

func (m *Model) IsRecording() Bool

func (*Model) IterateInstrumentPresets added in v0.4.0

func (m *Model) IterateInstrumentPresets(yield InstrumentPresetYieldFunc)

func (*Model) LinkInstrTrack added in v0.5.0

func (m *Model) LinkInstrTrack() Bool

func (*Model) LoadInstrument added in v0.4.0

func (m *Model) LoadInstrument(r io.ReadCloser) bool

func (*Model) LoadPreset added in v0.4.0

func (m *Model) LoadPreset(index int) Action

func (*Model) Loop added in v0.4.0

func (m *Model) Loop() Loop

func (*Model) LoopToggle added in v0.4.0

func (m *Model) LoopToggle() Bool

func (*Model) MarshalRecovery added in v0.3.0

func (m *Model) MarshalRecovery() []byte

func (*Model) Mute added in v0.5.0

func (m *Model) Mute() Bool

Mute methods

func (*Model) NewSong added in v0.4.0

func (m *Model) NewSong() Action

func (*Model) NoteRows added in v0.4.0

func (m *Model) NoteRows() *NoteRows

func (*Model) Notes added in v0.4.0

func (m *Model) Notes() *Notes

func (*Model) Octave

func (m *Model) Octave() Int

func (*Model) OpenSong added in v0.4.0

func (m *Model) OpenSong() Action

func (*Model) Order added in v0.4.0

func (m *Model) Order() *Order

func (*Model) OrderRows added in v0.4.0

func (m *Model) OrderRows() *OrderRows

func (*Model) Oversampling added in v0.5.0

func (m *Model) Oversampling() Bool

func (*Model) Panic added in v0.2.0

func (m *Model) Panic() Bool

func (*Model) ParamVertList added in v0.5.0

func (m *Model) ParamVertList() *ParamVertList

func (*Model) Params added in v0.4.0

func (m *Model) Params() *Params

func (*Model) PatternUnique added in v0.5.0

func (m *Model) PatternUnique(track, pat int) bool

func (*Model) PlayCurrentPos added in v0.5.0

func (m *Model) PlayCurrentPos() Action

func (*Model) PlayFromLoopStart added in v0.5.0

func (m *Model) PlayFromLoopStart() Action

func (*Model) PlayPosition added in v0.2.0

func (m *Model) PlayPosition() sointu.SongPos

func (*Model) PlaySelected added in v0.5.0

func (m *Model) PlaySelected() Action

func (*Model) PlaySongRow added in v0.4.0

func (m *Model) PlaySongRow() int

func (*Model) PlaySongStart added in v0.5.0

func (m *Model) PlaySongStart() Action

func (*Model) Playing added in v0.2.0

func (m *Model) Playing() Bool

func (*Model) ProcessMsg added in v0.5.0

func (m *Model) ProcessMsg(msg MsgToModel)

func (*Model) Quitted added in v0.4.0

func (m *Model) Quitted() bool

func (*Model) RailError added in v0.5.0

func (s *Model) RailError() RailError

func (*Model) RailWidth added in v0.5.0

func (s *Model) RailWidth() int

func (*Model) ReadSong added in v0.4.0

func (m *Model) ReadSong(r io.ReadCloser)

func (*Model) Redo

func (m *Model) Redo() Action

func (*Model) RemoveUnused added in v0.4.0

func (m *Model) RemoveUnused() Action

func (*Model) RequestQuit added in v0.5.0

func (m *Model) RequestQuit() Action

func (*Model) RowsPerBeat added in v0.4.0

func (m *Model) RowsPerBeat() Int

func (*Model) RowsPerPattern added in v0.4.0

func (m *Model) RowsPerPattern() Int

func (*Model) SaveInstrument added in v0.4.0

func (m *Model) SaveInstrument(w io.WriteCloser) bool

func (*Model) SaveRecovery added in v0.3.0

func (m *Model) SaveRecovery() error

func (*Model) SaveSong added in v0.4.0

func (m *Model) SaveSong() Action

func (*Model) SaveSongAs added in v0.4.0

func (m *Model) SaveSongAs() Action

func (*Model) SearchResults added in v0.4.0

func (m *Model) SearchResults() *SearchResults

func (*Model) SelectMidiInput added in v0.5.0

func (m *Model) SelectMidiInput(item MIDIDevice) Action

func (*Model) ShowLicense added in v0.5.0

func (m *Model) ShowLicense() Action

func (*Model) SignalAnalyzer added in v0.5.0

func (m *Model) SignalAnalyzer() *ScopeModel

func (*Model) Solo added in v0.5.0

func (m *Model) Solo() Bool

func (*Model) SongLength added in v0.4.0

func (m *Model) SongLength() Int

func (*Model) SplitInstrument added in v0.5.0

func (m *Model) SplitInstrument() Action

func (*Model) SplitTrack added in v0.5.0

func (m *Model) SplitTrack() Action

func (*Model) Step added in v0.4.0

func (m *Model) Step() Int

func (*Model) StopPlaying added in v0.5.0

func (m *Model) StopPlaying() Action

func (*Model) SubtractOctave added in v0.4.0

func (m *Model) SubtractOctave() Action

func (*Model) SubtractSemitone added in v0.4.0

func (m *Model) SubtractSemitone() Action

func (*Model) SyntherIndex added in v0.5.0

func (m *Model) SyntherIndex() Int

func (*Model) SyntherName added in v0.5.0

func (v *Model) SyntherName() string

func (*Model) TrackMidiIn added in v0.5.0

func (m *Model) TrackMidiIn() Bool

func (*Model) TrackTitle added in v0.5.0

func (m *Model) TrackTitle(index int) string

func (*Model) TrackVoices added in v0.4.0

func (m *Model) TrackVoices() Int

func (*Model) Tracks added in v0.4.0

func (m *Model) Tracks() *Tracks

func (*Model) Undo

func (m *Model) Undo() Action

func (*Model) UniquePatterns added in v0.5.0

func (m *Model) UniquePatterns() Bool

func (*Model) UnitComment added in v0.5.0

func (m *Model) UnitComment() String

func (*Model) UnitDisabled added in v0.4.0

func (m *Model) UnitDisabled() Bool

func (*Model) UnitSearch added in v0.4.0

func (m *Model) UnitSearch() String

func (*Model) UnitSearching added in v0.4.0

func (m *Model) UnitSearching() Bool

func (*Model) Units added in v0.4.0

func (m *Model) Units() *Units

func (*Model) UnmarshalRecovery added in v0.3.0

func (m *Model) UnmarshalRecovery(bytes []byte)

func (*Model) Wires added in v0.5.0

func (m *Model) Wires(yield func(wire Wire) bool)

func (*Model) WriteSong added in v0.4.0

func (m *Model) WriteSong(w io.WriteCloser)

func (*Model) WriteWav added in v0.4.0

func (m *Model) WriteWav(w io.WriteCloser, pcm16 bool)

type MsgToDetector added in v0.5.0

type MsgToDetector struct {
	Reset bool
	Data  any // TODO: consider using a sum type here, for a bit more type safety. See: https://www.jerf.org/iri/post/2917/

	WeightingType    WeightingType
	HasWeightingType bool
	Oversampling     bool
	HasOversampling  bool
}

MsgToDetector is a message sent to the detector. It contains a reset flag and a data field. The data field can contain many different messages, including *sointu.AudioBuffer for the detector to analyze and func() which gets executed in the detector goroutine.

type MsgToGUI added in v0.5.0

type MsgToGUI struct {
	Kind  GUIMessageKind
	Param int
}

MsgToGUI is a message sent to the GUI, as GUI stores part of the state. In particular, GUI knows about where lists / tables are centered, so the kind of messages we send to the GUI are about centering the view on a specific row, or ensuring that the cursor is visible.

type MsgToModel added in v0.5.0

type MsgToModel struct {
	HasPanicPlayerStatus bool
	Panic                bool
	PlayerStatus         PlayerStatus

	HasDetectorResult bool
	DetectorResult    DetectorResult

	TriggerChannel int  // note: 0 = no trigger, 1 = first channel, etc.
	Reset          bool // true: playing started, so should reset the detector and the scope cursor

	Data any // TODO: consider using a sum type here, for a bit more type safety. See: https://www.jerf.org/iri/post/2917/
}

MsgToModel is a message sent to the model. The most often sent data (Panic, SongPosition, VoiceLevels and DetectorResult) are not boxed to avoid allocations. All the infrequently passed messages can be boxed & cast to any; casting pointer types to any is cheap (does not allocate).

type MutableListData added in v0.4.0

type MutableListData interface {
	// contains filtered or unexported methods
}

type Mute added in v0.5.0

type Mute Model

func (*Mute) Enabled added in v0.5.0

func (m *Mute) Enabled() bool

func (*Mute) SetValue added in v0.5.0

func (m *Mute) SetValue(val bool)

func (*Mute) Value added in v0.5.0

func (m *Mute) Value() bool

type NewSong added in v0.5.0

type NewSong Model

func (*NewSong) Do added in v0.5.0

func (m *NewSong) Do()

type NoteEvent added in v0.5.0

type NoteEvent struct {
	Timestamp int64 // in frames, relative to whatever clock the source is using
	On        bool
	Channel   int
	Note      byte
	IsTrack   bool // true if "Channel" means track number, false if it means instrument number
	Source    any
	// contains filtered or unexported fields
}

NoteEvent describes triggering or releasing of a note. The timestamps are in frames, and relative to the clock of the event source. Different sources can use different clocks. Player tries to adjust the timestamps so that each note events would fall inside the current processing block, by maintaining an estimate of the delta from the source clock to the player clock.

type NoteEventList added in v0.5.0

type NoteEventList []NoteEvent

type NoteRows added in v0.4.0

type NoteRows Model // NoteRows is a list of all the note rows, implementing ListData & MutableListData interfaces

func (*NoteRows) Count added in v0.4.0

func (v *NoteRows) Count() int

func (*NoteRows) List added in v0.4.0

func (v *NoteRows) List() List

func (*NoteRows) Selected added in v0.4.0

func (v *NoteRows) Selected() int

func (*NoteRows) Selected2 added in v0.4.0

func (v *NoteRows) Selected2() int

func (*NoteRows) SetSelected added in v0.4.0

func (v *NoteRows) SetSelected(value int)

func (*NoteRows) SetSelected2 added in v0.4.0

func (v *NoteRows) SetSelected2(value int)

type Notes added in v0.4.0

type Notes Model

func (*Notes) Cursor added in v0.4.0

func (m *Notes) Cursor() Point

func (*Notes) Cursor2 added in v0.4.0

func (m *Notes) Cursor2() Point

func (*Notes) Effect added in v0.4.0

func (m *Notes) Effect(x int) bool

func (*Notes) Height added in v0.4.0

func (v *Notes) Height() int

func (*Notes) Input added in v0.5.0

func (v *Notes) Input(note byte) NoteEvent

func (*Notes) InputNibble added in v0.5.0

func (v *Notes) InputNibble(nibble byte) NoteEvent

func (*Notes) LowNibble added in v0.4.0

func (m *Notes) LowNibble() bool

func (*Notes) MoveCursor added in v0.4.0

func (v *Notes) MoveCursor(dx, dy int) (ok bool)

func (*Notes) SetCursor added in v0.4.0

func (v *Notes) SetCursor(p Point)

func (*Notes) SetCursor2 added in v0.4.0

func (v *Notes) SetCursor2(p Point)

func (*Notes) SetCursorFloat added in v0.5.0

func (m *Notes) SetCursorFloat(x, y float32)

func (*Notes) SetValue added in v0.4.0

func (m *Notes) SetValue(p Point, val byte)

func (*Notes) Table added in v0.4.0

func (v *Notes) Table() Table

func (*Notes) Value added in v0.4.0

func (m *Notes) Value(p Point) byte

func (*Notes) Width added in v0.4.0

func (v *Notes) Width() int

type NullMIDIContext added in v0.5.0

type NullMIDIContext struct{}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

func (NullMIDIContext) Close added in v0.5.0

func (m NullMIDIContext) Close()

func (NullMIDIContext) HasDeviceOpen added in v0.5.0

func (m NullMIDIContext) HasDeviceOpen() bool

func (NullMIDIContext) InputDevices added in v0.5.0

func (m NullMIDIContext) InputDevices(yield func(MIDIDevice) bool)

func (NullMIDIContext) TryToOpenBy added in v0.5.0

func (m NullMIDIContext) TryToOpenBy(name string, first bool)

type NullPlayerProcessContext added in v0.5.0

type NullPlayerProcessContext struct{}

func (NullPlayerProcessContext) BPM added in v0.5.0

func (p NullPlayerProcessContext) BPM() (bpm float64, ok bool)

type Octave added in v0.4.0

type Octave Model

func (*Octave) Range added in v0.4.0

func (v *Octave) Range() IntRange

func (*Octave) SetValue added in v0.5.0

func (v *Octave) SetValue(value int) bool

func (*Octave) Value added in v0.4.0

func (v *Octave) Value() int

type OpenSong added in v0.5.0

type OpenSong Model

func (*OpenSong) Do added in v0.5.0

func (m *OpenSong) Do()

type Order added in v0.4.0

type Order Model

func (*Order) Cursor added in v0.4.0

func (m *Order) Cursor() Point

func (*Order) Cursor2 added in v0.4.0

func (m *Order) Cursor2() Point

func (*Order) Height added in v0.4.0

func (v *Order) Height() int

func (*Order) MoveCursor added in v0.4.0

func (v *Order) MoveCursor(dx, dy int) (ok bool)

func (*Order) SetCursor added in v0.4.0

func (m *Order) SetCursor(p Point)

func (*Order) SetCursor2 added in v0.4.0

func (m *Order) SetCursor2(p Point)

func (*Order) SetValue added in v0.4.0

func (m *Order) SetValue(p Point, val int)

func (*Order) Table added in v0.4.0

func (v *Order) Table() Table

func (*Order) Value added in v0.4.0

func (m *Order) Value(p Point) int

func (*Order) Width added in v0.4.0

func (v *Order) Width() int

type OrderRows added in v0.4.0

type OrderRows Model // OrderRows is a list of all the order rows, implementing ListData & MutableListData interfaces

func (*OrderRows) Count added in v0.4.0

func (v *OrderRows) Count() int

func (*OrderRows) List added in v0.4.0

func (v *OrderRows) List() List

func (*OrderRows) Selected added in v0.4.0

func (v *OrderRows) Selected() int

func (*OrderRows) Selected2 added in v0.4.0

func (v *OrderRows) Selected2() int

func (*OrderRows) SetSelected added in v0.4.0

func (v *OrderRows) SetSelected(value int)

func (*OrderRows) SetSelected2 added in v0.4.0

func (v *OrderRows) SetSelected2(value int)

type Oversampling added in v0.5.0

type Oversampling Model

func (*Oversampling) SetValue added in v0.5.0

func (m *Oversampling) SetValue(val bool)

func (*Oversampling) Value added in v0.5.0

func (m *Oversampling) Value() bool

type Panic added in v0.4.0

type Panic Model

func (*Panic) SetValue added in v0.5.0

func (m *Panic) SetValue(val bool)

func (*Panic) Value added in v0.4.0

func (m *Panic) Value() bool

type PanicMsg added in v0.4.0

type PanicMsg struct {
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type ParamVertList added in v0.5.0

type ParamVertList Model

func (*ParamVertList) Count added in v0.5.0

func (pt *ParamVertList) Count() int

func (*ParamVertList) List added in v0.5.0

func (pt *ParamVertList) List() List

func (*ParamVertList) Selected added in v0.5.0

func (pt *ParamVertList) Selected() int

func (*ParamVertList) Selected2 added in v0.5.0

func (pt *ParamVertList) Selected2() int

func (*ParamVertList) SetSelected added in v0.5.0

func (pt *ParamVertList) SetSelected(index int)

func (*ParamVertList) SetSelected2 added in v0.5.0

func (pt *ParamVertList) SetSelected2(index int)

type ParamYieldFunc added in v0.4.0

type ParamYieldFunc func(param Parameter) bool

type Parameter

type Parameter struct {
	// contains filtered or unexported fields
}

Parameter represents a parameter of a unit. To support polymorphism without causing allocations, it has a vtable that defines the methods for the specific parameter type, to which all the method calls are delegated.

func (*Parameter) Add added in v0.5.0

func (p *Parameter) Add(delta int, snapToGrid bool) bool

func (*Parameter) Hint

func (p *Parameter) Hint() ParameterHint

func (*Parameter) Name

func (p *Parameter) Name() string

func (*Parameter) Neutral added in v0.5.0

func (p *Parameter) Neutral() int

func (*Parameter) Port added in v0.5.0

func (p *Parameter) Port() (int, bool)

func (*Parameter) Range added in v0.5.0

func (p *Parameter) Range() IntRange

func (*Parameter) Reset added in v0.4.0

func (p *Parameter) Reset()

func (*Parameter) SetValue added in v0.5.0

func (p *Parameter) SetValue(value int) bool

func (*Parameter) Type

func (p *Parameter) Type() ParameterType

func (*Parameter) UnitID added in v0.5.0

func (p *Parameter) UnitID() int

func (*Parameter) Value

func (p *Parameter) Value() int

type ParameterHint added in v0.5.0

type ParameterHint struct {
	Label string
	Valid bool
}

type ParameterType

type ParameterType int
const (
	NoParameter ParameterType = iota
	IntegerParameter
	BoolParameter
	IDParameter
)

type Params added in v0.4.0

type Params Model

func (*Params) Cursor added in v0.5.0

func (pt *Params) Cursor() Point

func (*Params) Cursor2 added in v0.5.0

func (pt *Params) Cursor2() Point

func (*Params) Height added in v0.5.0

func (pt *Params) Height() int

func (*Params) Item added in v0.5.0

func (pt *Params) Item(p Point) Parameter

func (*Params) MoveCursor added in v0.5.0

func (pt *Params) MoveCursor(dx, dy int) (ok bool)

func (*Params) RowWidth added in v0.5.0

func (pt *Params) RowWidth(y int) int

func (*Params) SetCursor added in v0.5.0

func (pt *Params) SetCursor(p Point)

func (*Params) SetCursor2 added in v0.5.0

func (pt *Params) SetCursor2(p Point)

func (*Params) Table added in v0.5.0

func (pt *Params) Table() Table

func (*Params) Width added in v0.5.0

func (pt *Params) Width() int

type PeakResult added in v0.5.0

type PeakResult [NumPeakTypes][2]Decibel

type PeakType added in v0.5.0

type PeakType int
const (
	PeakMomentary PeakType = iota
	PeakShortTerm
	PeakIntegrated
	NumPeakTypes
)

type PlayCurrentPos added in v0.5.0

type PlayCurrentPos Model

func (*PlayCurrentPos) Do added in v0.5.0

func (m *PlayCurrentPos) Do()

func (*PlayCurrentPos) Enabled added in v0.5.0

func (m *PlayCurrentPos) Enabled() bool

type PlayFromLoopStart added in v0.5.0

type PlayFromLoopStart Model

func (*PlayFromLoopStart) Do added in v0.5.0

func (m *PlayFromLoopStart) Do()

func (*PlayFromLoopStart) Enabled added in v0.5.0

func (m *PlayFromLoopStart) Enabled() bool

type PlaySelected added in v0.5.0

type PlaySelected Model

func (*PlaySelected) Do added in v0.5.0

func (m *PlaySelected) Do()

func (*PlaySelected) Enabled added in v0.5.0

func (m *PlaySelected) Enabled() bool

type PlaySongStart added in v0.5.0

type PlaySongStart Model

func (*PlaySongStart) Do added in v0.5.0

func (m *PlaySongStart) Do()

func (*PlaySongStart) Enabled added in v0.5.0

func (m *PlaySongStart) Enabled() bool

type Player

type Player struct {
	// contains filtered or unexported fields
}

Player is the audio player for the tracker, run in a separate thread. It is controlled by messages from the model and MIDI messages via the context, typically from the VSTI host. The player sendTargets messages to the model via the playerMessages channel. The model sendTargets messages to the player via the modelMessages channel.

func NewPlayer

func NewPlayer(broker *Broker, synther sointu.Synther) *Player

func (*Player) Process added in v0.2.0

func (p *Player) Process(buffer sointu.AudioBuffer, context PlayerProcessContext)

Process renders audio to the given buffer, trying to fill it completely. If the buffer is not filled, the synth is destroyed and an error is sent to the model. context tells the player which MIDI events happen during the current buffer. It is used to trigger and release notes during processing. The context is also used to get the current BPM from the host.

func (*Player) SendAlert added in v0.5.0

func (p *Player) SendAlert(name, message string, priority AlertPriority)

type PlayerProcessContext added in v0.2.0

type PlayerProcessContext interface {
	BPM() (bpm float64, ok bool)
}

PlayerProcessContext is the context given to the player when processing audio. Currently it is only used to get BPM from the VSTI host.

type PlayerStatus added in v0.5.0

type PlayerStatus struct {
	SongPos     sointu.SongPos         // the current position in the score
	VoiceLevels [vm.MAX_VOICES]float32 // a level that can be used to visualize the volume of each voice
	CPULoad     float64                // current CPU load of the player, used to adjust the render rate
}

PlayerStatus is the part of the player state that is communicated to the model, for different visualizations of what is happening in the player.

type Playing added in v0.4.0

type Playing Model

func (*Playing) Enabled added in v0.4.0

func (m *Playing) Enabled() bool

func (*Playing) SetValue added in v0.5.0

func (m *Playing) SetValue(val bool)

func (*Playing) Value added in v0.4.0

func (m *Playing) Value() bool

type Point added in v0.4.0

type Point struct {
	X, Y int
}

type Presets added in v0.4.0

type Presets Model // Presets is a unmutable list of all the presets, implementing ListData interface

type Rail added in v0.5.0

type Rail struct {
	PassThrough int
	Send        bool
	StackUse    sointu.StackUse
}

func (*Rail) StackAfter added in v0.5.0

func (s *Rail) StackAfter() int

type RailError added in v0.5.0

type RailError struct {
	InstrIndex, UnitIndex int
	Err                   error
}

func (*RailError) Error added in v0.5.0

func (e *RailError) Error() string

type Range added in v0.5.0

type Range struct {
	Start, End int
}

Range is used to represent a range [Start,End) of integers

func Complement added in v0.5.0

func Complement(a Range) [2]Range

func MakeMoveRanges added in v0.5.0

func MakeMoveRanges(a Range, delta int) [4]Range

func MakeSetLength added in v0.5.0

func MakeSetLength(a Range, length int) []Range

MakeSetLength takes a range and a length, and returns a slice of ranges that can be used with VoiceSlice to expand or shrink the range to the given length, by either duplicating or removing elements. The function tries to duplicate elements so all elements are equally spaced, and tries to remove elements from the middle of the range.

func VoiceInsert added in v0.5.0

func VoiceInsert[T any, S ~[]T, P sointu.NumVoicerPointer[T]](orig S, index, length int, added ...T) (ret S, retRange Range, ok bool)

VoiceInsert tries adding the elements "added" to the slice "orig" at the voice index "index". Notice that index is the index into a virtual slice where each element is repeated by the number of voices it has. If the index is between elements, the new elements are added in between the old elements. If the addition would cause splitting of an element, we rather increase the number of voices the element has, but do not split it.

func VoiceRange added in v0.5.0

func VoiceRange[T any, S ~[]T, P sointu.NumVoicerPointer[T]](slice S, indexRange Range) (voiceRange Range)

func (Range) Intersect added in v0.5.0

func (r Range) Intersect(s Range) (ret Range)

func (Range) Len added in v0.5.0

func (r Range) Len() int

func (Range) Swaps added in v0.5.0

func (r Range) Swaps(delta int) iter.Seq2[int, int]

type Recording added in v0.3.0

type Recording struct {
	BPM                  float64 // vsts allow bpms as floats so for accurate reconstruction, keep it as float for recording
	Events               NoteEventList
	StartFrame, EndFrame int64
	State                RecordingState
}

func (*Recording) Finish added in v0.5.0

func (r *Recording) Finish(frame int64, frameDeltas map[any]int64)

func (*Recording) Record added in v0.5.0

func (r *Recording) Record(ev NoteEvent, frame int64)

func (*Recording) Score added in v0.4.0

func (recording *Recording) Score(patch sointu.Patch, rowsPerBeat, rowsPerPattern int) (sointu.Score, error)

type RecordingMsg added in v0.4.0

type RecordingMsg struct {
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type RecordingState added in v0.5.0

type RecordingState int
const (
	RecordingNone RecordingState = iota
	RecordingWaitingForNote
	RecordingStarted  // StartFrame is set, but EndFrame is not
	RecordingFinished // StartFrame and EndFrame are both set, recording is finished
)

type Rect added in v0.4.0

type Rect struct {
	TopLeft, BottomRight Point
}

func (*Rect) Contains added in v0.4.0

func (r *Rect) Contains(p Point) bool

func (*Rect) Height added in v0.4.0

func (r *Rect) Height() int

func (*Rect) Limit added in v0.4.0

func (r *Rect) Limit(width, height int)

func (*Rect) Width added in v0.4.0

func (r *Rect) Width() int

type Redo added in v0.5.0

type Redo Model

func (*Redo) Do added in v0.5.0

func (m *Redo) Do()

func (*Redo) Enabled added in v0.5.0

func (m *Redo) Enabled() bool

type RemoveUnused added in v0.5.0

type RemoveUnused Model

func (*RemoveUnused) Do added in v0.5.0

func (m *RemoveUnused) Do()

type RequestQuit added in v0.5.0

type RequestQuit Model

func (*RequestQuit) Do added in v0.5.0

func (m *RequestQuit) Do()

type RingBuffer added in v0.5.0

type RingBuffer[T any] struct {
	Buffer []T
	Cursor int
}

func (*RingBuffer[T]) WriteOnce added in v0.5.0

func (r *RingBuffer[T]) WriteOnce(values []T)

func (*RingBuffer[T]) WriteOnceSingle added in v0.5.0

func (r *RingBuffer[T]) WriteOnceSingle(value T)

func (*RingBuffer[T]) WriteWrap added in v0.5.0

func (r *RingBuffer[T]) WriteWrap(values []T)

func (*RingBuffer[T]) WriteWrapSingle added in v0.5.0

func (r *RingBuffer[T]) WriteWrapSingle(value T)

type RowsPerBeat added in v0.4.0

type RowsPerBeat Model

func (*RowsPerBeat) Range added in v0.4.0

func (v *RowsPerBeat) Range() IntRange

func (*RowsPerBeat) SetValue added in v0.5.0

func (v *RowsPerBeat) SetValue(value int) bool

func (*RowsPerBeat) Value added in v0.4.0

func (v *RowsPerBeat) Value() int

type RowsPerBeatMsg added in v0.4.0

type RowsPerBeatMsg struct {
	// contains filtered or unexported fields
}

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type RowsPerPattern added in v0.4.0

type RowsPerPattern Model

func (*RowsPerPattern) Range added in v0.4.0

func (v *RowsPerPattern) Range() IntRange

func (*RowsPerPattern) SetValue added in v0.5.0

func (v *RowsPerPattern) SetValue(value int) bool

func (*RowsPerPattern) Value added in v0.4.0

func (v *RowsPerPattern) Value() int

type SaveSong added in v0.5.0

type SaveSong Model

func (*SaveSong) Do added in v0.5.0

func (m *SaveSong) Do()

type SaveSongAs added in v0.5.0

type SaveSongAs Model

func (*SaveSongAs) Do added in v0.5.0

func (m *SaveSongAs) Do()

type ScopeModel added in v0.5.0

type ScopeModel struct {
	// contains filtered or unexported fields
}

func NewScopeModel added in v0.5.0

func NewScopeModel(broker *Broker, bpm int) *ScopeModel

func (*ScopeModel) LengthInBeats added in v0.5.0

func (s *ScopeModel) LengthInBeats() Int

func (*ScopeModel) Once added in v0.5.0

func (s *ScopeModel) Once() Bool

func (*ScopeModel) ProcessAudioBuffer added in v0.5.0

func (s *ScopeModel) ProcessAudioBuffer(bufPtr *sointu.AudioBuffer)

func (*ScopeModel) Reset added in v0.5.0

func (s *ScopeModel) Reset()

func (*ScopeModel) SetBpm added in v0.5.0

func (s *ScopeModel) SetBpm(bpm int)

func (*ScopeModel) Trigger added in v0.5.0

func (s *ScopeModel) Trigger(channel int)

Note: channel 1 is the first channel

func (*ScopeModel) TriggerChannel added in v0.5.0

func (s *ScopeModel) TriggerChannel() Int

func (*ScopeModel) Waveform added in v0.5.0

func (s *ScopeModel) Waveform() RingBuffer[[2]float32]

func (*ScopeModel) Wrap added in v0.5.0

func (s *ScopeModel) Wrap() Bool

type SearchResults added in v0.4.0

type SearchResults Model // SearchResults is a unmutable list of all the search results, implementing ListData interface

func (*SearchResults) Count added in v0.4.0

func (l *SearchResults) Count() (count int)

func (*SearchResults) Item added in v0.5.0

func (l *SearchResults) Item(index int) (name string, ok bool)

func (*SearchResults) Iterate added in v0.4.0

func (l *SearchResults) Iterate(yield UnitSearchYieldFunc)

func (*SearchResults) List added in v0.4.0

func (v *SearchResults) List() List

func (*SearchResults) Selected added in v0.4.0

func (l *SearchResults) Selected() int

func (*SearchResults) Selected2 added in v0.4.0

func (l *SearchResults) Selected2() int

func (*SearchResults) SetSelected added in v0.4.0

func (l *SearchResults) SetSelected(value int)

func (*SearchResults) SetSelected2 added in v0.4.0

func (l *SearchResults) SetSelected2(value int)

type SelectMidiInput added in v0.5.0

type SelectMidiInput struct {
	Item MIDIDevice
	*Model
}

func (SelectMidiInput) Do added in v0.5.0

func (s SelectMidiInput) Do()

type ShowLicense added in v0.5.0

type ShowLicense Model

func (*ShowLicense) Do added in v0.5.0

func (m *ShowLicense) Do()

type SignalLengthInBeats added in v0.5.0

type SignalLengthInBeats ScopeModel

func (*SignalLengthInBeats) Range added in v0.5.0

func (m *SignalLengthInBeats) Range() IntRange

func (*SignalLengthInBeats) SetValue added in v0.5.0

func (m *SignalLengthInBeats) SetValue(val int) bool

func (*SignalLengthInBeats) Value added in v0.5.0

func (m *SignalLengthInBeats) Value() int

type SignalOnce added in v0.5.0

type SignalOnce ScopeModel

func (*SignalOnce) SetValue added in v0.5.0

func (m *SignalOnce) SetValue(val bool)

func (*SignalOnce) Value added in v0.5.0

func (m *SignalOnce) Value() bool

type SignalWrap added in v0.5.0

type SignalWrap ScopeModel

func (*SignalWrap) SetValue added in v0.5.0

func (m *SignalWrap) SetValue(val bool)

func (*SignalWrap) Value added in v0.5.0

func (m *SignalWrap) Value() bool

type Solo added in v0.5.0

type Solo Model

func (*Solo) Enabled added in v0.5.0

func (m *Solo) Enabled() bool

func (*Solo) SetValue added in v0.5.0

func (m *Solo) SetValue(val bool)

func (*Solo) Value added in v0.5.0

func (m *Solo) Value() bool

type SongLength added in v0.4.0

type SongLength Model

func (*SongLength) Range added in v0.4.0

func (v *SongLength) Range() IntRange

func (*SongLength) SetValue added in v0.5.0

func (v *SongLength) SetValue(value int) bool

func (*SongLength) Value added in v0.4.0

func (v *SongLength) Value() int

type SplitInstrument added in v0.5.0

type SplitInstrument Model

func (*SplitInstrument) Do added in v0.5.0

func (m *SplitInstrument) Do()

func (*SplitInstrument) Enabled added in v0.5.0

func (m *SplitInstrument) Enabled() bool

type SplitTrack added in v0.5.0

type SplitTrack Model

func (*SplitTrack) Do added in v0.5.0

func (m *SplitTrack) Do()

func (*SplitTrack) Enabled added in v0.5.0

func (m *SplitTrack) Enabled() bool

type StartPlayMsg added in v0.4.0

type StartPlayMsg struct{ sointu.SongPos }

Model implements the mutable state for the tracker program GUI.

Go does not have immutable slices, so there's no efficient way to guarantee accidental mutations in the song. But at least the value members are protected. It is owned by the GUI thread (goroutine), while the player is owned by by the audioprocessing thread. They communicate using the two channels

type Step added in v0.4.0

type Step Model

func (*Step) Range added in v0.4.0

func (v *Step) Range() IntRange

func (*Step) SetValue added in v0.5.0

func (v *Step) SetValue(value int) bool

func (*Step) Value added in v0.4.0

func (v *Step) Value() int

type StopPlaying added in v0.5.0

type StopPlaying Model

func (*StopPlaying) Do added in v0.5.0

func (m *StopPlaying) Do()

type String added in v0.4.0

type String struct {
	// contains filtered or unexported fields
}

func MakeString added in v0.5.0

func MakeString(value StringValue) String

func (String) SetValue added in v0.5.0

func (v String) SetValue(value string) bool

func (String) Value added in v0.5.0

func (v String) Value() string

type StringValue added in v0.5.0

type StringValue interface {
	Value() string
	SetValue(string) bool
}

type SubtractOctave added in v0.5.0

type SubtractOctave Model

func (*SubtractOctave) Do added in v0.5.0

func (m *SubtractOctave) Do()

type SubtractSemitone added in v0.5.0

type SubtractSemitone Model

func (*SubtractSemitone) Do added in v0.5.0

func (m *SubtractSemitone) Do()

type SyntherIndex added in v0.5.0

type SyntherIndex Model

func (*SyntherIndex) Range added in v0.5.0

func (v *SyntherIndex) Range() IntRange

func (*SyntherIndex) SetValue added in v0.5.0

func (v *SyntherIndex) SetValue(value int) bool

func (*SyntherIndex) Value added in v0.5.0

func (v *SyntherIndex) Value() int

type Table added in v0.4.0

type Table struct {
	TableData
}

func (Table) Add added in v0.4.0

func (v Table) Add(delta int, largeStep bool)

func (Table) Clear added in v0.4.0

func (v Table) Clear()

func (Table) Copy added in v0.4.0

func (v Table) Copy() ([]byte, bool)

func (Table) Fill added in v0.4.0

func (v Table) Fill(value int)

func (Table) Paste added in v0.4.0

func (v Table) Paste(data []byte) bool

func (Table) Range added in v0.4.0

func (v Table) Range() (rect Rect)

func (Table) Set added in v0.5.0

func (v Table) Set(value byte)

func (Table) SetCursorX added in v0.4.0

func (v Table) SetCursorX(x int)

func (Table) SetCursorY added in v0.4.0

func (v Table) SetCursorY(y int)

type TableData added in v0.4.0

type TableData interface {
	Cursor() Point
	Cursor2() Point
	SetCursor(Point)
	SetCursor2(Point)
	Width() int
	Height() int
	MoveCursor(dx, dy int) (ok bool)
	// contains filtered or unexported methods
}

type TrackMidiIn added in v0.5.0

type TrackMidiIn Model

func (*TrackMidiIn) SetValue added in v0.5.0

func (m *TrackMidiIn) SetValue(val bool)

func (*TrackMidiIn) Value added in v0.5.0

func (m *TrackMidiIn) Value() bool

type TrackVoices added in v0.4.0

type TrackVoices Model

func (*TrackVoices) Range added in v0.4.0

func (v *TrackVoices) Range() IntRange

func (*TrackVoices) SetValue added in v0.5.0

func (m *TrackVoices) SetValue(value int) bool

func (*TrackVoices) Value added in v0.4.0

func (v *TrackVoices) Value() int

type Tracks added in v0.4.0

type Tracks Model // Tracks is a list of all the tracks, implementing ListData & MutableListData interfaces

func (*Tracks) Count added in v0.4.0

func (v *Tracks) Count() int

func (*Tracks) List added in v0.4.0

func (v *Tracks) List() List

func (*Tracks) Selected added in v0.4.0

func (v *Tracks) Selected() int

func (*Tracks) Selected2 added in v0.4.0

func (v *Tracks) Selected2() int

func (*Tracks) SetSelected added in v0.4.0

func (v *Tracks) SetSelected(value int)

func (*Tracks) SetSelected2 added in v0.4.0

func (v *Tracks) SetSelected2(value int)

type TriggerChannel added in v0.5.0

type TriggerChannel ScopeModel

func (*TriggerChannel) Range added in v0.5.0

func (m *TriggerChannel) Range() IntRange

func (*TriggerChannel) SetValue added in v0.5.0

func (m *TriggerChannel) SetValue(val int) bool

func (*TriggerChannel) Value added in v0.5.0

func (m *TriggerChannel) Value() int

type Undo added in v0.5.0

type Undo Model

func (*Undo) Do added in v0.5.0

func (m *Undo) Do()

func (*Undo) Enabled added in v0.5.0

func (m *Undo) Enabled() bool

type UniquePatterns added in v0.5.0

type UniquePatterns Model

func (*UniquePatterns) SetValue added in v0.5.0

func (m *UniquePatterns) SetValue(val bool)

func (*UniquePatterns) Value added in v0.5.0

func (m *UniquePatterns) Value() bool

type UnitComment added in v0.5.0

type UnitComment Model

func (*UnitComment) SetValue added in v0.5.0

func (v *UnitComment) SetValue(value string) bool

func (*UnitComment) Value added in v0.5.0

func (v *UnitComment) Value() string

type UnitDisabled added in v0.4.0

type UnitDisabled Model

func (*UnitDisabled) Enabled added in v0.4.0

func (m *UnitDisabled) Enabled() bool

func (*UnitDisabled) SetValue added in v0.5.0

func (m *UnitDisabled) SetValue(val bool)

func (*UnitDisabled) Value added in v0.4.0

func (m *UnitDisabled) Value() bool

type UnitListItem added in v0.4.0

type UnitListItem struct {
	Type, Comment string
	Disabled      bool
	Signals       Rail
}

type UnitSearch added in v0.4.0

type UnitSearch Model

func (*UnitSearch) SetValue added in v0.5.0

func (v *UnitSearch) SetValue(value string) bool

func (*UnitSearch) Value added in v0.4.0

func (v *UnitSearch) Value() string

type UnitSearchYieldFunc added in v0.4.0

type UnitSearchYieldFunc func(index int, item string) (ok bool)

type UnitSearching added in v0.4.0

type UnitSearching Model

func (*UnitSearching) SetValue added in v0.5.0

func (m *UnitSearching) SetValue(val bool)

func (*UnitSearching) Value added in v0.4.0

func (m *UnitSearching) Value() bool

type UnitYieldFunc added in v0.4.0

type UnitYieldFunc func(index int, item UnitListItem) (ok bool)

type Units added in v0.4.0

type Units Model // Units is a list of all the units in the selected instrument, implementing ListData & MutableListData interfaces

func (*Units) Count added in v0.4.0

func (v *Units) Count() int

func (*Units) Item added in v0.5.0

func (v *Units) Item(index int) UnitListItem

func (*Units) List added in v0.4.0

func (v *Units) List() List

func (*Units) Selected added in v0.4.0

func (v *Units) Selected() int

func (*Units) Selected2 added in v0.4.0

func (v *Units) Selected2() int

func (*Units) SelectedType added in v0.4.0

func (m *Units) SelectedType() string

func (*Units) SetSelected added in v0.4.0

func (v *Units) SetSelected(value int)

func (*Units) SetSelected2 added in v0.4.0

func (v *Units) SetSelected2(value int)

func (*Units) SetSelectedType added in v0.4.0

func (m *Units) SetSelectedType(t string)

type WeightingType added in v0.5.0

type WeightingType int
const (
	KWeighting WeightingType = iota
	AWeighting
	CWeighting
	NoWeighting
	NumWeightingTypes
)

type Wire added in v0.5.0

type Wire struct {
	From      int
	FromSet   bool
	To        Point
	ToSet     bool
	Hint      string
	Highlight bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL