Documentation ¶
Overview ¶
Package mix implements golang audio sequencer.
Demo:
go run examples/main.go | aplay
Example ¶
package main import ( "github.com/kikht/mix" "github.com/kikht/mix/sox" "os" ) func main() { const ( sampleRate = 44100 tempo = 58 bars = 4 whole = sampleRate * 60 * 4 / tempo length = bars * whole ) sess := mix.NewSession(sampleRate) sess.SetOutput(os.Stdout) // It's only example. Handle your errors properly! kick, _ := sox.Load("examples/audio/kick.ogg") snare, _ := sox.Load("examples/audio/snare.ogg") hat, _ := sox.Load("examples/audio/hat.ogg") crash, _ := sox.Load("examples/audio/crash.ogg") guitar, _ := sox.Load("examples/audio/guitar.ogg") drums := mix.NewSession(sampleRate) drums.AddRegion(mix.Region{Source: crash, Begin: 0, Volume: 0.7, FadeOut: crash.Length()}) for h := mix.Tz(whole / 16); h < whole; h += whole / 16 { drums.AddRegion(mix.Region{Source: hat, Begin: h, Volume: 0.5, Pan: -0.3}) } kickPos := [...]mix.Tz{0, whole * 7 / 16, whole * 9 / 16} for _, k := range kickPos { drums.AddRegion(mix.Region{Source: kick, Begin: k, Volume: 1}) } snarePos := [...]mix.Tz{whole / 4, whole * 3 / 4} for _, s := range snarePos { drums.AddRegion(mix.Region{Source: snare, Begin: s, Volume: 1, Pan: 0.1}) } sess.AddRegion(mix.Region{Source: drums, Begin: 0, Volume: 1, FadeIn: whole}) for b := mix.Tz(whole); b < (bars-1)*whole; b += whole { sess.AddRegion(mix.Region{Source: drums, Begin: b, Volume: 1}) } sess.AddRegion(mix.Region{Source: drums, Begin: (bars - 1) * whole, Volume: 1, FadeOut: whole}) sess.AddRegion(mix.Region{Source: guitar, Begin: 0, Volume: 1, FadeIn: whole}) sess.AddRegion(mix.Region{Source: guitar, Begin: 2 * whole, Volume: 1, FadeOut: whole}) for i := 0; i < bars; i++ { sess.Play(whole) } }
Output:
Index ¶
- func PanMonoGain(pan float32) (l, r float32)
- func PanStereoGain(pan float32) (l2l, l2r, r2l, r2r float32)
- func SourceDuration(s Source) time.Duration
- type Buffer
- func (src Buffer) Clone() Buffer
- func (dst Buffer) CopyGain(src Buffer, gain float32)
- func (dst Buffer) Gain(gain float32)
- func (dst Buffer) LinearRamp(initial, target float32)
- func (dst Buffer) Mix(src Buffer)
- func (dst Buffer) MixGain(src Buffer, gain float32)
- func (dst Buffer) MixSqrtRamp(src Buffer, initial, target float32)
- func (dst Buffer) SqrtRamp(initial, target float32)
- func (dst Buffer) Zero()
- type MemSource
- type Player
- type PlayerState
- type Region
- type Session
- func (s *Session) AddRegion(r Region) error
- func (s *Session) Clone() Source
- func (s *Session) DurationToTz(d time.Duration) Tz
- func (s *Session) Length() Tz
- func (s *Session) NumChannels() int
- func (s *Session) Play(length Tz) error
- func (s *Session) Position() Tz
- func (s *Session) SampleRate() Tz
- func (s *Session) Samples(channel int, offset, length Tz) Buffer
- func (s *Session) SetOutput(output io.Writer)
- func (s *Session) SetPosition(pos Tz)
- type Source
- type SourceMutator
- type SourceMutatorFunc
- type SwitchPlayer
- type Tz
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func PanMonoGain ¶
func PanStereoGain ¶
Some useful info about panning in Ardour: http://lists.project-wombat.org/pipermail/ardour-dev-ardour.org/2005-August/009449.html Details of sincos implementation in golang: https://groups.google.com/forum/#!topic/golang-dev/gFJDX3mnjQU Anyway it's better to cache results of this in preparedRegion struct
func SourceDuration ¶
Duration returns Length() of Source as time.Duration according to its SampleRate()
Types ¶
type Buffer ¶
type Buffer []float32
Buffer of audio data.
func (Buffer) LinearRamp ¶
LinearRamp scales dst with linearly changing gain from initial to target.
func (Buffer) MixSqrtRamp ¶
MixSqrtRamp puts sum of src with SqrtRamp gain and dst into dst.
type MemSource ¶
MemSource is a Source that holds all necessary data in memory.
func (MemSource) NumChannels ¶
NumChannels returns number of channels in MemSource.
func (MemSource) SampleRate ¶
SampleRate returns number of samples per second in MemSource.
type Player ¶
type Player interface { PlayerState Play(source Source) }
type PlayerState ¶
type Region ¶
type Region struct { Source Source // Audio to play. Begin Tz // Time to begin playing in session samples. Offset, Length Tz // Offset and Length in Source that will be played. Volume, Pan float32 // Volume gain and stereo panning. FadeIn, FadeOut Tz // Length of fades. }
Region defines where and how Source audio (or its part) will be played.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session mixes collection of Regions. Output is done in 32-bit float WAV. Session implements Source, so it could be nested.
func NewSession ¶
NewSession creates Session with given sampleRate.
func (*Session) Clone ¶
Returns shallow copy of Session. Sources that are used in regions are not cloned.
func (*Session) DurationToTz ¶
DurationToTz converts time.Duration to number of samples with Session sample rate.
func (*Session) NumChannels ¶
NumChannels returns number of channels in Session
func (*Session) Play ¶
Play mixes length samples, writes them to output and advances currernt position by length.
func (*Session) SampleRate ¶
SampleRate returns sample rate of Session.
func (*Session) SetPosition ¶
SetPosition sets current Session position.
type Source ¶
type Source interface { // Samples may return internal buffer. // You must Clone first, if you plan to modify it. Samples(channel int, offset, length Tz) Buffer SampleRate() Tz NumChannels() int Length() Tz // Creates immutable read-only copy of Source Clone() Source }
Source is the interface that represents audio data.
type SourceMutator ¶
type SourceMutatorFunc ¶
type SwitchPlayer ¶
type SwitchPlayer interface { PlayerState Switch(mutator SourceMutator) }