mix

package module
v0.0.0-...-83c7bd8 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2019 License: MIT Imports: 13 Imported by: 0

README

Mix

GoDoc Build Status Go Report Card

Audio mixer for golang. Inspired by https://github.com/go-mix/mix but has following differences:

  • All audio operations are vectorized.
  • No forced compression on whole mix. Optional compressors are planned, but not implemented yet.
  • Fade-in & fade-out on audio regions.
  • Float32 for audio samples - more than enough for audio.
  • Most time calculations are in number of samples. Converters to time.Duration are provided.

Demo

go run examples/main.go | aplay

Dependencies

  • github.com/rkusa/gm/math32 - math functions for float32
  • github.com/krig/go-sox - cgo bindings to SoX for audio input
  • github.com/xthexder/go-jack - cgo bindings to jackd
  • sfml package requires csfml 2.4

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func PanMonoGain

func PanMonoGain(pan float32) (l, r float32)

func PanStereoGain

func PanStereoGain(pan float32) (l2l, l2r, r2l, r2r float32)

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

func SourceDuration(s Source) time.Duration

Duration returns Length() of Source as time.Duration according to its SampleRate()

Types

type Buffer

type Buffer []float32

Buffer of audio data.

func NewBuffer

func NewBuffer(length Tz) Buffer

NewBuffer creates buffer of length samples.

func (Buffer) Clone

func (src Buffer) Clone() Buffer

Clone buffer with contents.

func (Buffer) CopyGain

func (dst Buffer) CopyGain(src Buffer, gain float32)

CopyGain copies samples from src into dst scaling by gain.

func (Buffer) Gain

func (dst Buffer) Gain(gain float32)

Gain scales all samples by gain.

func (Buffer) LinearRamp

func (dst Buffer) LinearRamp(initial, target float32)

LinearRamp scales dst with linearly changing gain from initial to target.

func (Buffer) Mix

func (dst Buffer) Mix(src Buffer)

Mix puts sum of src and dst into dst.

func (Buffer) MixGain

func (dst Buffer) MixGain(src Buffer, gain float32)

MixGain puts sum of src scaled by gain and dst into dst.

func (Buffer) MixSqrtRamp

func (dst Buffer) MixSqrtRamp(src Buffer, initial, target float32)

MixSqrtRamp puts sum of src with SqrtRamp gain and dst into dst.

func (Buffer) SqrtRamp

func (dst Buffer) SqrtRamp(initial, target float32)

SqrtRamp scales dst with "sqrt-linear" changing gain from sqrt(initial) to sqrt(target). Useful for equal-power crossfade.

func (Buffer) Zero

func (dst Buffer) Zero()

Zero fills buffer with silence.

type MemSource

type MemSource struct {
	Data []Buffer
	Rate Tz
}

MemSource is a Source that holds all necessary data in memory.

func (MemSource) Clone

func (s MemSource) Clone() Source

func (MemSource) Length

func (s MemSource) Length() Tz

Length returns number of samples in MemSource.

func (MemSource) NumChannels

func (s MemSource) NumChannels() int

NumChannels returns number of channels in MemSource.

func (MemSource) SampleRate

func (s MemSource) SampleRate() Tz

SampleRate returns number of samples per second in MemSource.

func (MemSource) Samples

func (s MemSource) Samples(channel int, offset, length Tz) Buffer

Samples returns Buffer holding length samples from channel starting at offset. Will return internal buffer. Copy it, if you want to modify.

type Player

type Player interface {
	PlayerState
	Play(source Source)
}

type PlayerState

type PlayerState interface {
	SampleRate() Tz
	ChunkSize() Tz
}

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

func NewSession(sampleRate Tz) *Session

NewSession creates Session with given sampleRate.

func (*Session) AddRegion

func (s *Session) AddRegion(r Region) error

AddRegion adds region to the Session mix.

func (*Session) Clone

func (s *Session) Clone() Source

Returns shallow copy of Session. Sources that are used in regions are not cloned.

func (*Session) DurationToTz

func (s *Session) DurationToTz(d time.Duration) Tz

DurationToTz converts time.Duration to number of samples with Session sample rate.

func (*Session) Length

func (s *Session) Length() Tz

Length returns end of last region in Session

func (*Session) NumChannels

func (s *Session) NumChannels() int

NumChannels returns number of channels in Session

func (*Session) Play

func (s *Session) Play(length Tz) error

Play mixes length samples, writes them to output and advances currernt position by length.

func (*Session) Position

func (s *Session) Position() Tz

Position returns current Session position.

func (*Session) SampleRate

func (s *Session) SampleRate() Tz

SampleRate returns sample rate of Session.

func (*Session) Samples

func (s *Session) Samples(channel int, offset, length Tz) Buffer

func (*Session) SetOutput

func (s *Session) SetOutput(output io.Writer)

SetOutput redirects session output to given io.Writer.

func (*Session) SetPosition

func (s *Session) SetPosition(pos Tz)

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 SourceMutator interface {
	Mutate(cur Source, pos Tz) Source
}

type SourceMutatorFunc

type SourceMutatorFunc func(cur Source, pos Tz) Source

func (SourceMutatorFunc) Mutate

func (f SourceMutatorFunc) Mutate(cur Source, pos Tz) Source

type SwitchPlayer

type SwitchPlayer interface {
	PlayerState
	Switch(mutator SourceMutator)
}

type Tz

type Tz int64

Tz represents time in number of samples

func DurationToTz

func DurationToTz(d time.Duration, sampleRate Tz) Tz

DurationToTz converts time.Duration to number of samples for specified sample rate.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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