Documentation ¶
Index ¶
- Constants
- Variables
- type AudioBuffer
- type AudioContext
- type AudioOutput
- type Instrument
- type Order
- type Patch
- func (p Patch) Copy() Patch
- func (p Patch) FindUnit(id int) (instrIndex int, unitIndex int, err error)
- func (p Patch) FirstVoiceForInstrument(instrIndex int) int
- func (p Patch) InstrumentForVoice(voice int) (int, error)
- func (p Patch) NumDelayLines() int
- func (p Patch) NumSyncs() int
- func (p Patch) NumVoices() int
- func (p Patch) ParamHintString(instrIndex, unitIndex int, param string) string
- type Pattern
- type Score
- type Song
- type Synth
- type Synther
- type Track
- type Unit
- type UnitParameter
Constants ¶
When unit.Type = "oscillator", its unit.Parameter["Type"] tells the type of the oscillator. There is five different oscillator types, so these consts just enumerate them.
Variables ¶
var Ports = make(map[string]([]string))
Ports is static map allowing quickly finding the parameters of a unit that can be modulated. This is populated based on the UnitTypes list during init(). Thus, should be immutable, but Go not supporting that, then this will have to suffice: DO NOT EVER CHANGE THIS MAP.
var UnitNames []string
UnitNames is a list of all the names of units, sorted alphabetically.
var UnitTypes = map[string]([]UnitParameter){ "add": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "addp": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "pop": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "loadnote": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "mul": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "mulp": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "push": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "xch": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "distort": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "drive", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "hold": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "holdfreq", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "crush": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "resolution", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "gain": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "invgain": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "invgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "filter": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "frequency", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "resonance", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "lowpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "bandpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "highpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "negbandpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "neghighpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "clip": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "pan": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "panning", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "delay": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "pregain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "dry", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "feedback", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "damp", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "notetracking", MinValue: 0, MaxValue: 2, CanSet: true, CanModulate: false}, {Name: "delaytime", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}}, "compressor": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "attack", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "release", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "invgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "threshold", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "ratio", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "speed": []UnitParameter{}, "out": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "outaux": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "outgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "auxgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "aux": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "channel", MinValue: 0, MaxValue: 6, CanSet: true, CanModulate: false}}, "send": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "amount", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "voice", MinValue: 0, MaxValue: 32, CanSet: true, CanModulate: false}, {Name: "target", MinValue: 0, MaxValue: math.MaxInt32, CanSet: true, CanModulate: false}, {Name: "port", MinValue: 0, MaxValue: 7, CanSet: true, CanModulate: false}, {Name: "sendpop", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}}, "envelope": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "attack", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "decay", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "sustain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "release", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "noise": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "shape", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "oscillator": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "transpose", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "detune", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "phase", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "color", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "shape", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}, {Name: "frequency", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}, {Name: "type", MinValue: int(Sine), MaxValue: int(Sample), CanSet: true, CanModulate: false}, {Name: "lfo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "unison", MinValue: 0, MaxValue: 3, CanSet: true, CanModulate: false}, {Name: "samplestart", MinValue: 0, MaxValue: 1720329, CanSet: true, CanModulate: false}, {Name: "loopstart", MinValue: 0, MaxValue: 65535, CanSet: true, CanModulate: false}, {Name: "looplength", MinValue: 0, MaxValue: 65535, CanSet: true, CanModulate: false}}, "loadval": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "value", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}}, "receive": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "left", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}, {Name: "right", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}}, "in": []UnitParameter{ {Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}, {Name: "channel", MinValue: 0, MaxValue: 6, CanSet: true, CanModulate: false}}, "sync": []UnitParameter{}, }
UnitTypes documents all the available unit types and if they support stereo variant and what parameters they take.
Functions ¶
This section is empty.
Types ¶
type AudioBuffer ¶ added in v0.3.0
type AudioBuffer [][2]float32
AudioBuffer is a buffer of stereo audio samples of variable length, each sample represented by [2]float32. [0] is left channel, [1] is right
func Play ¶
func Play(synther Synther, song Song) (AudioBuffer, error)
Play plays the Song by first compiling the patch with the given Synther, returning the stereo audio buffer as a result (and possible errors).
func (AudioBuffer) Fill ¶ added in v0.3.0
func (buffer AudioBuffer) Fill(synth Synth) error
Fill fills the AudioBuffer using a Synth, disregarding all syncs and time limits. Note that this will change the state of the Synth.
func (AudioBuffer) Raw ¶ added in v0.3.0
func (buffer AudioBuffer) Raw(pcm16 bool) ([]byte, error)
Raw converts an AudioBuffer into a raw audio file, returned as a []byte array.
If pcm16 is set to true, the samples will be 16-bit signed integers; otherwise the samples will be 32-bit floats
func (AudioBuffer) Wav ¶ added in v0.3.0
func (buffer AudioBuffer) Wav(pcm16 bool) ([]byte, error)
Wav converts an AudioBuffer into a valid WAV-file, returned as a []byte array.
If pcm16 is set to true, the samples in the WAV-file will be 16-bit signed integers; otherwise the samples will be 32-bit floats
type AudioContext ¶
type AudioContext interface { Output() AudioOutput Close() error }
AudioContext represents the low-level audio drivers. There should be at most one AudioContext at a time. The interface is implemented at least by oto.OtoContext, but in future we could also mock it.
AudioContext is used to create one or more AudioOutputs with Output(); each can be used to output separate sound & closed when done.
type AudioOutput ¶ added in v0.2.0
type AudioOutput interface { WriteAudio(buffer AudioBuffer) error Close() error }
AudioOutput represents something where we can send audio e.g. audio output. WriteAudio should block if not ready to accept audio e.g. buffer full.
type Instrument ¶
type Instrument struct { Name string `yaml:",omitempty"` Comment string `yaml:",omitempty"` NumVoices int Units []Unit }
Instrument includes a list of units consisting of the instrument, and the number of polyphonic voices for this instrument
func Read4klangInstrument ¶ added in v0.2.0
func Read4klangInstrument(r io.Reader) (instr Instrument, err error)
Read4klangInstrument reads a 4klang instrument (a file usually with .4ki extension) from r and returns an Instrument, making best attempt to convert 4ki file to a sointu Instrument. It returns an error if the file is malformed or if the 4ki file version is not supported.
func (*Instrument) Copy ¶
func (instr *Instrument) Copy() Instrument
Copy makes a deep copy of an Instrument
type Order ¶ added in v0.2.0
type Order []int
Order is the pattern order for a track, in practice just a slice of integers, but provides convenience functions that return -1 values for indices out of bounds of the array, and functions to increase the size of the slice only by necessary amount when a new item is added, filling the unused slots with -1s.
type Patch ¶
type Patch []Instrument
Patch is simply a list of instruments used in a song
func Read4klangPatch ¶ added in v0.2.0
Read4klangPatch reads a 4klang patch (a file usually with .4kp extension) from r and returns a Patch, making best attempt to convert 4klang file to a sointu Patch. It returns an error if the file is malformed or if the 4kp file version is not supported.
func (Patch) FindUnit ¶ added in v0.3.0
FindUnit searches the instrument index and unit index for a unit with the given id. Two units should never have the same id, but if they do, then the first match is returned. Id 0 is interpreted as "no id", thus searching for id 0 returns an error. Error is also returned if the searched id is not found.
func (Patch) FirstVoiceForInstrument ¶
FirstVoiceForInstrument returns the index of the first voice of given instrument. For example, if the Patch has three instruments (0, 1 and 2), with 1, 3, 2 voices, respectively, then FirstVoiceForInstrument(0) returns 0, FirstVoiceForInstrument(1) returns 1 and FirstVoiceForInstrument(2) returns 4. Essentially computes just the cumulative sum.
func (Patch) InstrumentForVoice ¶
InstrumentForVoice returns the instrument number for the given voice index. For example, if the Patch has three instruments (0, 1 and 2), with 1, 3, 2 voices, respectively, then InstrumentForVoice(0) returns 0, InstrumentForVoice(1) returns 1 and InstrumentForVoice(3) returns 1.
func (Patch) NumDelayLines ¶
NumDelayLines return the total number of delay lines used in the patch; summing the number of delay lines of every delay unit in every instrument
func (Patch) NumSyncs ¶
NumSyns return the total number of sync outputs used in the patch; summing the number of sync outputs of every sync unit in every instrument
type Pattern ¶ added in v0.2.0
type Pattern []byte
Pattern represents a single pattern of note, in practice just a slice of bytes, but provides convenience functions that return 1 values (hold) for indices out of bounds of the array, and functions to increase the size of the slice only by necessary amount when a new item is added, filling the unused slots with 1s.
type Score ¶
type Score struct { Tracks []Track RowsPerPattern int // number of rows in each pattern Length int // length of the song, in number of patterns }
Score represents the arrangement of notes in a song; just a list of tracks and RowsPerPattern and Length (in patterns) to know the desired length of a song in rows. If any of the tracks is too short, all the notes outside the range should be just considered as holding the last note.
func (Score) FirstVoiceForTrack ¶
FirstVoiceForTrack returns the index of the first voice of given track. For example, if the Score has three tracks (0, 1 and 2), with 1, 3, 2 voices, respectively, then FirstVoiceForTrack(0) returns 0, FirstVoiceForTrack(1) returns 1 and FirstVoiceForTrack(2) returns 4. Essentially computes just the cumulative sum.
func (Score) LengthInRows ¶
LengthInRows returns just RowsPerPattern * Length, as the length is the length in the number of patterns.
type Song ¶
Song includes a Score (the arrangement of notes in the song in one or more tracks) and a Patch (the list of one or more instruments). Additionally, BPM and RowsPerBeat fields set how fast the song should be played. Currently, BPM is an integer as it offers already quite much granularity for controlling the playback speed, but this could be changed to a floating point in future if finer adjustments are necessary.
func (*Song) SamplesPerRow ¶
Assuming 44100 Hz playback speed, return the number of samples of each row of the song.
type Synth ¶
type Synth interface { // Render tries to fill a stereo signal buffer with sound from the // synthesizer, until either the buffer is full or a given number of // timesteps is advanced. Normally, 1 sample = 1 unit of time, but speed // modulations may change this. It returns the number of samples filled (in // stereo samples i.e. number of elements of AudioBuffer filled), the // number of sync outputs written, the number of time steps time advanced, // and a possible error. Render(buffer AudioBuffer, maxtime int) (sample int, time int, err error) // Update recompiles a patch, but should maintain as much as possible of its // state as reasonable. For example, filters should keep their state and // delaylines should keep their content. Every change in the Patch triggers // an Update and if the Patch would be started fresh every time, it would // lead to very choppy audio. Update(patch Patch, bpm int) error // Trigger triggers a note for a given voice. Called between synth.Renders. Trigger(voice int, note byte) // Release releases the currently playing note for a given voice. Called // between synth.Renders. Release(voice int) }
Synth represents a state of a synthesizer, compiled from a Patch.
type Synther ¶ added in v0.3.0
Synther compiles a given Patch into a Synth, throwing errors if the Patch is malformed.
type Track ¶
type Track struct { // NumVoices is the number of voices this track triggers, cycling through // the voices. When this track triggers a new voice, the previous should be // released. NumVoices int // Effect hints the GUI if this is more of an effect track than a note // track: if true, e.g. the GUI can display the values as hexadecimals // instead of note values. Effect bool `yaml:",omitempty"` // Order is a list telling which pattern comes in which order in the song in // this track. Order Order `yaml:",flow"` // Patterns is a list of Patterns for this track. Patterns []Pattern `yaml:",flow"` }
Track represents the patterns and orderlist for each track. Note that each track has its own patterns, so one track cannot use another tracks patterns. This makes the data more intuitive to humans, as the reusing of patterns over tracks is a rather rare occurence. However, the compiler will put all the patterns in one global table (identical patterns only appearing once), to optimize the runtime code.
type Unit ¶
type Unit struct { // Type is the type of the unit, e.g. "add","oscillator" or "envelope". // Always in lowercase. "" type should be ignored, no invalid types should // be used. Type string `yaml:",omitempty"` // ID should be a unique ID for this unit, used by SEND units to target // specific units. ID = 0 means that no ID has been given to a unit and thus // cannot be targeted by SENDs. When possible, units that are not targeted // by any SENDs should be cleaned from having IDs, e.g. to keep the exported // data clean. ID int `yaml:",omitempty"` // Parameters is a map[string]int of parameters of a unit. For example, for // an oscillator, unit.Type == "oscillator" and unit.Parameters["attack"] // could be 64. Most parameters are either limites to 0 and 1 (e.g. stereo // parameters) or between 0 and 128, inclusive. Parameters map[string]int `yaml:",flow"` // VarArgs is a list containing the variable number arguments that some // units require, most notably the DELAY units. For example, for a DELAY // unit, VarArgs is the delaytimes, in samples, of the different delaylines // in the unit. VarArgs []int `yaml:",flow,omitempty"` }
Unit is e.g. a filter, oscillator, envelope and its parameters
func (*Unit) StackChange ¶
StackChange returns how this unit will affect the signal stack. "pop" and "addp" and such will consume the topmost signal, and thus return -1 (or -2, if the unit is a stereo unit). On the other hand, "oscillator" and "envelope" will produce a signal, and thus return 1 (or 2, if the unit is a stereo unit). Effects that just change the topmost signal and will not change the number of signals on the stack and thus return 0.
type UnitParameter ¶
type UnitParameter struct { Name string // thould be found with this name in the Unit.Parameters map MinValue int // minimum value of the parameter, inclusive MaxValue int // maximum value of the parameter, inclusive CanSet bool // if this parameter can be set before hand i.e. through the gui CanModulate bool // if this parameter can be modulated i.e. has a port number in "send" unit }
UnitParameter documents one parameter that an unit takes
Directories ¶
Path | Synopsis |
---|---|
Package tracker contains the data model for the Sointu tracker GUI.
|
Package tracker contains the data model for the Sointu tracker GUI. |
Package vm implements a virtual machine based synthesizer that runs Sointu bytecode, and methods to convert patches into bytecode.
|
Package vm implements a virtual machine based synthesizer that runs Sointu bytecode, and methods to convert patches into bytecode. |