Documentation ¶
Overview ¶
Package snd provides methods and types for sound processing and synthesis.
Audio hardware is accessed via package snd/al which in turn manages the dispatching of sound synthesis via golang.org/x/mobile/audio/al. Start the dispatcher as follows:
const buffers = 1 if err := al.OpenDevice(buffers); err != nil { log.Fatal(err) } al.Start()
Once running, add a source for sound synthesis. For example:
osc := snd.NewOscil(snd.Sine(), 440, nil) al.AddSource(osc)
This results in a 440Hz tone being played back through the audio hardware.
Synthesis types in package snd implement the Sound interface and many type methods accept a Sound argument that can affect sampling. For example, one may modulate an oscillator by passing in a third argument to NewOscil.
sine := snd.Sine() mod := snd.NewOscil(sine, 2, nil) osc := snd.NewOscil(sine, 440, mod)
The above results in a lower frequency sound that may require decent speakers to hear properly.
Signals ¶
Note the sine argument in the previous example. There are two conceptual types of sounds, ContinuousFunc and Discrete. ContinuousFunc represents an indefinite series over time. Discrete is the sampling of a ContinuousFunc over an interval. Functions such as Sine, Triangle, and Square (non-exhaustive) return Discretes created by sampling a ContinuousFunc such as SineFunc, TriangleFunc, and SquareFunc.
Discrete signals serve as a lookup table to efficiently synthesize sound. A Discrete is a []float64 and can sample any ContinuousFunc, within the package or user defined which is a func(t float64) float64.
Discrete signals may be further modified with intent or arbitrarily. For example, Discrete.Add(Discrete, int) performs additive synthesis and is used by functions such as SquareSynthesis(int) to return an approximation of a square signal based on a sinusoidal.
Time Approximation ¶
Functions that take a time.Duration argument approximate the value to the closest number of frames. For example, if sample rate is 44.1kHz and duration is 75ms, this results in the argument representing 3307 frames which is approximately 74.99ms.
Index ¶
- Constants
- func Dtof(d time.Duration, sr float64) (f int)
- func EqualTempermantFunc(ns Notes, tones int, freq float64, pos int)
- func ExpDrive() signal.Discrete
- func Ftod(f int, sr float64) (d time.Duration)
- func LinearDrive() signal.Discrete
- type ADSR
- type BPM
- type ByWT
- type Comb
- func (sd Comb) At(t float64) float64
- func (sd Comb) Channels() int
- func (sd Comb) Index(i int) float64
- func (sd Comb) Inputs() []Sound
- func (sd Comb) Interp(t float64) float64
- func (sd Comb) IsOff() bool
- func (sd Comb) Off()
- func (sd Comb) On()
- func (cmb *Comb) Prepare(uint64)
- func (sd Comb) SampleRate() float64
- func (sd Comb) Samples() signal.Discrete
- type Damp
- func (sd Damp) At(t float64) float64
- func (sd Damp) Channels() int
- func (sd Damp) Index(i int) float64
- func (sd Damp) Inputs() []Sound
- func (sd Damp) Interp(t float64) float64
- func (sd Damp) IsOff() bool
- func (sd Damp) Off()
- func (sd Damp) On()
- func (dmp *Damp) Prepare(uint64)
- func (sd Damp) SampleRate() float64
- func (sd Damp) Samples() signal.Discrete
- type Decibel
- type Delay
- func (sd Delay) At(t float64) float64
- func (sd Delay) Channels() int
- func (sd Delay) Index(i int) float64
- func (sd Delay) Inputs() []Sound
- func (sd Delay) Interp(t float64) float64
- func (sd Delay) IsOff() bool
- func (sd Delay) Off()
- func (sd Delay) On()
- func (dly *Delay) Prepare(uint64)
- func (sd Delay) SampleRate() float64
- func (sd Delay) Samples() signal.Discrete
- type Dispatcher
- type Drive
- func (sd Drive) At(t float64) float64
- func (sd Drive) Channels() int
- func (sd Drive) Index(i int) float64
- func (sd Drive) Inputs() []Sound
- func (sd Drive) Interp(t float64) float64
- func (sd Drive) IsOff() bool
- func (sd Drive) Off()
- func (sd Drive) On()
- func (drv *Drive) Prepare(uint64)
- func (sd Drive) SampleRate() float64
- func (sd Drive) Samples() signal.Discrete
- type Freeze
- func (sd Freeze) At(t float64) float64
- func (sd Freeze) Channels() int
- func (sd Freeze) Index(i int) float64
- func (sd Freeze) Inputs() []Sound
- func (sd Freeze) Interp(t float64) float64
- func (sd Freeze) IsOff() bool
- func (frz *Freeze) Off()
- func (sd Freeze) On()
- func (frz *Freeze) Prepare(uint64)
- func (frz *Freeze) Restart()
- func (sd Freeze) SampleRate() float64
- func (sd Freeze) Samples() signal.Discrete
- type Gain
- func (sd Gain) At(t float64) float64
- func (sd Gain) Channels() int
- func (sd Gain) Index(i int) float64
- func (sd Gain) Inputs() []Sound
- func (sd Gain) Interp(t float64) float64
- func (sd Gain) IsOff() bool
- func (sd Gain) Off()
- func (sd Gain) On()
- func (gn *Gain) Prepare(uint64)
- func (sd Gain) SampleRate() float64
- func (sd Gain) Samples() signal.Discrete
- func (gn *Gain) SetAmp(a float64)
- type Hertz
- type Input
- type Instrument
- func (sd Instrument) At(t float64) float64
- func (sd Instrument) Channels() int
- func (sd Instrument) Index(i int) float64
- func (sd Instrument) Inputs() []Sound
- func (sd Instrument) Interp(t float64) float64
- func (sd Instrument) IsOff() bool
- func (sd Instrument) Off()
- func (nst *Instrument) OffIn(d time.Duration)
- func (nst *Instrument) On()
- func (nst *Instrument) Prepare(uint64)
- func (sd Instrument) SampleRate() float64
- func (sd Instrument) Samples() signal.Discrete
- type Loop
- func (sd Loop) At(t float64) float64
- func (sd Loop) Channels() int
- func (sd Loop) Index(i int) float64
- func (sd Loop) Inputs() []Sound
- func (sd Loop) Interp(t float64) float64
- func (sd Loop) IsOff() bool
- func (sd Loop) Off()
- func (sd Loop) On()
- func (lp *Loop) Prepare(tc uint64)
- func (lp *Loop) Record()
- func (lp *Loop) Recording() bool
- func (sd Loop) SampleRate() float64
- func (sd Loop) Samples() signal.Discrete
- func (lp *Loop) SetBPM(bpm BPM)
- func (lp *Loop) Stop()
- func (lp *Loop) Syncing() bool
- type LowPass
- func (sd LowPass) At(t float64) float64
- func (sd LowPass) Channels() int
- func (sd LowPass) Index(i int) float64
- func (sd LowPass) Inputs() []Sound
- func (sd LowPass) Interp(t float64) float64
- func (sd LowPass) IsOff() bool
- func (sd LowPass) Off()
- func (sd LowPass) On()
- func (lp *LowPass) Passthrough() bool
- func (lp *LowPass) Prepare(uint64)
- func (sd LowPass) SampleRate() float64
- func (sd LowPass) Samples() signal.Discrete
- func (lp *LowPass) SetPassthrough(b bool)
- type Mixer
- func (mix *Mixer) Append(s ...Sound)
- func (sd Mixer) At(t float64) float64
- func (sd Mixer) Channels() int
- func (mix *Mixer) Empty()
- func (sd Mixer) Index(i int) float64
- func (mix *Mixer) Inputs() []Sound
- func (sd Mixer) Interp(t float64) float64
- func (sd Mixer) IsOff() bool
- func (sd Mixer) Off()
- func (sd Mixer) On()
- func (mix *Mixer) Prepare(uint64)
- func (sd Mixer) SampleRate() float64
- func (sd Mixer) Samples() signal.Discrete
- type Notes
- type NotesFunc
- type Oscil
- func (sd Oscil) At(t float64) float64
- func (sd Oscil) Channels() int
- func (sd Oscil) Index(i int) float64
- func (osc *Oscil) Inputs() []Sound
- func (sd Oscil) Interp(t float64) float64
- func (sd Oscil) IsOff() bool
- func (sd Oscil) Off()
- func (sd Oscil) On()
- func (osc *Oscil) Prepare(tc uint64)
- func (sd Oscil) SampleRate() float64
- func (sd Oscil) Samples() signal.Discrete
- func (osc *Oscil) SetAmp(fac float64, mod Sound)
- func (osc *Oscil) SetFreq(hz float64, mod Sound)
- func (osc *Oscil) SetPhase(mod Sound)
- type Pan
- func (sd Pan) At(t float64) float64
- func (sd Pan) Channels() int
- func (sd Pan) Index(i int) float64
- func (sd Pan) Inputs() []Sound
- func (sd Pan) Interp(t float64) float64
- func (sd Pan) IsOff() bool
- func (sd Pan) Off()
- func (sd Pan) On()
- func (pan *Pan) Prepare(uint64)
- func (sd Pan) SampleRate() float64
- func (sd Pan) Samples() signal.Discrete
- func (pan *Pan) SetAmount(xf float64)
- type Player
- type Ring
- func (sd Ring) At(t float64) float64
- func (sd Ring) Channels() int
- func (sd Ring) Index(i int) float64
- func (ng *Ring) Inputs() []Sound
- func (sd Ring) Interp(t float64) float64
- func (sd Ring) IsOff() bool
- func (sd Ring) Off()
- func (sd Ring) On()
- func (ng *Ring) Prepare(uint64)
- func (sd Ring) SampleRate() float64
- func (sd Ring) Samples() signal.Discrete
- type Sound
- type Tap
- func (sd Tap) At(t float64) float64
- func (sd Tap) Channels() int
- func (sd Tap) Index(i int) float64
- func (sd Tap) Inputs() []Sound
- func (sd Tap) Interp(t float64) float64
- func (sd Tap) IsOff() bool
- func (sd Tap) Off()
- func (sd Tap) On()
- func (tap *Tap) Prepare(uint64)
- func (sd Tap) SampleRate() float64
- func (sd Tap) Samples() signal.Discrete
Constants ¶
const ( DefaultSampleRate float64 = 48000 // 44100 DefaultSampleBitDepth = 16 // TODO not currently used for anything DefaultBufferLen = 256 DefaultAmpFac float64 = 0.31622776601683794 // -10dB )
const DefaultNotesLen = 128
Variables ¶
This section is empty.
Functions ¶
func EqualTempermantFunc ¶
EqualTempermantFunc evaluates notes as an octave containing n tones at an equal distance on a logarithmic scale. The reference freq and pos is used to find all other values.
func LinearDrive ¶
Types ¶
type ADSR ¶
type ADSR struct {
// contains filtered or unexported fields
}
TODO reimplement sustain functionality
func (*ADSR) Release ¶
Release immediately releases envelope from anywhere and starts release period.
type Comb ¶
type Comb struct {
// contains filtered or unexported fields
}
Comb adds a delayed version of a signal onto itself.
func (Comb) SampleRate ¶
func (sd Comb) SampleRate() float64
type Damp ¶
type Damp struct {
// contains filtered or unexported fields
}
func (Damp) SampleRate ¶
func (sd Damp) SampleRate() float64
type Delay ¶
type Delay struct {
// contains filtered or unexported fields
}
Delay represents a signal delayed by a given duration.
func (Delay) SampleRate ¶
func (sd Delay) SampleRate() float64
type Dispatcher ¶
func (*Dispatcher) Dispatch ¶
func (dp *Dispatcher) Dispatch(tc uint64, inps ...*Input)
Dispatch blocks until all inputs are prepared.
type Drive ¶
type Drive struct {
// contains filtered or unexported fields
}
func (Drive) SampleRate ¶
func (sd Drive) SampleRate() float64
type Freeze ¶
type Freeze struct {
// contains filtered or unexported fields
}
func (Freeze) SampleRate ¶
func (sd Freeze) SampleRate() float64
type Gain ¶
type Gain struct {
// contains filtered or unexported fields
}
func (Gain) SampleRate ¶
func (sd Gain) SampleRate() float64
type Hertz ¶
type Hertz float64
Hertz is defined as cycles per second and is synonymous with frequency.
func (Hertz) Angular ¶
Angular returns the angular frequency as 2 * pi * hz and is synonymous with radians.
func (Hertz) Normalized ¶
Normalized returns the angular frequency of hz divided by the sample rate sr.
type Instrument ¶
type Instrument struct {
// contains filtered or unexported fields
}
func NewInstrument ¶
func NewInstrument(in Sound) *Instrument
func (*Instrument) OffIn ¶
func (nst *Instrument) OffIn(d time.Duration)
func (*Instrument) On ¶
func (nst *Instrument) On()
func (*Instrument) Prepare ¶
func (nst *Instrument) Prepare(uint64)
func (Instrument) SampleRate ¶
func (sd Instrument) SampleRate() float64
type Loop ¶
type Loop struct {
// contains filtered or unexported fields
}
Loop records a signal by a given duration, repeating the recording in subsequent playback.
TODO cross-fade
func NewLoopFrames ¶
NewLoopFrames return a Loop with sample buffer of length nframes.
func (Loop) SampleRate ¶
func (sd Loop) SampleRate() float64
type LowPass ¶
type LowPass struct {
// contains filtered or unexported fields
}
LowPass is a 3rd order IIR filter.
Recursive implementation of the Gaussian filter.
func NewLowPass ¶
func (*LowPass) Passthrough ¶
func (LowPass) SampleRate ¶
func (sd LowPass) SampleRate() float64
func (*LowPass) SetPassthrough ¶
type Mixer ¶
type Mixer struct {
// contains filtered or unexported fields
}
TODO should mixer be stereo out? TODO perhaps this class is unnecessary, any sound could be a mixer if you can set multiple inputs, but might get confusing. TODO consider embedding Gain type
func (Mixer) SampleRate ¶
func (sd Mixer) SampleRate() float64
type Notes ¶
type Notes []float64
Notes is a collection of note function evaluations.
func EqualTempermant ¶
EqualTempermant is a helper function for returning an evaluated Notes.
type Oscil ¶
type Oscil struct {
// contains filtered or unexported fields
}
func (Oscil) SampleRate ¶
func (sd Oscil) SampleRate() float64
type Pan ¶
type Pan struct {
// contains filtered or unexported fields
}
func (Pan) SampleRate ¶
func (sd Pan) SampleRate() float64
type Player ¶
type Player struct {
// contains filtered or unexported fields
}
func (*Player) SampleRate ¶
type Ring ¶
type Ring struct {
// contains filtered or unexported fields
}
Ring modulator
func (Ring) SampleRate ¶
func (sd Ring) SampleRate() float64
type Sound ¶
type Sound interface { // Channels returns the frame size in samples of the internal buffer. Channels() int // SampleRate returns the number of digital samples of sound pressure per second. SampleRate() float64 // Prepare is when a sound should prepare sample frames. Prepare(uint64) // Inputs should return all inputs a Sound wants discovered by a dispatcher. // TODO consider other methods for handling this, check book multidimensional data structures Inputs() []Sound // Samples returns prepared samples slice. // // TODO maybe ditch this, point of architecture is you can't mess // with an input's output but a slice exposes that. Or, discourage // use by making a copy of data. // TODO rename to Data()? So, Buffer.Data() Samples() signal.Discrete Interp(t float64) float64 At(t float64) float64 Index(i int) float64 }
TODO rename as Buffer? TODO what about handling []byte instead of []float? Sound represents a type capable of producing sound data.
type Tap ¶
type Tap struct {
// contains filtered or unexported fields
}
Tap is a tapped delay line, essentially a shorter delay within a larger one.
TODO consider some type of method on Delay instead of a separate type. For example, Tap intentionally does not expose dly via Inputs() so why is it its own type? Conversely, that'd make Delay a mixer of sorts.
func (Tap) SampleRate ¶
func (sd Tap) SampleRate() float64